欢迎来到
银狐的个人博客

OpenCV-Python实战(15)——面部特征点检测详解(仅需5行代码学会3种面部特征点检测方法)

OpenCV-Python实战(15)——面部特征点检测详解(仅需5行代码学会3种面部特征点检测方法) 0. 前言1. 面部特征点简介2. 使用 OpenCV 检测面部特征点3. 用 dlib 检测面部特征点4. 使用 face_recognition 检测面部特征点小结系列链接

0. 前言

人脸处理是人工智能中的一个热门话题,人脸处理可以使用计算机视觉算法从人脸中自动提取大量信息,例如身份、意图和情感。在计算机视觉中,面部关键点(也称为面部特征点)的定位通常是许多面部分析方法和算法中的关键步骤。例如,面部表情识别、头部姿态估计和疲倦检测系统都依赖于面部特征点检测提供的面部信息。在本文中,我们将使用 OpenCVdlib 以及 face_recognition 检测面部特征点。

1. 面部特征点简介

面部特征点检测算法的目标是自动识别图像或视频中面部特征点的位置。更具体地说,这些关键点是描述面部组件位置(例如,嘴角或眼角)的主要点,或者是连接面部组件和面部轮廓主要点及其插值点。形式上,给定表示为 I 的面部图像,特征点检测算法检测 D 个特征点的位置 x = x 1 , y 1 , x 2 , y 2 , . . . , x D , y D x = {x_1, y_1, x_2, y_2, …, x_D, y_D} x=x1​,y1​,x2​,y2​,…,xD​,yD​,其中 xy 表示图像的面部特征点的坐标。

2. 使用 OpenCV 检测面部特征点

OpenCV 人脸特征点 API 称为 Facemark。它包括特征点检测的三种不同实现:

FacemarkLBFFacemarkKameziFacemarkAAM

以下示例展示了如何使用这些算法检测面部特征点:

import cv2import numpy as np# 加载图片image = cv2.imread("example",0)# 检测人脸cas = cv2.CascadeClassifier("haarcascade_frontalface_alt2.xml")faces = cas.detectMultiScale(image , 1.5, 5)print("faces", faces)# 创建特征点检测器并对其进行测试print("testing LBF")# 第一种面部特征点检测方法,第一行代码# 创建特征点检测器facemark = cv2.face.createFacemarkLBF()# 第一种面部特征点检测方法,第二行代码# 加载检测器模型facemark.loadModel("lbfmodel.yaml")# 第一种面部特征点检测方法,第三行代码# 检测面部特征点ok, landmarks = facemark.fit(image , faces)print ("landmarks LBF", ok, landmarks)# 测试其他特征点检测算法print("testing AAM")facemark = cv2.face.createFacemarkAAM()facemark .loadModel("aam.xml")ok, landmarks = facemark.fit(image , faces)print ("landmarks AAM", ok, landmarks)print("testing Kazemi")facemark = cv2.face.createFacemarkKazemi()facemark .loadModel("face_landmark_model.dat")ok, landmarks = facemark.fit(image , faces)print ("landmarks Kazemi", ok, landmarks)

上述示例使用 OpenCV 提供的三种不同算法来检测面部特征点。

3. 用 dlib 检测面部特征点

我们也可以使用 dlib 库来检测面部特征点,接下来,我们加载测试图像,然后使用 dlib 执行人脸检测,最后使用人脸特征检测器获取检测面部特征点。想要运行以下代码,首先需要下载检测面部特征点检测器文件 shape_predictor_68_face_landmarks.dat。

# 加载图像并转换为灰度图像test_face = cv2.imread("example.png")gray = cv2.cvtColor(test_face, cv2.COLOR_BGR2GRAY)# 人脸检测detector = dlib.get_frontal_face_detector()rects = detector(gray, 0)# 检测面部特征点p = "shape_predictor_68_face_landmarks.dat"# 第二种面部特征点检测方法,第一行代码predictor = dlib.shape_predictor(p)# 第二种面部特征点检测方法,第二行代码shape = predictor(gray, rect)

shape 是一个 dlib full_object_detection 对象,用于表示图像中对象的位置,接下来需要将其转换为 numpy 数组,编写 shape_to_np() 函数执行此转换:

def shape_to_np(dlib_shape, dtype="int"):    # 初始化 (x, y) 坐标列表    coordinates = np.zeros((dlib_shape.num_parts, 2), dtype=dtype)    # 循环所有面部特征点,并将其转换为 (x, y) 坐标的元组    for i in range(0, dlib_shape.num_parts):        coordinates[i] = (dlib_shape.part(i).x, dlib_shape.part(i).y)    # 返回 (x,y) 坐标的列表    return coordinates

最后,在图像中绘制了 68 个面部特征点。我们可以使用灵活的方式以所需的格式在图像中绘制特征点,接下来,介绍集中常用的绘制检测到的面部特征点的不同方法:

(1) 使用线条绘制面部特征点形状,以连接绘制脸部的不同部分的轮廓(例如鼻子、眼睛等):

# 定义不同特征点取值切片JAWLINE_POINTS = list(range(0, 17))RIGHT_EYEBROW_POINTS = list(range(17, 22))LEFT_EYEBROW_POINTS = list(range(22, 27))NOSE_BRIDGE_POINTS = list(range(27, 31))LOWER_NOSE_POINTS = list(range(31, 36))RIGHT_EYE_POINTS = list(range(36, 42))LEFT_EYE_POINTS = list(range(42, 48))MOUTH_OUTLINE_POINTS = list(range(48, 61))MOUTH_INNER_POINTS = list(range(61, 68))ALL_POINTS = list(range(0, 68))# 使用线条绘制面部特征点def draw_shape_lines_all(np_shape, image):    draw_shape_lines_range(np_shape, image, JAWLINE_POINTS)    draw_shape_lines_range(np_shape, image, RIGHT_EYEBROW_POINTS)    draw_shape_lines_range(np_shape, image, LEFT_EYEBROW_POINTS)    draw_shape_lines_range(np_shape, image, NOSE_BRIDGE_POINTS)    draw_shape_lines_range(np_shape, image, LOWER_NOSE_POINTS)    draw_shape_lines_range(np_shape, image, RIGHT_EYE_POINTS, True)    draw_shape_lines_range(np_shape, image, LEFT_EYE_POINTS, True)    draw_shape_lines_range(np_shape, image, MOUTH_OUTLINE_POINTS, True)    draw_shape_lines_range(np_shape, image, MOUTH_INNER_POINTS, True)# 连接不同的点来绘制曲线形状def draw_shape_lines_range(np_shape, image, range_points, is_closed=False):    np_shape_display = np_shape[range_points]    points = np.array(np_shape_display, dtype=np.int32)    cv2.polylines(image, [points], is_closed, (255, 255, 0), thickness=2, lineType=cv2.LINE_8)# 函数调用draw_shape_lines_all(shape, test_face)cv2.imshow("Landmarks detection using dlib", test_face)cv2.waitKey(0)

(2) 调用 draw_shape_lines_range() 函数,可以仅绘制指定面部组件轮廓线,例如下颚线 JAWLINE_POINTS

draw_shape_lines_range(shape, test_face, JAWLINE_POINTS)

(3) 绘制所有特征点及其位序:

# 绘制指定的特征点def draw_shape_points_pos_range(np_shape, image, points):    np_shape_display = np_shape[points]    draw_shape_points_pos(np_shape_display, image)# 使用每个特征点及其位序绘制形状def draw_shape_points_pos(np_shape, image):    for idx, (x, y) in enumerate(np_shape):        # 绘制每个检测到的特征点的位序        cv2.putText(image, str(idx + 1), (x, y), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 0, 255))        # 在每个特征点位置上绘制一个点        cv2.circle(image, (x, y), 2, (0, 255, 0), -1)# 可以用两种方法来绘制检测到的所有特征点及其位序# 方法1draw_shape_points_pos(shape, test_face)# 方法2draw_shape_points_pos_rangeOpenCV-Python实战(15)——面部特征点检测详解(仅需5行代码学会3种面部特征点检测方法) 第1张图片-银狐博客(shape, test_face, ALL_POINTS)

(4) 我们也可以仅绘制所有特征点:

# 绘制指定特征点def draw_shape_points_range(np_shape, image, points):    np_shape_display = np_shape[points]    draw_shape_points(np_shape_display, image)# 绘制所有特征点def draw_shape_points(np_shape, image):    for (x, y) in np_shape:        cv2.circle(image, (x, y), 2, (0, 255, 0), -1)# 可以用两种方法绘制所有特征点# 方法1draw_shape_points(shape, test_face)# 方法2draw_shape_points_range(shape, test_face, ALL_POINTS)

(5) 利用上述函数,我们可以仅绘制指定特征点,例如仅绘制眼部和鼻子特征点:

draw_shape_points_pos_range(shape, test_face, LEFT_EYE_POINTS + RIGHT_EYE_POINTS + NOSE_BRIDGE_POINTS)

dlib 还提供了检测与双眼和鼻尖位置相对应的 5 个面部特征点检测器,如果想要使用此检测器,需要首先下载 shape_predictor_5_face_landmarks.dat,然后加载它:

p = "shape_predictor_5_face_landmarks.dat"

4. 使用 face_recognition 检测面部特征点

如果想要使用 face_recognition 包检测和绘制面部特征点,需要调用 face_recognition.face_landmarks() 函数:

# 加载图像image = cv2.imread("example.png")image_68 = image.copy()# 将图像从 BGR 颜色转换为 RGB 颜色rgb = image[:, :, ::-1]# 检测 68 个特征点# 第三种面部特征点检测方法,第一行代码face_landmarks_list_68 = face_recognition.face_landmarks(rgb)

此函数返回图像中每张脸的面部特征点(例如,眼睛和鼻子)的字典,如果打印检测到的特征点,则可以看到输出如下:

[{'chin': [(113, 251), (111, 283), (115, 315), (122, 346), (136, 376), (154, 402), (177, 425), (203, 442), (231, 447), (260, 442), (285, 426), (306, 403), (323, 377), (334, 347), (340, 315), (343, 282), (343, 251)], 'left_eyebrow': [(123, 223), (140, 211), (163, 208), (185, 211), (206, 220)], 'right_eyebrow': [(240, 221), (263, 212), (288, 209), (312, 211), (332, 223)], 'nose_bridge': [(225, 249), (225, 272), (225, 295), (226, 319)], 'nose_tip': [(201, 337), (213, 340), (OpenCV-Python实战(15)——面部特征点检测详解(仅需5行代码学会3种面部特征点检测方法) 第2张图片-银狐博客226, 343), (239, 339), (252, 336)], 'left_eye': [(144, 248), (158, 239), (175, 240), (188, 254), (173, 255), (156, 254)], 'right_eye': [(262, 254), (276, 240), (293, 239), (308, 248), (295, 254), (278, 255)], 'top_lip': [(185, 377), (200, 370), (216, 364), (226, 367), (238, 364), (255, 370), (274, 377), (267, 378), (238, 378), (227, 380), (215, 379), (192, 378)], 'bottom_lip': [(274, 377), (257, 391), (240, 399), (228, 400), (215, 398), (200, 391), (185, 377), (192, 378), (215, 381), (227, 382), (239, 380), (267, 378)]}]

最后绘制检测到的特征点:

for face_landmarks in face_landmarks_list_68:    for facial_feature in face_landmarks.keys():        for p in face_landmarks[facial_feature]:            cv2.circle(image_68, p, 2, (255, 255, 0), -1)

face_recognition.face_landmarks() 函数的用法如下:

face_landmarks(face_image, face_locations=None, model="large")

默认情况下会检测到 68 个特征点,如果 model="small",只会检测 5 个特征点:

# 检测 5 个特征点face_landmarks_list_5 = face_recognition.face_landmarks(rgb, None, "small")

如果打印返回的结果 face_landmarks_list_5,可以得到以下输出:

[{'nose_tip': [(227, 343)], 'left_eye': [(145, 248), (191, 253)], 'right_eye': [(307, 248), (262, 252)]}]

在这种情况下,结果字典只包含双眼和鼻尖的面部特征点位置。 接下来,同样绘制检测到的特征点:

for face_landmarks in face_landmarks_list_5:    for facial_feature in face_landmarks.keys():        for p in face_landmarks[facial_feature]:            cv2.circle(image_68, p, 2, (255, 255, 0), -1)

Facemark 在图中,可以看到使用 face_recognition 包检测到的 68 个和 5 个面部特征点。

小结

在本文中,介绍了如何使用 OpenCVFacemark APIdlibshape_predictor() 函数以及 face_recognitionface_landmarks() 函数进行面部特征点检测。

系列链接

OpenCV-Python实战(1)——OpenCV简介与图像处理基础 OpenCV-Python实战(2)——图像与视频文件的处理 OpenCV-Python实战(3)——OpenCV中绘制图形与文本 OpenCV-Python实战(4)——OpenCV常见图像处理技术 OpenCV-Python实战(5)——OpenCV图像运算 OpenCV-Python实战(6)——OpenCV中的色彩空间和色彩映射 OpenCV-Python实战(7)——直方图详解 OpenCV-Python实战(8)——直方图均衡化 OpenCV-Python实战(9)——OpenCV用于图像分割的阈值技术 OpenCV-Python实战(10)——OpenCV轮廓检测 OpenCV-Python实战(11)——OpenCV轮廓检测相关应用 OpenCV-Python实战(12)——一文详解AR增强现实 OpenCV-Python实战(13)——OpenCV与机器学习的碰撞 OpenCV-Python实战(14)——人脸检测详解

赞(0) 打赏
版权声明:本文采用知识共享 署名4.0国际许可协议 [BY-NC-SA] 进行授权
文章名称:《OpenCV-Python实战(15)——面部特征点检测详解(仅需5行代码学会3种面部特征点检测方法)》
文章链接:https://www.yinhu3.com/1680.html
本站资源仅供个人学习交流,请于下载后24小时内删除,不允许用于商业用途,否则法律问题自行承担。
如果文章侵犯到你的权益,请查看本站免责声明:《免责声明》

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

愿意请我喝杯矿泉水吗

支付宝扫一扫打赏