3D人脸网格
1.实验目的
进行3D人脸网格的估计。
2.核心代码
人脸检测任务类
类初始化 __init__
def __init__(self, kmodel_path, model_input_size, anchors, confidence_threshold=0.25, nms_threshold=0.3, rgb888p_size=[1280,720], display_size=[1920,1080], debug_mode=0):
主要参数解释:
kmodel_path:模型路径model_input_size:模型输入尺寸(如[320, 240])anchors:YOLO 类型模型使用的锚框confidence_threshold和nms_threshold:置信度和非极大值抑制阈值rgb888p_size:Sensor 采集图像的分辨率display_size:最终显示分辨率debug_mode:是否开启调试
初始化成员变量
包括对 Ai2d 实例化和设置格式类型:
self.ai2d = Ai2d(debug_mode)
self.ai2d.set_ai2d_dtype(nn.ai2d_format.NCHW_FMT, nn.ai2d_format.NCHW_FMT, np.uint8, np.uint8)
表示图像预处理输入输出为 NCHW 格式,数据类型为 uint8。
预处理
self.ai2d.pad(self.get_pad_param(), 0, [104,117,123])
self.ai2d.resize(nn.interp_method.tf_bilinear, nn.interp_mode.half_pixel)
self.ai2d.build([1,3,ai2d_input_size[1],ai2d_input_size[0]],[1,3,self.model_input_size[1],self.model_input_size[0]])
- 使用
pad()增加边缘空白以保持图像宽高比,pad 值由get_pad_param()自动计算 - 使用
resize()将图像缩放到模型输入大小 - 使 用
build()构建整个预处理流程图
Padding参数计算 get_pad_param()
ratio = min(dst_w / src_w, dst_h / src_h)
new_w = ratio * src_w
new_h = ratio * src_h
dw = dst_w - new_w
dh = dst_h - new_h
此函数按比例缩放图像,再对边缘加 padding 保持居中,避免图像变形。
后处理
res = aidemo.face_det_post_process(self.confidence_threshold,self.nms_threshold,self.model_input_size[0],self.anchors,self.rgb888p_size,results)
aidemo.face_det_post_process()是 CanMV 提供的 C 库函数,处理 YOLO 检测框输出,包括解码、过滤低分数框、NMS 等。- 输出结果是多个检测框,若有多个结果返回
res[0]作为主结果。
人脸网格检测任务类
这个类的任务是在人脸框中提取关键点参数(一般是 3D 姿态或 3D 网格)。
初始化时加载均值/方差参数
self.param_mean = np.array([...])
self.param_std = np.array([...])
这些是用于模型输出反归一化的参数,YOLOv8-face-mesh 或类似模型的输出一般是一个归一化的人脸参数向量。
预处理
roi = self.parse_roi_box_from_bbox(det)
self.ai2d.crop(int(roi[0]),int(roi[1]),int(roi[2]),int(roi[3]))
self.ai2d.resize(nn.interp_method.tf_bilinear, nn.interp_mode.half_pixel)
self.ai2d.build([1,3,ai2d_input_size[1],ai2d_input_size[0]],[1,3,self.model_input_size[1],self.model_input_size[0]])
- 根据人脸框
det提取roi区域 - 使用
crop()截取该区域并做resize,构建模型输入数据流
ROI计算
old_size = (w + h) / 2
center_x = x + w/2
center_y = y + h/2 + old_size * 0.14
size = old_size * 1.58
该方法是 FaceMesh 论文中标准的人脸裁剪方式,中心稍微偏下,区域稍微放大。
后处理
param = results[0] * self.param_std + self.param_mean
模型输出是一个归一化向量,对它进行反归一化以获得真实的人脸姿态参数。
完整流程
-
使用
FaceDetApp处理图像得到人脸框:face_bbox = face_det_app.postprocess(results_from_model) -
使用
FaceMeshApp读取该人脸框,预处理并进行推理:roi = face_mesh_app.config_preprocess(face_bbox)
face_param = face_mesh_app.postprocess(results_from_mesh_model)