乐闻世界logo
搜索文章和话题

OpenCV.js 如何实现实时视频处理?

3月6日 21:36

OpenCV.js 支持在浏览器中进行实时视频处理,以下是实现方法:

1. 获取视频流

javascript
async function startVideo() { const video = document.getElementById('videoInput'); try { const stream = await navigator.mediaDevices.getUserMedia({ video: { width: 640, height: 480 } }); video.srcObject = stream; await video.play(); // 开始处理视频帧 processVideo(); } catch (err) { console.error('Error accessing webcam:', err); } }

2. 处理视频帧

javascript
function processVideo() { const video = document.getElementById('videoInput'); const canvas = document.getElementById('canvasOutput'); const ctx = canvas.getContext('2d'); // 设置 canvas 尺寸 canvas.width = video.videoWidth; canvas.height = video.videoHeight; // 创建 Mat 对象 let src = new cv.Mat(video.videoHeight, video.videoWidth, cv.CV_8UC4); let dst = new cv.Mat(); let cap = new cv.VideoCapture(video); function processFrame() { try { // 读取视频帧 cap.read(src); // 图像处理(示例:边缘检测) cv.cvtColor(src, dst, cv.COLOR_RGBA2GRAY); cv.Canny(dst, dst, 50, 100); // 显示结果 cv.imshow('canvasOutput', dst); // 请求下一帧 requestAnimationFrame(processFrame); } catch (err) { console.error('Error processing frame:', err); } } processFrame(); }

3. 人脸检测示例

javascript
function faceDetection() { const video = document.getElementById('videoInput'); const canvas = document.getElementById('canvasOutput'); // 加载人脸检测模型 let faceCascade = new cv.CascadeClassifier(); faceCascade.load('haarcascade_frontalface_default.xml'); let src = new cv.Mat(); let gray = new cv.Mat(); let faces = new cv.RectVector(); let cap = new cv.VideoCapture(video); function detectFaces() { try { cap.read(src); // 转灰度 cv.cvtColor(src, gray, cv.COLOR_RGBA2GRAY); // 检测人脸 faceCascade.detectMultiScale(gray, faces, 1.1, 3, 0); // 绘制人脸框 for (let i = 0; i < faces.size(); ++i) { let face = faces.get(i); let point1 = new cv.Point(face.x, face.y); let point2 = new cv.Point(face.x + face.width, face.y + face.height); cv.rectangle(src, point1, point2, [255, 0, 0, 255], 2); } cv.imshow('canvasOutput', src); requestAnimationFrame(detectFaces); } catch (err) { console.error('Error:', err); } } detectFaces(); }

4. 性能优化技巧

降低分辨率

javascript
// 处理低分辨率图像,然后放大显示 let small = new cv.Mat(); cv.resize(src, small, new cv.Size(320, 240)); // 处理 small cv.resize(small, dst, new cv.Size(src.cols, src.rows));

限制帧率

javascript
let lastTime = 0; const FPS = 30; function processVideo(timestamp) { if (timestamp - lastTime >= 1000 / FPS) { // 处理视频帧 lastTime = timestamp; } requestAnimationFrame(processVideo); }

使用 Web Worker

javascript
// 主线程 const worker = new Worker('opencv-worker.js'); worker.onmessage = function(e) { const { imageData } = e.data; ctx.putImageData(imageData, 0, 0); }; function sendFrameToWorker() { const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); worker.postMessage({ imageData }, [imageData.data.buffer]); } // opencv-worker.js self.onmessage = function(e) { const { imageData } = e.data; // 使用 OpenCV.js 处理图像 const result = processImage(imageData); self.postMessage({ imageData: result }, [result.data.buffer]); };

5. 内存管理

javascript
function processVideo() { let src = new cv.Mat(); let dst = new cv.Mat(); function processFrame() { try { // 处理逻辑 } finally { // 确保释放内存 src.delete(); dst.delete(); } } // 页面卸载时清理 window.addEventListener('beforeunload', () => { src.delete(); dst.delete(); }); }

6. 完整示例:实时边缘检测

javascript
class VideoProcessor { constructor(videoId, canvasId) { this.video = document.getElementById(videoId); this.canvas = document.getElementById(canvasId); this.ctx = this.canvas.getContext('2d'); this.isProcessing = false; } async start() { try { const stream = await navigator.mediaDevices.getUserMedia({ video: { width: 640, height: 480 } }); this.video.srcObject = stream; await this.video.play(); this.canvas.width = this.video.videoWidth; this.canvas.height = this.video.videoHeight; this.src = new cv.Mat(this.video.videoHeight, this.video.videoWidth, cv.CV_8UC4); this.dst = new cv.Mat(); this.cap = new cv.VideoCapture(this.video); this.isProcessing = true; this.processFrame(); } catch (err) { console.error('Error starting video:', err); } } processFrame() { if (!this.isProcessing) return; try { this.cap.read(this.src); cv.cvtColor(this.src, this.dst, cv.COLOR_RGBA2GRAY); cv.Canny(this.dst, this.dst, 50, 100); cv.imshow(this.canvas.id, this.dst); requestAnimationFrame(() => this.processFrame()); } catch (err) { console.error('Error processing frame:', err); } } stop() { this.isProcessing = false; this.src.delete(); this.dst.delete(); } } // 使用 const processor = new VideoProcessor('videoInput', 'canvasOutput'); processor.start();
标签:Opencv.js