OpenCV  4.10.0
开源计算机视觉
加载中...
搜索中...
无匹配结果
视频操作入门

目标

  • 了解如何通过摄像头采集视频并显示视频。

通过摄像头采集视频

我们经常需要通过摄像头采集直播。在 OpenCV.js 中,我们使用 WebRTC 和 HTML canvas 元素实现此操作。现在,让我们通过摄像头(内置或 USB)采集一段视频,将其转换为灰度视频并进行显示。

要采集视频,您需要将部分 HTML 元素添加到网页中

  • 一个用于直接显示摄像头视频的 <video>
  • 一个用于逐帧将视频传输到 canvas ImageData 的 <canvas>
  • 另一个用于显示 OpenCV.js 采集的视频的 <canvas>

首先,我们使用 WebRTC 浏览器 navigator.mediaDevices.getUserMedia 获取媒体流。

let video = document.getElementById("videoInput"); // 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 视频元素仅支持 Ogg(Theora)、WebM(VP8/VP9) 或 MP4(H.264) 视频格式。

播放视频

现在,浏览器获取了摄像头流。然后,我们使用 Canvas 2D API 的 CanvasRenderingContext2D.drawImage() 方法将视频绘制到 canvas 中。最后,我们可以使用 图像操作入门 中的方法在 canvas 中读取和显示图像。对于播放视频,应每隔几毫秒执行一次 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)。您无需手动添加隐藏画布元素。

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

我们使用 read(图像)获取视频的一个帧。出于性能考虑,图像使用 cv.CV_8UC4 类型构建,且大小与视频一致。

参数
图像图像类型为 cv.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。

试试看