step1. 调用摄像头

📅 2026/7/2 2:42:25
step1. 调用摄像头
我们需要先在浏览器上访问和调用摄像头用来监控屋子里的一举一动。不同浏览器中调用摄像头的 API 都略有出入在这里我们以 chrome 做示例video width640 height480 autoplay/video script var video document.querySelector(video); navigator.webkitGetUserMedia({ video: true }, success, error); function success(stream) { video.src window.webkitURL.createObjectURL(stream); video.play(); } function error(err) { alert(video error: err) } /script运行页面后浏览器出于安全性考虑会询问是否允许当前页面访问你的摄像头设备点击“允许”后便能直接在 video 上看到摄像头捕获到的画面了step2. 捕获 video 帧画面光是开着摄像头监视房间可没有任何意义浏览器不会帮你对监控画面进行分析。所以这里我们得手动用脚本捕获 video 上的帧画面用于在后续进行数据分析。从这里开始咱们就要借助 canvas 力量了。在 Canvas入门五一文我们介绍过ctx.drawImage()方法通过它可以捕获 video 帧画面并渲染到画布上。我们需要创建一个画布然后这么写video width640 height480 autoplay/video canvas width640 height480/canvas script var video document.querySelector(video); var canvas document.querySelector(canvas); // video捕获摄像头画面 navigator.webkitGetUserMedia({ video: true }, success, error); function success(stream) { video.src window.webkitURL.createObjectURL(stream); video.play(); } function error(err) { alert(video error: err) } //canvas var context canvas.getContext(2d); setTimeout(function(){ //把当前视频帧内容渲染到画布上 context.drawImage(video, 0, 0, 640, 480); }, 5000); /script如上代码所示5秒后把视频帧内容渲染到画布上下方右图step3. 对捕获的两个帧画面执行差异混合在上面我们提到过要有效地识别某个场景需要对视频画面进行数据分析。那么要怎么识别咱们的房子是否有人突然闯入了呢答案很简单 —— 定时地捕获 video 画面然后对比前后两帧内容是否存在较大变化。我们先简单地写一个定时捕获的方法并将捕获到的帧数据存起来//canvas var context canvas.getContext(2d); var preFrame, //前一帧 curFrame; //当前帧 //捕获并保存帧内容 function captureAndSaveFrame(){ console.log(context); preFrame curFrame; context.drawImage(video, 0, 0, 640, 480); curFrame canvas.toDataURL; //转为base64并保存 } //定时捕获 function timer(delta){ setTimeout(function(){ captureAndSaveFrame(); timer(delta) }, delta || 500); } timer();如上代码所示画布会每隔500毫秒捕获并渲染一次 video 的帧内容夭寿哇做完这个动作不小心把饼干洒了一地。。。\(▔□▔)/留意这里我们使用了canvas.toDataURL方法来保存帧画面。接着就是数据分析处理了我们可以通过对比前后捕获的帧画面来判断摄像头是否监控到变化那么怎么做呢熟悉设计的同学肯定常常使用一个图层功能 —— 混合模式当有两个图层时对顶层图层设置“差值/Difference”的混合模式可以一目了然地看到两个图层的差异“图A”是我去年在公司楼下拍的照片然后我把它稍微调亮了一点点并在上面画了一个 X 和 O 得到“图B”。接着我把它们以“差值”模式混合在一起得到了最右的这张图。“差值”模式原理要混合图层双方的RGB值中每个值分别进行比较用高值减去低值作为合成后的颜色通常用白色图层合成一图像时可以得到负片效果的反相图像。用黑色的话不发生任何变化黑色亮度最低下层颜色减去最小颜色值0结果和原来一样而用白色会得到反相效果下层颜色被减去得到补值其它颜色则基于它们的亮度水平在CSS3中已经有 blend-mode 特性来支持这个有趣的混合模式不过我们发现在主流浏览器上canvas 的globalCompositeOperation接口也已经良好支持了图像混合模式于是我们再建多一个画布来展示前后两帧差异video width640 height480 autoplay/video canvas width640 height480/canvas canvas width640 height480/canvas script var video document.querySelector(video); var canvas document.querySelectorAll(canvas)[0]; var canvasForDiff document.querySelectorAll(canvas)[1]; // video捕获摄像头画面 navigator.webkitGetUserMedia({ video: true }, success, error); function success(stream) { video.src window.URL.createObjectURL(stream); video.play(); } function error(err) { alert(video error: err) } //canvas var context canvas.getContext(2d), diffCtx canvasForDiff.getContext(2d); //将第二个画布混合模式设为“差异” diffCtx.globalCompositeOperation difference; var preFrame, //前一帧 curFrame; //当前帧 //捕获并保存帧内容 function captureAndSaveFrame(){ preFrame curFrame; context.drawImage(video, 0, 0, 640, 480); curFrame canvas.toDataURL(); //转为base64并保存 } //绘制base64图像到画布上 function drawImg(src, ctx){ ctx ctx || diffCtx; var img new Image(); img.src src; ctx.drawImage(img, 0, 0, 640, 480); } //渲染前后两帧差异 function renderDiff(){ if(!preFrame || !curFrame) return; diffCtx.clearRect(0, 0, 640, 480); drawImg(preFrame); drawImg(curFrame); } //定时捕获 function timer(delta){ setTimeout(function(){ captureAndSaveFrame(); renderDiff(); timer(delta) }, delta || 500); } timer(); /script效果如下夭寿啊做完这个动作我又把雪碧洒在键盘上了。。。()/