实用指南:计算机视觉:人脸关键点定位与轮廓绘制
目录
一、关键模型准备
二、实战 1:人脸 68 个关键点定位
2.1 核心原理
2.2 完整代码实现
2.3 结果说明
三、实战 2:基于关键点的面部轮廓绘制
3.1 核心原理
3.2 完整代码实现
3.3 运行效果
四、常见问题与解决方案
1.模型路径错误
2.未检测到人脸
3.关键点绘制错位
五、技术扩展:关键点的应用场景
在计算机视觉领域,人脸关键点检测是表情识别、人脸编辑、疲劳监测等高级应用的核心基础。本文将跳过环境搭建环节,直接从核心原理出发,结合 OpenCV 与 dlib 库,详细讲解人脸 68 个关键点的定位与面部轮廓绘制的完整实现过程。
一、关键模型准备
dlib 的人脸关键点预测依赖预训练模型shape_predictor_68_face_landmarks.dat
,该模型可精准检测人脸的 68 个关键点(涵盖眼睛、眉毛、鼻子、嘴巴、面部轮廓)。
- 下载地址:https://github.com/davisking/dlib-models
- 使用说明:下载后将模型文件与代码放在同一目录,避免后续路径调用错误。
二、实战 1:人脸 68 个关键点定位
2.1 核心原理
dlib 的关键点检测基于级联回归树算法,整体流程分为三步:
- 人脸检测:通过
dlib.get_frontal_face_detector()
识别图像中的人脸区域,输出人脸边界框; - 关键点预测:利用预训练的
shape_predictor
模型,在人脸边界框内定位 68 个关键点的坐标; - 可视化展示:将关键点坐标转换为 NumPy 数组,通过 OpenCV 绘制关键点及编号,直观呈现检测结果。
2.2 完整代码实现
'''
功能:检测人脸68个关键点,并绘制关键点及编号
依赖库:numpy, cv2, dlib
模型:shape_predictor_68_face_landmarks.dat(需与代码同目录)
'''
import numpy as np
import cv2
import dlib
# 1. 读取图像(替换为你的图像路径,支持png/jpg格式)
img = cv2.imread("man.png")
# 读取失败判断
if img is None:raise ValueError("图像读取失败,请检查文件路径是否正确!")
# 2. 初始化人脸检测器(正面人脸检测)
detector = dlib.get_frontal_face_detector()
# 3. 检测图像中的人脸(参数0:不放大图像,平衡速度与精度)
faces = detector(img, 0)
if len(faces) == 0:print("未检测到人脸,请更换清晰正面人脸图像重试!")
else:print(f"共检测到 {len(faces)} 张人脸")
# 4. 加载关键点预测模型
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
# 5. 遍历人脸,获取并绘制关键点
for face in faces:# 5.1 预测当前人脸的68个关键点shape = predictor(img, face) # shape包含68个关键点对象# 5.2 转换关键点为(x, y)坐标数组(便于后续处理)landmarks = np.array([[p.x, p.y] for p in shape.parts()])# 5.3 绘制关键点(绿色实心圆)与编号(白色文字)for idx, point in enumerate(landmarks):pos = (point[0], point[1]) # 关键点坐标# 绘制实心圆:图像、坐标、半径2、颜色(0,255,0)(BGR)、厚度-1(填充)cv2.circle(img, pos, radius=2, color=(0, 255, 0), thickness=-1)# 绘制编号:字体SIMPLEX、字号0.4、颜色(255,255,255)、厚度1、抗锯齿cv2.putText(img, str(idx), pos, cv2.FONT_HERSHEY_SIMPLEX,fontScale=0.4, color=(255, 255, 255), thickness=1, lineType=cv2.LINE_AA)
# 6. 显示结果与释放资源
cv2.imshow("Face 68 Landmarks", img)
cv2.waitKey(0) # 按任意键关闭窗口
cv2.destroyAllWindows()
2.3 结果说明
关键点编号规则:68 个关键点按区域划分,具体对应关系如下:
- 0-16:面部轮廓(从下巴到额头两侧)
- 17-21:左眉,22-26:右眉
- 27-35:鼻子(含鼻梁、鼻尖、鼻翼)
- 36-41:右眼,42-47:左眼
- 48-67:嘴巴(48-59 为外轮廓,60-67 为内轮廓)
可视化效果:图像中每个关键点以绿色实心圆标记,旁边标注白色编号,可清晰区分不同面部区域的关键点位置。
三、实战 2:基于关键点的面部轮廓绘制
在获取 68 个关键点后,通过凸包算法与线段绘制,可进一步勾勒面部轮廓,让检测结果更直观。
3.1 核心原理
- 凸包算法(cv2.convexHull):对于眼睛、嘴巴等闭合区域,通过关键点生成凸多边形,准确包裹区域边界,避免轮廓断裂;
- 线段绘制(cv2.line):对于面部轮廓、眉毛、鼻子等非闭合区域,将连续关键点用线段连接,形成完整的线性轮廓。
3.2 完整代码实现
'''
功能:基于68个关键点绘制面部轮廓(眉毛、眼睛、鼻子、嘴巴、面部轮廓)
依赖库:numpy, cv2, dlib
'''
import numpy as np
import dlib
import cv2
# 1. 定义轮廓绘制工具函数
def draw_line(start, end):'''绘制线段:连接从start到end的连续关键点(左闭右开区间)'''pts = shape[start:end] # 获取关键点区间for i in range(1, len(pts)):pt_a = tuple(pts[i-1]) # 前一个关键点pt_b = tuple(pts[i]) # 当前关键点# 绘制绿色线段,厚度2cv2.line(image, pt_a, pt_b, color=(0, 255, 0), thickness=2)
def draw_convex_hull(start, end):'''绘制凸包轮廓:用于眼睛、嘴巴等闭合区域(包含end的闭区间)'''facial_pts = shape[start:end+1] # 获取关键点区间hull = cv2.convexHull(facial_pts) # 生成凸包# 绘制绿色凸包轮廓,厚度2(-1表示填充,此处用2保留轮廓线)cv2.drawContours(image, [hull], -1, (0, 255, 0), thickness=2)
# 2. 读取图像
image = cv2.imread("man.png")
if image is None:raise ValueError("图像读取失败,请检查文件路径!")
# 3. 人脸检测与关键点预测(与实战1逻辑一致)
detector = dlib.get_frontal_face_detector()
faces = detector(image, 0)
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
if len(faces) == 0:print("未检测到人脸!")
else:for face in faces:# 获取关键点并转换为数组shape = predictor(image, face)shape = np.array([[p.x, p.y] for p in shape.parts()])# 4. 按区域绘制轮廓(关键:对应68个关键点的正确区间)draw_convex_hull(36, 41) # 右眼轮廓(36-41号关键点)draw_convex_hull(42, 47) # 左眼轮廓(42-47号关键点)draw_convex_hull(48, 59) # 嘴巴外部轮廓(48-59号关键点)draw_convex_hull(60, 67) # 嘴巴内部轮廓(60-67号关键点)draw_line(0, 17) # 面部轮廓(0-16号,左闭右开需到17)draw_line(17, 22) # 左眉轮廓(17-21号关键点)draw_line(22, 27) # 右眉轮廓(22-26号关键点)draw_line(27, 36) # 鼻子轮廓(27-35号关键点)
# 5. 结果展示与保存(可选)
cv2.imshow("Face Contours", image)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 保存结果图像到当前目录
cv2.imwrite("face_contours_result.png", image)
print("结果图像已保存为 face_contours_result.png")
3.3 运行效果
代码运行后,图像将呈现以下绿色轮廓:
- 闭合轮廓:左右眼(凸包形状,完整包裹眼球区域)、嘴巴内外侧(区分嘴唇与牙齿边界);
- 线性轮廓:面部轮廓(从下巴尖沿脸颊到额头两侧)、左右眉毛(沿眉形连接关键点)、鼻子(从鼻梁到鼻尖的中线)。
四、常见问题与解决方案
1.模型路径错误
报错信息:Unable to open shape_predictor_68_face_landmarks.dat
解决:确认模型文件与代码在同一目录,或在shape_predictor
中传入完整路径(如"D:/cv_project/shape_predictor_68_face_landmarks.dat"
)。
2.未检测到人脸
原因:图像中无正面人脸、人脸尺寸过小(小于 80×80 像素,dlib 默认最小检测尺寸)或光线过暗。
解决:更换清晰正面人脸图像,或调整detector
参数(如detector(img, 1)
,1 表示放大图像 1 倍后检测,提升小人脸识别率)。
3.关键点绘制错位
原因:图像读取时通道顺序错误(OpenCV 默认 BGR,若误转为 RGB 会导致坐标偏移)。
解决:确保直接使用cv2.imread()
读取图像,不额外转换通道顺序(除非后续有特殊处理需求)。
五、技术扩展:关键点的应用场景
人脸 68 个关键点是计算机视觉中极具价值的基础数据,基于本文技术可进一步扩展以下应用:
表情识别:通过嘴巴关键点(48-67)的开合程度、眼睛关键点(36-47)的眯眼状态,判断微笑、愤怒、惊讶等表情;
疲劳监测:计算眼睛纵横比(如 “眼高 / 眼宽”,当比值 < 0.3 时判定为闭眼),统计单位时间内闭眼次数与时长,预警疲劳状态;
人脸编辑:结合仿射变换(cv2.warpAffine
),基于关键点实现人脸对齐、换脸、妆容迁移(如将 A 的眉毛轮廓复制到 B 的脸上)。