如何先对齐再提取:用RetinaFace实现无黑边人脸对齐
解决RetinaFace倾斜人脸对齐后裁剪黑边问题
要实现按眼水平线对齐→提取人脸→无黑边裁剪的流程,需拆分RetinaFace的默认操作逻辑,手动处理检测、对齐和裁剪步骤,避免强制填充黑边:
步骤1:检测人脸关键点与边界框
先获取人脸的边界框和关键点(双眼、鼻子等),为后续对齐提供基础:
import matplotlib.pyplot as plt import cv2 import numpy as np from retinaface import RetinaFace img_path = "/content/drive/img/0036.jpg" # 检测人脸,返回包含边界框和关键点的字典 detected_faces = RetinaFace.detect_faces(img_path) # 读取并转换图像格式 img = cv2.imread(img_path) img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
步骤2:按眼水平线手动对齐人脸
基于双眼连线的角度旋转校正人脸,确保眼水平线水平,同时避免引入黑边:
for face_key in detected_faces: face_info = detected_faces[face_key] # 获取双眼关键点坐标 left_eye = face_info['landmarks']['left_eye'] right_eye = face_info['landmarks']['right_eye'] # 计算双眼连线的倾斜角度 dx = right_eye[0] - left_eye[0] dy = right_eye[1] - left_eye[1] angle = np.degrees(np.arctan2(dy, dx)) # 获取原始人脸边界框 x1, y1, x2, y2 = face_info['facial_area'] face_width = x2 - x1 face_height = y2 - y1 # 以人脸中心为旋转轴 center = ((x1 + x2) // 2, (y1 + y2) // 2) # 生成旋转矩阵,保持缩放比例为1 rotation_matrix = cv2.getRotationMatrix2D(center, angle, 1.0) # 计算旋转后图像的尺寸,确保人脸完整显示 cos = np.abs(rotation_matrix[0, 0]) sin = np.abs(rotation_matrix[0, 1]) new_width = int((face_height * sin) + (face_width * cos)) new_height = int((face_height * cos) + (face_width * sin)) # 调整旋转矩阵的平移参数,让人脸居中 rotation_matrix[0, 2] += (new_width / 2) - center[0] rotation_matrix[1, 2] += (new_height / 2) - center[1] # 对人脸区域进行旋转对齐 aligned_face = cv2.warpAffine(img, rotation_matrix, (new_width, new_height), flags=cv2.INTER_CUBIC)
步骤3:无黑边裁剪对齐后的人脸
基于旋转后的双眼位置,定位真实人脸区域,裁剪掉多余的空白部分:
# 计算旋转后双眼的坐标 rotated_left_eye = cv2.transform(np.array([[left_eye]]), rotation_matrix)[0][0] rotated_right_eye = cv2.transform(np.array([[right_eye]]), rotation_matrix)[0][0] # 以双眼为基准,确定裁剪范围(可根据需求调整比例) eye_y = (rotated_left_eye[1] + rotated_right_eye[1]) / 2 crop_top = max(0, int(eye_y - face_height * 0.6)) crop_bottom = min(new_height, int(eye_y + face_height * 0.8)) crop_left = max(0, int(min(rotated_left_eye[0], rotated_right_eye[0]) - face_width * 0.2)) crop_right = min(new_width, int(max(rotated_left_eye[0], rotated_right_eye[0]) + face_width * 0.2)) # 执行裁剪 cropped_face = aligned_face[crop_top:crop_bottom, crop_left:crop_right] # 显示结果 plt.imshow(cropped_face) plt.axis('off') plt.show()
核心逻辑说明
- 拆分
detect_faces与手动对齐流程,替代extract_faces的默认黑边填充逻辑 - 旋转时计算适配尺寸,确保人脸区域完整,再通过关键点定位只保留真实人脸像素
- 对齐基准为双眼连线水平,而非图像垂直边缘,符合姿态校正需求
内容的提问来源于stack exchange,提问作者Victor
相关产品推荐
相关产品推荐

