如何用JavaScript正确裁剪视频流捕获的画面(提取人脸区域)
问题:如何从视频捕获的画面中裁剪出中间的人脸区域
我参考MDN教程实现了用JavaScript从视频中捕获画面,当前代码可获取全屏画面,但需要裁剪出屏幕中间的人脸区域,修改drawImage参数后仅实现图片缩小,复制到其他画布也显示为空,求正确裁剪方法。
现有代码
HTML代码
<canvas id="canvas" style="display:none" ></canvas> <div class="output"> <img id="photo" alt="" src=""> </div>
JS代码
let imgElement = document.querySelector("#photo"); function takePicture(results) { let canvas = document.getElementById('canvas'); let context = canvas.getContext('2d'); if (width && height) { canvas.width = width; canvas.height = height; context.drawImage(results.image, 0, 0, canvas.width, canvas.height); let data = canvas.toDataURL('image/png'); imgElement.setAttribute('src', data); } else { clearPhoto(); } }
尝试过的修改
context.drawImage(results.image, 0, 0, canvas.width, canvas.height, 100, 100, 300, 300);
解决方案
你用错了drawImage的参数顺序,裁剪需要正确区分源图像的裁剪区域和目标画布的绘制区域:
drawImage的完整参数定义是:
context.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
sx/sy:源图像上要裁剪区域的左上角坐标sWidth/sHeight:源图像上裁剪区域的宽高dx/dy:目标画布上放置裁剪后图像的左上角坐标dWidth/dHeight:目标画布上图像的显示宽高
要裁剪画面中间的人脸区域,按以下步骤修改即可:
计算源图像中间区域的坐标
假设你要裁剪的人脸区域宽高为300x300,那么源图像的起始坐标需要取画面正中间:const faceWidth = 300; const faceHeight = 300; const sx = (width - faceWidth) / 2; const sy = (height - faceHeight) / 2;调整画布尺寸(可选但关键)
如果希望最终输出的是裁剪后的小图,必须把画布的实际宽高设为裁剪区域的大小(CSS设置的只是显示尺寸,不影响绘图区域):canvas.width = faceWidth; canvas.height = faceHeight;正确调用
drawImage
把裁剪的源区域绘制到目标画布的左上角:context.drawImage(results.image, sx, sy, faceWidth, faceHeight, 0, 0, faceWidth, faceHeight);
修改后的完整函数
let imgElement = document.querySelector("#photo"); function takePicture(results) { let canvas = document.getElementById('canvas'); let context = canvas.getContext('2d'); if (width && height) { // 定义人脸裁剪区域的宽高 const faceWidth = 300; const faceHeight = 300; // 计算源图像中间区域的起始坐标 const sx = (width - faceWidth) / 2; const sy = (height - faceHeight) / 2; // 设置画布为裁剪后的实际尺寸 canvas.width = faceWidth; canvas.height = faceHeight; // 裁剪并绘制到画布 context.drawImage(results.image, sx, sy, faceWidth, faceHeight, 0, 0, faceWidth, faceHeight); let data = canvas.toDataURL('image/png'); imgElement.setAttribute('src', data); } else { clearPhoto(); } }
之前复制到其他画布为空,大概率是因为画布实际尺寸未正确设置,或者drawImage参数顺序错误导致没有绘制有效内容。只要按上述方式调整,就能正确裁剪出中间的人脸区域。
内容的提问来源于stack exchange,提问作者Azamat Uzbekov
相关产品推荐
相关产品推荐

