Face mesh
是从原始图像中裁剪得到的人脸区域(ROI,Region of Interest)。裁剪的目的是降低计算成本或为后续处理提供专注区域。归一化比例因子是为了让坐标值适配不同大小的输入图像。归一化的主要目的是消除因图像尺寸不同带来的影响,使关键点坐标具有通用性。),但 Face Mesh 模块通过深度信息估计输出了三维坐标。虽然图像是二维的(像素坐标系只有。
1. 为什么输出是 x, y, z 而不是只有 x, y?
虽然图像是二维的(像素坐标系只有 x,yx, yx,y),但 Face Mesh 模块通过深度信息估计输出了三维坐标 x,y,zx, y, zx,y,z。以下是具体原因:
1.1 图像是二维的,但人脸是三维的
- 即使图像本身是二维的,人脸是一个三维物体。MediaPipe 使用机器学习模型从二维图像中推测出三维的深度信息。
- Z 轴:代表每个关键点相对于人脸中心的深度值,单位通常是相对值,用来估计人脸在三维空间中的形状。
1.2 MediaPipe 的 3D 推测原理
- 模型基于训练数据,从多个角度学习了三维人脸的结构。
- 关键点 x, y, z 含义:
- xxx: 水平方向坐标,归一化为 [0, 1]。
- yyy: 垂直方向坐标,归一化为 [0, 1]。
- zzz: 深度值,相对归一化坐标,用于表示点距离摄像头或基准平面的远近关系。
2. 归一化比例因子是什么?
2.1 归一化的含义
归一化比例因子是为了让坐标值适配不同大小的输入图像。归一化的主要目的是消除因图像尺寸不同带来的影响,使关键点坐标具有通用性。
-
归一化公式:
xnormalized=ximage width,ynormalized=yimage height x_{\text{normalized}} = \frac{x}{\text{image width}}, \quad y_{\text{normalized}} = \frac{y}{\text{image height}} xnormalized=image widthx,ynormalized=image heighty
其中:- x,yx, yx,y 是像素坐标。
- image width\text{image width}image width 和 image height\text{image height}image height 是输入图像的宽度和高度。
-
归一化的优点:
- 无论图像大小如何,关键点的坐标值都在 [0, 1] 范围内。
- 便于在模型中使用或与其他图像对齐。
2.2 Z 坐标的归一化
- zzz 的归一化是相对深度值,通常以人脸框的宽度为基准单位。例如:
znormalized=zface width z_{\text{normalized}} = \frac{z}{\text{face width}} znormalized=face widthz - 归一化后的 zzz 是无单位值,可以反映人脸中某些关键点在深度上的相对关系,例如鼻尖相对于面部其他部分是否更靠近摄像头。
3. 小图 sub_face_mini 为什么需要?
小图 sub_face_mini 是从原始图像中裁剪得到的人脸区域(ROI,Region of Interest)。裁剪的目的是降低计算成本或为后续处理提供专注区域。
3.1 小图的作用
-
局部增强精度:
- 后续操作(如表情识别、属性分析)可能需要对脸部局部细节进行处理。通过裁剪小图,可以集中分析人脸特定区域的特征。
-
降低计算复杂度:
- 使用完整图像可能会浪费计算资源,而裁剪的小图减少了无关背景,降低计算成本。
-
便于进一步操作:
- 小图可以用于表情识别、年龄估计、化妆检测等任务。
- 特定应用可能只需要眼睛、嘴巴等局部区域,裁剪后的小图为后续裁剪提供了基础。
3.2 小图裁剪的逻辑
- 通过检测到的关键点(如眼睛、嘴巴、下巴等的坐标)裁剪出一个包含整个人脸的矩形区域。
- 裁剪过程:
- 找到关键点的边界框。
- 根据边界框裁剪图像:
ROI=image[ymin:ymax,xmin:xmax] \text{ROI} = \text{image}[y_{\text{min}}:y_{\text{max}}, x_{\text{min}}:x_{\text{max}}] ROI=image[ymin:ymax,xmin:xmax]
示例代码
import cv2
import mediapipe as mp
# 初始化 Face Mesh 模块
mp_face_mesh = mp.solutions.face_mesh.FaceMesh()
# 加载图像
image = cv2.imread("face.jpg")
rgb_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# 检测人脸关键点
results = mp_face_mesh.process(rgb_image)
# 提取人脸区域小图
if results.multi_face_landmarks:
for face_landmarks in results.multi_face_landmarks:
h, w, _ = image.shape
# 根据关键点找到边界框
x_min = int(min([lm.x for lm in face_landmarks.landmark]) * w)
y_min = int(min([lm.y for lm in face_landmarks.landmark]) * h)
x_max = int(max([lm.x for lm in face_landmarks.landmark]) * w)
y_max = int(max([lm.y for lm in face_landmarks.landmark]) * h)
# 裁剪人脸小图
sub_face_mini = image[y_min:y_max, x_min:x_max]
cv2.imshow("Cropped Face", sub_face_mini)
cv2.waitKey(0)
cv2.destroyAllWindows()
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)