OpenCV.js 如何实现实时视频处理?
OpenCV.js 实现实时视频处理的核心流程是:通过 navigator.mediaDevices.getUserMedia() 获取摄像头流绑定到 video 元素,再用 cv.VideoCapture(video) 逐帧读取到 cv.Mat,在 requestAnimationFrame 循环中完成处理和 cv.imshow() 输出。性能瓶颈主要在 WASM 单线程执行和帧处理耗时,常用优化手段包括降低处理分辨率(先 resize 到小尺寸处理再放大显示)、用 Web Worker 将计算移到后台线程、以及控制帧率跳帧处理。内存管理上,视频循环中必须及时 delete 每帧的 Mat 对象,否则几秒内就会内存溢出。
追问
cv.VideoCapture 的参数可以传 canvas 吗? 可以。VideoCapture 构造函数接受 video 或 canvas 元素,传 canvas 时从 canvas 读取当前帧。这对于处理已有图像序列或截图场景很有用。
requestAnimationFrame 和 setTimeout 控制帧循环哪个好? requestAnimationFrame 与浏览器渲染同步,在不活动标签页自动暂停,更省资源。setTimeout 可精确控制帧率但不会自动暂停。实时视频场景推荐 requestAnimationFrame。
Web Worker 中能直接使用 cv 对象吗? 不能直接共享。Worker 需要独立加载 opencv.js 脚本,主线程通过 postMessage 传递 ImageData 的 ArrayBuffer(使用 Transferable 零拷贝),Worker 处理后回传结果。
如何检测和处理帧率下降? 用 performance.now() 记录每帧处理耗时,当单帧耗时超过 1000/targetFPS 时跳过处理帧只显示原始画面,或降低处理分辨率动态适配。
CascadeClassifier 加载 XML 模型文件在浏览器端怎么做? 浏览器无法直接读本地文件,需通过 fetch 下载 XML 文件为 ArrayBuffer,再用 cv.CascadeClassifier 的 load 方法传入 Uint8Array。也可将 XML 编码为 Base64 内嵌在代码中。
写段代码
javascriptlet cap = new cv.VideoCapture(video); let src = new cv.Mat(), dst = new cv.Mat(); function loop() { cap.read(src); cv.cvtColor(src, dst, cv.COLOR_RGBA2GRAY); cv.Canny(dst, dst, 50, 100); cv.imshow('output', dst); requestAnimationFrame(loop); } loop();