OpenCV 4.11.0
开源计算机视觉
加载中…
搜索中…
无匹配项
视频入门

目标

  • 学习如何捕捉摄像头视频并显示它。

从摄像头捕捉视频

通常,我们需要使用摄像头捕捉实时流。在 OpenCV.js 中,我们使用 WebRTC 和 HTML canvas 元素来实现这一点。让我们从摄像头(内置或 USB)捕捉视频,将其转换为灰度视频并显示它。

要捕捉视频,您需要向网页添加一些 HTML 元素:

  • 一个 <video> 元素,用于直接显示来自摄像头的视频
  • 一个 <canvas> 元素,用于逐帧将视频传输到 canvas ImageData
  • 另一个 <canvas> 元素,用于显示 OpenCV.js 获取的视频

首先,我们使用 WebRTC 的 `navigator.mediaDevices.getUserMedia` 获取媒体流。

let video = document.getElementById("videoInput"); // video 是 video 标签的 id
navigator.mediaDevices.getUserMedia({ video: true, audio: false })
.then(function(stream) {
video.srcObject = stream;
video.play();
})
.catch(function(err) {
console.log("An error occurred! " + err);
});
注意
如果您从视频文件捕捉视频,则此函数是不必要的。但是请注意,HTML video 元素仅支持 Ogg(Theora)、WebM(VP8/VP9)或 MP4(H.264)格式的视频。

播放视频

现在,浏览器获取了摄像头流。然后,我们使用 Canvas 2D API 的 `CanvasRenderingContext2D.drawImage()` 方法将视频绘制到 canvas 上。最后,我们可以使用 图像入门 中的方法来读取和显示 canvas 中的图像。对于播放视频,应每隔 `delay` 毫秒执行一次 cv.imshow()。我们推荐使用 `setTimeout()` 方法。如果视频是 30fps,则延迟毫秒数应为 (1000/30 - processing_time)。

let canvasFrame = document.getElementById("canvasFrame"); // canvasFrame 是 <canvas> 的 id
let context = canvasFrame.getContext("2d");
let src = new cv.Mat(height, width, cv.CV_8UC4);
let dst = new cv.Mat(height, width, cv.CV_8UC1);
const FPS = 30;
function processVideo() {
let begin = Date.now();
context.drawImage(video, 0, 0, width, height);
src.data.set(context.getImageData(0, 0, width, height).data);
cv.cvtColor(src, dst, cv.COLOR_RGBA2GRAY);
cv.imshow("canvasOutput", dst); // canvasOutput 是另一个 <canvas> 的 id;
// 安排下一个
let delay = 1000/FPS - (Date.now() - begin);
setTimeout(processVideo, delay);
}
// 安排第一个
setTimeout(processVideo, 0);

OpenCV.js 使用上述方法实现了cv.VideoCapture (videoSource)。您无需手动添加隐藏的 canvas 元素。

参数
videoSource视频 id 或元素。
返回值
cv.VideoCapture 实例

我们使用read (image)来获取视频的一帧。出于性能原因,图像应使用 cv.CV_8UC4 类型构造,大小与视频相同。

参数
imagecv.CV_8UC4 类型且大小与视频相同的图像。

上面播放视频的代码可以简化为如下:

let src = new cv.Mat(height, width, cv.CV_8UC4);
let dst = new cv.Mat(height, width, cv.CV_8UC1);
let cap = new cv.VideoCapture(videoSource);
const FPS = 30;
function processVideo() {
let begin = Date.now();
cap.read(src);
cv.cvtColor(src, dst, cv.COLOR_RGBA2GRAY);
cv.imshow("canvasOutput", dst);
// 安排下一个
let delay = 1000/FPS - (Date.now() - begin);
setTimeout(processVideo, delay);
}
// 安排第一个
setTimeout(processVideo, 0);
注意
停止时,记得删除 src 和 dst。

试一试