I spent couple hours browsing the internet and searching for some solution how to capture desktop (or window) and send it to OpenCv VideoCapture so that I can do some computer vision magic on it.
After doing my research the only solution that I was able to think of is starting stream with desktopCapturer and passing the stream to opencv library.
I have this code:
const { desktopCapturer } = require('electron');
var cv = require('electron').remote.require('opencv4nodejs');
...some setup...
navigator.mediaDevices.getUserMedia({
audio: false,
video: {
mandatory: {
chromeMediaSource: 'desktop',
chromeMediaSourceId: source.id,
minWidth: 640,
maxWidth: 640,
minHeight: 320,
maxHeight: 320,
},
},
})
.then((stream) => {
console.log('stream ', stream);
const videoUrl = URL.createObjectURL(stream);
console.log('videoUrl', videoUrl);
const capturedVideo = new cv.VideoCapture(videoUrl);
console.log('captured video', capturedVideo);
})
.catch((error) => console.error(error));
But I get following error:
Following piece of code actually handles the conversion between browser desktop capturer and nodejs for opencv and other libraries:
}).then((stream) => {
const video = document.createElement('video');
video.srcObject = stream;
video.onloadedmetadata = () => {
video.play();
setInterval(() => {
const canvas = document.createElement('canvas');
canvas.getContext('2d').drawImage(video, 0, 0, 800, 800);
canvas.toBlob(blob => {
toBuffer(blob, function (err, buffer) {
if (err) throw err;
// do some magic with buffer
});
});
}, 40);
};
Related
I'm trying to use Charts.js on an AWS Lambda function to create a chart image (png).
However, for some reason it plots the axes, but no data.
this is my code:
export const plotData = (values: number[]): Buffer | null => {
const canvas = createCanvas(800, 600);
let ctx: ChartItem = canvas as unknown as ChartItem;
const plugin: Plugin = {
id: "customCanvasBackgroundColor",
beforeDraw: (chart: any, _args: any, options: any) => {
const { ctx: context } = chart;
context.save();
context.globalCompositeOperation = "destination-over";
context.fillStyle = options.color || "#99ffff";
context.fillRect(0, 0, chart.width, chart.height);
context.restore();
},
};
const chart = new Chart(ctx, {
type: "line",
data: {
datasets: [
{
label: "ph",
data: values.map((y) => ({
y,
t: new Date(),
})),
borderWidth: 2,
borderColor: "red",
backgroundColor: "rgb(255, 0, 0, 0.5)",
},
],
},
options: {
responsive: false,
animation: false,
scales: {
y: {
beginAtZero: true,
},
},
plugins: {
legend: {
position: "top",
},
title: {
display: true,
text: "TEstuibg",
},
customCanvasBackgroundColor: {
color: "rgba(255,255,255, 1)",
},
},
},
plugins: [plugin],
});
// chart.draw();
chart.update();
return canvas.toBuffer("image/png");
};
And this is what it is rendering when I call plotData([100, 200, 300, 400, 500, 1600]):
I am already disabling animations and responsiveness. Is there something else I need to do?
I would create the image on the onComplete event, than everything should be visible, atleast this works in browsers.
from the documentation: "...The animation configuration provides callbacks which are useful for synchronizing an external draw to the chart animation....", but works surely for your image creating process. link to documentation
...
options: {
animation:{
duration: 0, // "no" animation
onComplete: () => {
...
// create image
...
}
}
}
...
Ofcourse: in this case your function plotData would have to be async or pass a callback function for when the event onComplete fires.
I have made a script which renders a graph with multiple lines and dates, I can run the script once perfectly fine but when trying to run it a second time it give an error: "Error: This method is not implemented: Check that a complete date adapter is provided.". I couldn't find anything about it that fits my situation.
[enter image description here][1]const {
MessageEmbed,
MessageAttachment
} = require("discord.js");
const {
ChartJSNodeCanvas
} = require("chartjs-node-canvas");
const canvas = require('canvas'); // important
var groupArray = require('group-array');
const fs = require('fs')
const axios = require('axios');
require('chartjs-adapter-moment')
const generateCanva = async (labels, datas, names, interaction) => {
const renderer = new ChartJSNodeCanvas({
width: 800,
height: 300,
backgroundColour: "white"
});
parsedLabels = []
if (Array.isArray(labels[0])) {
for (alabel in labels) {
parsedLabels = labels[alabel].reduce(
(acc, item) => {
return acc.includes(item) ? acc : [...acc, item]
},
[...parsedLabels]
)
}
} else {
parsedLabels = labels
}
parsedLabels = parsedLabels.sort(function (a, b) {
return new Date(b) - new Date(a);
}).reverse();
parsedLabelsDate = []
for (x in parsedLabels) {
parsedLabelsDate.push(new Date(parsedLabels[x]))
}
chartObject = {
type: "line", // Show a bar chart
backgroundColor: "rgb(255,255,255)",
options: {
scales: {
x: {
type: 'time',
}
}
},
data: {
labels: parsedLabelsDate,
datasets: [],
},
}
colors = ['rgb(240,128,128)', 'rgb(240,230,140)', 'rgb(152,251,152)', 'rgb(0,206,209)', 'rgb(135,206,250)', 'rgb(238,130,238)']
if (Array.isArray(labels[0])) {
for (var i in labels) {
parcedDatas = []
for (x in datas[i]) {
parcedDatas.push({
x: new Date(labels[i][x]),
y: datas[i][x]
})
}
dataset = {
label: names[i],
data: parcedDatas,
fill: false,
borderColor: colors[i],
tension: 0.1
}
console.log(dataset)
chartObject.data.datasets.push(dataset)
}
} else {
dataset = {
label: interaction.author.username,
data: datas,
fill: false,
borderColor: 'rgb(75, 192, 192)',
tension: 0.1
}
chartObject.data.datasets.push(dataset)
}
const image = await renderer.renderToBuffer(
// Build your graph passing option you want
chartObject
);
return new MessageAttachment(image, "graph.png");
};
Fixed the issue by moving:
const renderer = new ChartJSNodeCanvas({
width: 800,
height: 300,
backgroundColour: "white"
});
Outside of the function.
i am new to ionic4/angular4.i need to upload the profile pic to database.i wrote code but i don't know whether it is correct or not and when i am uploading it i am getting the above mentioned error. backed i am using Django and sorry for the bad indentation.i just beginner to programming.
.ts
async sendPictureToSomewhere() {
const fileuri = await this.getPicture();
const blobinfo = await this.b64toBlob(fileuri);
await this.upload(blobinfo);
alert("done");
}
async getPicture() {
const options: CameraOptions = {
quality: 100,
destinationType: this.camera.DestinationType.FILE_URI,
encodingType: this.camera.EncodingType.JPEG,
mediaType: this.camera.MediaType.PICTURE
// targetWidth: 200
};
let fileuri = await this.camera.getPicture(options);
return fileuri;
}
b64toBlob(_imagePath) {
return new Promise((resolve, reject) => {
let fileName = "";
this.file
.resolveLocalFilesystemUrl(_imagePath)
.then(fileEntry => {
let { name, nativeURL } = fileEntry;
// get the path..
let path = nativeURL.substring(0, nativeURL.lastIndexOf("/"));
console.log("path", path);
console.log("fileName", name);
fileName = name;
// we are provided the name, so now read the file into
// a buffer
return this.file.readAsArrayBuffer(path, name);
})
.then(buffer => {
// get the buffer and make a blob to be saved
let imgBlob = new Blob([buffer], {
type: "image/jpeg"
});
console.log(imgBlob.type, imgBlob.size);
resolve({
fileName,
imgBlob
});
})
.catch(e => reject(e));
});
}
upload(_Blobinfo) {
this.profileService.postInfluencerProfile(_Blobinfo, null,
null).subscribe(
response => {
console.log(response);
},
(error: MavinError) => {
if (error instanceof NotFoundError) {
alert("Not found");
} else {
console.log(error);
}
}
);
}
}
I am using cropperJS, and I am trying to use the setCropBoxData's function, but this does not works and Documentation gives not clearly (i think) examples how to use it. please, if someone can help, that would be amazing.
This is my function
function createCropper() {
data = new FormData();
var file = $('#file')[0].files[0];
$('#' + globalId).attr('src', window.URL.createObjectURL(file));
$('#img2').attr('src', window.URL.createObjectURL(file));
var image = document.getElementById('img2');
cropper = new Cropper(image, {
aspectRatio: Cropwidth / Cropheigh,
autoCropArea: 0.65,
restore: false,
center: false,
highlight: false,
cropBoxResizable: false,
toggleDragModeOnDblclick: false,
built: function () {
cropper.setCropBoxData({ width: "100", height: "100" });
}
});
cropper.crop();
}
I also tried:
function createCropper() {
data = new FormData();
var file = $('#file')[0].files[0];
$('#' + globalId).attr('src', window.URL.createObjectURL(file));
$('#img2').attr('src', window.URL.createObjectURL(file));
var image = document.getElementById('img2');
cropper = new Cropper(image, {
aspectRatio: Cropwidth / Cropheigh,
autoCropArea: 0.65,
restore: false,
center: false,
highlight: false,
cropBoxResizable: false,
toggleDragModeOnDblclick: false,
built: function () {
cropper.cropper("setCropBoxData", { width: "100", height: "100" });
}
});
cropper.crop();
}
thanks in advance
i solved it.. refer to my solution on this post here.. setting cropbox data
the setCropBoxData(), function did not work for me either, but after studying and
several trials, i found a way to initialize the width and height using the data property.
data:{
width: 240,
height: 507,
},
refer to the link to see my approach.
thank me later.
I am actually implementing a function to allow user to upload the photos from phone.
Is there any image compress plugin / library to recommended?
Notes: it is image compression, not image resizing.
Thanks a lot
Use the Ionic Native Camera function
There is a quality option ranging from 0-100. It will return a compressed image
const options: CameraOptions = {
quality: 50, // Try changing this
destinationType: this.camera.DestinationType.DATA_URL,
encodingType: this.camera.EncodingType.JPEG,
mediaType: this.camera.MediaType.PICTURE
}
this.camera.getPicture(options).then((imageData) => {
let base64Image = 'data:image/jpeg;base64,' + imageData;
}, (err) => {
// Handle error
});
Try following CameraOptions with ionic camera plugin.
const options: CameraOptions = {
quality: 20,
targetWidth: 600,
targetHeight: 600,
destinationType: this.camera.DestinationType.DATA_URL,
encodingType: this.camera.EncodingType.PNG,
mediaType: this.camera.MediaType.PICTURE,
sourceType: this.camera.PictureSourceType.PHOTOLIBRARY,
allowEdit: true //may not work with some deices
}
It is targetHeight and targetWidth doing the magic. :)
Answer referred from : Ionic image compress