我正在尝试从网络摄像头录制视频,然后使用 openCV.js(正确包含在我的 html 文件中)对该视频应用边缘检测过滤器。录音有效,我正在使用 WebRTC 进行录音。它给了我一个 blob 中的视频,我可以毫无问题地显示它。
这里是边缘检测函数的代码:
async function detectContours(inputBlob) {
console.trace("a");
const response = await fetch(URL.createObjectURL(inputBlob));
const blob = await response.blob();
const inputVideo = document.createElement("video");
inputVideo.src = URL.createObjectURL(blob);
await new Promise((resolve) => {
inputVideo.addEventListener("loadedmetadata", () => {
resolve();
});
inputVideo.load();
});
console.log("type de inputVideo : %o", typeof inputVideo);
console.log("vidéo d'entrée : %o * %o", inputVideo.height, inputVideo.width);
console.trace("b");
await new Promise((resolve) => {
inputVideo.addEventListener("canplaythrough", () => {
resolve();
});
inputVideo.load();
});
await inputVideo.play();
console.trace("c");
const outputCanvas = document.createElement("canvas");
outputCanvas.width = inputVideo.videoWidth;
outputCanvas.height = inputVideo.videoHeight;
const outputCtx = outputCanvas.getContext("2d");
console.trace("d");
outputCtx.drawImage(
inputVideo,
0,
0,
outputCanvas.width,
outputCanvas.height
);
console.trace("e");
const cvInput = cv.imread(outputCanvas);
const cvOutput = new cv.Mat();
console.trace("f");
cv.Canny(cvInput, cvOutput, 100, 200);
console.trace("g");
console.log(
"vidéo d'entrée : %o * %o",
inputVideo.videoHeight,
inputVideo.videoWidth
);
console.log("canvas de sortie : %o * %o", cvOutput.rows, cvOutput.cols);
console.log("%o bytes", cvOutput.data.length);
const outputImageData = new ImageData(
new Uint8ClampedArray(cvOutput.data),
cvOutput.cols,
cvOutput.rows / 4
);
console.trace("h");
const outputCanvas2 = document.createElement("canvas");
outputCanvas2.width = outputImageData.width;
outputCanvas2.height = outputImageData.height;
const outputCtx2 = outputCanvas2.getContext("2d");
outputCtx2.putImageData(outputImageData, 0, 0);
console.trace("i");
const outputBlob = await new Promise((resolve) =>
outputCanvas2.toBlob(resolve, "image/png")
);
console.trace("j");
URLvideoEdge = URL.createObjectURL(outputBlob);
blobVideoEdge = outputBlob;
console.trace("k");
}
这是我点击“停止录制”按钮时调用的函数代码:
async function stopRecording() {
console.trace("1");
//Recording the video
for (let track of stream.getTracks()) {
track.stop(); //when this event is triggered, function called display the video without any issue
}
console.trace("2");
// verifying blobVideoCouleur actually is an object
while (typeof blobVideoCouleur !== "object") {
await new Promise(resolve => setTimeout(resolve, 100)); // Pause 100ms
}
console.trace("3");
//Applying edge detection filter
await detectContours(blobVideoCouleur);
console.trace("4");
//Displaying filtered video
playBack.src = URLvideoEdge;
playBack.autoplay = true;
console.trace("5");
}
playBack
是一个全局变量,定义为播放录制视频的 html 视频元素
以防万一,这是执行此操作的函数,在我停止录制时调用:
recorder.onstop = () => { // Event triggered when I stop the recorder
const blob = new Blob(chunks, { //
type: 'video/webm' // Et il le fait en webm
})
chunks = [];
URLvideoCouleur = URL.createObjectURL(blob);
playBack = document.getElementById("playBack");
playBack.src = URLvideoCouleur;
playBack.controls = true;
blobVideoCouleur = blob;
}
好吧,我在使用 openCV.js 时遇到了很多问题,因为我以前从未使用过它,所以这就是为什么我的代码中有那么多
console.trace
,因为我可以看到代码哪里有错误。我在这段代码中找到的最后一个“解决方案”是在这里除以 4:
const outputImageData = new ImageData(
new Uint8ClampedArray(cvOutput.data),
cvOutput.cols,
cvOutput.rows / 4
);
Cause ImageData 正在寻找等于 in_video_height*in_video_width*4 尺寸乘以 4“颜色”(RGBA)的数据长度,但实际上我只是在应用边缘检测过滤器后有一层,黑色或白色。
所以从现在开始,代码在控制台中没有中断或错误地运行,但最终的行为并不像预期的那样。我的视频播放器不显示过滤视频而不是“正常”视频,它甚至不是视频而是黑色块,带有控件,但无用,因为视频的持续时间为 0。 (见画面)
好吧...因为我没有控制台反馈,我只是被困住了,我不再知道我能做些什么来获得这个过滤后的视频。你有什么建议吗? 此外,我不禁认为这个功能
detectContours
是一个巨大的gasworks,没有更简单的方法可以在js中对我的视频应用边缘检测滤镜?
提前致谢