4. 人脸对齐
任务说明
本案例实现人脸对齐的核心流程:给定一张人脸图像及检测到的两只眼睛关键点坐标,通过仿射变换将人脸旋转至眼睛水平,并裁剪出标准化尺寸的人脸区域。输入为图像文件路径与两眼坐标,输出为对齐并裁剪后的标准人脸图像。
实现方案
采用OpenCV完成全部计算。核心步骤为:根据两眼坐标计算旋转角度,构造旋转矩阵(以两眼中心为旋转中心),执行仿射变换,最后按标准人脸几何比例裁剪出固定尺寸区域。裁剪区域依据两眼距离确定宽度,再按比例推算高度,保证不同人脸图像输出尺寸一致。
代码实现
import cv2
import numpy as np
def align_face(image_path, left_eye, right_eye, output_size=(220, 165)):
"""
人脸对齐:旋转使眼睛水平,并裁剪标准化区域
参数:
image_path: 输入图像路径
left_eye: 左眼坐标 (x, y)
right_eye: 右眼坐标 (x, y)
output_size: 输出尺寸 (宽, 高)
返回:
对齐并裁剪后的人脸图像 (numpy数组)
"""
# 读取图像
img = cv2.imread(image_path)
if img is None:
raise ValueError(f"无法读取图像: {image_path}")
# 计算旋转角度(弧度)
dx = right_eye[0] - left_eye[0]
dy = right_eye[1] - left_eye[1]
angle_rad = np.arctan2(dy, dx)
angle_deg = -np.degrees(angle_rad) # 负号:顺时针旋转使眼睛水平
# 两眼中心作为旋转中心
eye_center = ((left_eye[0] + right_eye[0]) / 2.0,
(left_eye[1] + right_eye[1]) / 2.0)
# 构造旋转矩阵(含缩放)
rot_matrix = cv2.getRotationMatrix2D(eye_center, angle_deg, scale=1.0)
# 执行仿射变换
h, w = img.shape[:2]
rotated = cv2.warpAffine(img, rot_matrix, (w, h),
flags=cv2.INTER_CUBIC,
borderMode=cv2.BORDER_REPLICATE)
# 计算标准化裁剪区域
eye_dist = np.sqrt(dx**2 + dy**2)
crop_w = int(2.2 * eye_dist) # 宽度 = 2.2倍眼距
crop_h = int(crop_w * 0.75) # 高度 = 宽度的0.75
# 裁剪中心 = 旋转后的两眼中心
# 旋转后两眼中心位置不变(旋转中心即两眼中心)
cx, cy = int(eye_center[0]), int(eye_center[1])
# 计算裁剪矩形(越界处理)
x1 = max(0, cx - crop_w // 2)
y1 = max(0, cy - crop_h // 2)
x2 = min(w, x1 + crop_w)
y2 = min(h, y1 + crop_h)
cropped = rotated[y1:y2, x1:x2]
# 缩放到标准输出尺寸
aligned = cv2.resize(cropped, output_size, interpolation=cv2.INTER_CUBIC)
return aligned
# 示例:使用给定关键点执行对齐
if __name__ == "__main__":
# 输入图像(请替换为实际路径)
img_path = "face.jpg"
# 示例关键点(左眼、右眼坐标)
left_eye_pt = (112, 98)
right_eye_pt = (168, 102)
# 执行对齐
result = align_face(img_path, left_eye_pt, right_eye_pt)
# 保存结果
cv2.imwrite("aligned_face.jpg", result)
print("对齐完成,输出尺寸:", result.shape[1], "x", result.shape[0])
落地与验证
依赖安装:需要OpenCV与NumPy,执行 pip install opencv-python numpy。
运行方式:将代码保存为 face_align.py,准备一张含正脸人脸的图像 face.jpg,修改代码中两眼坐标为你图像中的实际关键点位置,然后执行 python face_align.py。
验证方法:程序运行后生成 aligned_face.jpg。打开该图像,观察以下判定标准:
- 两只眼睛中心处于同一水平线(y坐标差不超过2像素);
- 输出图像尺寸为220×165像素;
- 人脸位于图像中央,双眼完整可见。
若眼睛仍倾斜,说明输入关键点坐标不准确,请重新标注后再次运行。