如何在Mediapipe JS中为检测到的嘴唇区域填充颜色而非仅绘边界
为MediaPipe检测到的嘴唇区域填充颜色
MediaPipe的drawingUtils.drawConnectors仅能绘制关键点间的连线,要实现嘴唇区域填充,需手动通过Canvas API构建闭合路径并完成填充。以下是具体实现方案及修改后的代码:
核心思路
- 提取MediaPipe FaceMesh中嘴唇轮廓的有序关键点索引,按顺序连接可形成闭合的嘴唇形状路径
- 将关键点的归一化坐标转换为Canvas实际像素坐标,构建路径后执行填充
- 通过Canvas混合模式让填充色与原图自然融合,模拟滤镜效果
修改后的完整代码
// Draw the overlays. canvasCtx.save(); canvasCtx.fillRect(0, 0, canvasElement.width, canvasElement.height); canvasCtx.drawImage( results.image, 0, 0, canvasElement.width, canvasElement.height); if (results.multiFaceLandmarks) { // 定义嘴唇外轮廓的关键点索引(按闭合顺序排列,确保路径连贯) const LIP_OUTLINE_POINTS = [ 61, 185, 40, 39, 37, 0, 267, 269, 270, 409, 291, 375, 321, 405, 314, 17, 84, 181, 91, 146, 61 ]; for (const landmarks of results.multiFaceLandmarks) { // 1. 构建嘴唇填充路径 canvasCtx.beginPath(); const firstLipPoint = landmarks[LIP_OUTLINE_POINTS[0]]; // 将归一化坐标转为Canvas像素坐标 canvasCtx.moveTo( firstLipPoint.x * canvasElement.width, firstLipPoint.y * canvasElement.height ); // 依次连接所有嘴唇关键点 for (let i = 1; i < LIP_OUTLINE_POINTS.length; i++) { const point = landmarks[LIP_OUTLINE_POINTS[i]]; canvasCtx.lineTo( point.x * canvasElement.width, point.y * canvasElement.height ); } // 2. 设置填充样式与混合模式 canvasCtx.fillStyle = 'rgba(255, 0, 0, 0.5)'; // 半透明红色,可自定义颜色/透明度 canvasCtx.globalCompositeOperation = 'multiply'; // 让填充色与原图融合,可选overlay/screen等模式 canvasCtx.fill(); // 恢复默认混合模式,避免影响后续绘制 canvasCtx.globalCompositeOperation = 'source-over'; // 3. 绘制嘴唇边界(可选,保留原有的边界线) drawingUtils.drawConnectors( canvasCtx, landmarks, mpFaceMesh.FACEMESH_LIPS, {color: 'red', lineWidth: 1 }); } } canvasCtx.restore();
自定义调整说明
- 若要改变填充效果,可修改
fillStyle的颜色值(如rgba(255, 165, 0, 0.6)实现橙色半透明) - 切换
globalCompositeOperation的取值,可获得不同的滤镜融合效果(比如screen会让颜色更明亮) - 若需要填充嘴唇内部完整区域,可补充嘴唇内轮廓的关键点索引,构建更复杂的闭合路径
内容的提问来源于stack exchange,提问作者Vipul Sharma
相关产品推荐
相关产品推荐

