世界杯欧洲区预选赛_世界杯足球几年一次 - chinaacecloud.com



Python人脸识别实战——基于Dlib和OpenCV的人脸识别与关键点检测(附完整代码和结果图)

Python人脸识别实战——基于Dlib和OpenCV的人脸识别与关键点检测(附完整代码和结果图)

关于作者

作者:小白熊

作者简介:精通python、matlab、c#语言,擅长机器学习,深度学习,机器视觉,目标检测,图像分类,姿态识别,语义分割,路径规划,智能优化算法,数据分析,各类创新融合等等。

联系邮箱:xbx3144@163.com

科研辅导、知识付费答疑、个性化定制以及其他合作需求请联系作者~

1 引言

在这篇博文中,博主将展示如何使用Python中的Dlib库对人脸进行关键点检测,并利用OpenCV绘制关键点。人脸关键点检测是计算机视觉领域的一项重要任务。我们可以通过检测人脸上的特定位置(如眼睛、鼻子、嘴唇等)来分析面部特征。在这篇文章中,我们将基于Dlib库的预训练模型shape_predictor_68_face_landmarks.dat,结合OpenCV进行人脸关键点的绘制。

2 模型理论

2.1 人脸识别

人脸识别是定位图像或视频中的人脸的过程。经典的HOG(Histogram of Oriented Gradients,方向梯度直方图)特征提取方法是Dlib中的核心方法之一。

HOG特征:HOG是一种用于对象检测的图像描述方法,它通过统计图像中局部区域的梯度方向来提取物体的形状特征。SVM分类器:Dlib使用支持向量机(SVM)分类器来检测面部,HOG特征被送入SVM分类器进行人脸与非人脸的分类。

Dlib的get_frontal_face_detector()方法基于HOG特征和SVM分类器,能够快速准确地检测出人脸的边界框。

2.2 关键点检测

关键点检测属于回归任务,它根据输入的图像预测人脸上各个特定部位的坐标。Dlib使用的是经典的**回归树(Regression Tree)*算法,具体为*基于局部二值模式(Local Binary Features)特征的回归树模型。

回归树模型:这种模型在初始人脸检测的基础上,通过多次迭代逐步逼近真实的关键点位置。68关键点模型:Dlib提供了一个68个点的模型(shape_predictor_68_face_landmarks.dat),它能够精确定位包括脸部轮廓、眉毛、眼睛、鼻子、嘴唇等部位的68个点。

2.3 工作流程

输入图像:提供一张待检测的图像。人脸检测:使用HOG特征提取与SVM分类器检测人脸的边界框。关键点预测:基于回归树模型,对人脸区域内的68个关键点进行预测。关键点绘制:使用OpenCV对检测到的关键点进行绘制。

3 依赖库

我们需要以下库来实现这一功能:

dlib:用于人脸检测和关键点识别opencv-python:用于加载图像并绘制关键点numpy:用于处理数组和矩阵warnings:用于忽略不必要的警告

可以通过以下命令安装这些库:

pip install opencv-python dlib numpy

4 代码讲解

4.1 导入所需模块

pythonCopy codeimport os

import cv2

import dlib

import numpy as np

import warnings

warnings.filterwarnings("ignore") # 忽略警告

首先需要导入上述模块,并且为了保持输出的清晰性,我们使用warnings.filterwarnings("ignore")来忽略警告信息。

4.2 定义关键点类型及其颜色

pred_types = {

'face': ((0, 17), (0.682, 0.780, 0.909, 0.5)),

'eyebrow1': ((17, 22), (1.0, 0.498, 0.055, 0.4)),

'eyebrow2': ((22, 27), (1.0, 0.498, 0.055, 0.4)),

'nose': ((27, 31), (0.345, 0.239, 0.443, 0.4)),

'nostril': ((31, 36), (0.345, 0.239, 0.443, 0.4)),

'eye1': ((36, 42), (0.596, 0.875, 0.541, 0.3)),

'eye2': ((42, 48), (0.596, 0.875, 0.541, 0.3)),

'lips': ((48, 60), (0.596, 0.875, 0.541, 0.3)),

'teeth': ((60, 68), (0.596, 0.875, 0.541, 0.4))

}

这个字典定义了各部分关键点的范围以及对应的颜色,用于后续绘制。

4.3 绘制关键点和连线的函数

我们定义了两个函数来实现关键点的绘制:

draw_line():用于绘制两个连续关键点之间的直线。draw_line_circle():用于绘制一圈关键点的连线,适用于嘴唇、眼睛等区域。

def draw_line(img, shape, i):

cv2.line(img, (shape.part(i).x, shape.part(i).y),

(shape.part(i + 1).x, shape.part(i + 1).y),

color=(0, 255, 0), thickness=1, lineType=cv2.LINE_AA)

def draw_line_circle(img, shape, i, start, end):

cv2.line(img, (shape.part(i).x, shape.part(i).y),

(shape.part(i + 1).x, shape.part(i + 1).y),

color=(0, 255, 0), thickness=1, lineType=cv2.LINE_AA)

cv2.line(img, (shape.part(start).x, shape.part(start).y),

(shape.part(end).x, shape.part(end).y),

color=(0, 255, 0), thickness=1, lineType=cv2.LINE_AA)

4.4 人脸识别和关键点检测

在dlib_face_keypoint_detector()函数中,我们使用Dlib预训练模型shape_predictor_68_face_landmarks.dat来加载人脸关键点检测模型。然后,我们使用detector来检测图像中的人脸,接着使用predictor来识别人脸的68个关键点。

下载人脸关键点检测模型: http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2

def dlib_face_keypoint_detector(img_path, save_result=True):

detector = dlib.get_frontal_face_detector()

predictor_path = './model/shape_predictor_68_face_landmarks.dat'

predictor = dlib.shape_predictor(predictor_path)

img = cv2.imread(img_path)

dets = detector(img, 1)

for k, d in enumerate(dets):

shape = predictor(img, d)

for i, point in enumerate(shape.parts()):

x, y = point.x, point.y

cv2.circle(img, (x, y), 1, color=(255, 0, 255), thickness=1)

cv2.putText(img, str(i + 1), (x, y), fontFace=cv2.FONT_HERSHEY_SCRIPT_SIMPLEX,

fontScale=0.3, color=(255, 255, 0))

# 连接关键点

if i + 1 < 17: # face

draw_line(img, shape, i)

elif 17 < i + 1 < 22: # eyebrow1

draw_line(img, shape, i)

elif 22 < i + 1 < 27: # eyebrow2

draw_line(img, shape, i)

elif 27 < i + 1 < 31: # nose

draw_line(img, shape, i)

elif 31 < i + 1 < 36: # nostril

draw_line(img, shape, i)

elif 36 < i + 1 < 42: # eye1

draw_line_circle(img, shape, i, 36, 42 - 1)

elif 42 < i + 1 < 48: # eye2

draw_line_circle(img, shape, i, 42, 48 - 1)

elif 48 < i + 1 < 60: # lips

draw_line_circle(img, shape, i, 48, 60 - 1)

elif 60 < i + 1 < 68: # teeth

draw_line_circle(img, shape, i, 60, 68 - 1)

cv2.imshow('detect keypoints', img)

if save_result:

save_filename = img_path.split('.')[0] + '_keypoint.' + img_path.split('.')[1]

cv2.imwrite(save_filename, img)

cv2.waitKey(0)

4.5 运行程序

运行主函数,img_path是待识别图片的路径。

if __name__ == '__main__':

dlib_face_keypoint_detector('./images/test.jpg')

5 结果展示

原图:

运行代码后,程序会在图像上绘制人脸的矩形框和68个关键点。每个关键点将被标注序号,并且相关部分(如眼睛、嘴巴)会被连成线:

6 完整代码

import os

import cv2

import dlib

import numpy as np

import warnings

warnings.filterwarnings("ignore")

pred_types = {'face': ((0, 17), (0.682, 0.780, 0.909, 0.5)),

'eyebrow1': ((17, 22), (1.0, 0.498, 0.055, 0.4)),

'eyebrow2': ((22, 27), (1.0, 0.498, 0.055, 0.4)),

'nose': ((27, 31), (0.345, 0.239, 0.443, 0.4)),

'nostril': ((31, 36), (0.345, 0.239, 0.443, 0.4)),

'eye1': ((36, 42), (0.596, 0.875, 0.541, 0.3)),

'eye2': ((42, 48), (0.596, 0.875, 0.541, 0.3)),

'lips': ((48, 60), (0.596, 0.875, 0.541, 0.3)),

'teeth': ((60, 68), (0.596, 0.875, 0.541, 0.4))

}

def draw_line(img, shape, i):

cv2.line(img, pt1=(shape.part(i).x, shape.part(i).y), pt2=(shape.part(i + 1).x, shape.part(i + 1).y),

color=(0, 255, 0), thickness=1, lineType=cv2.LINE_AA)

def draw_line_circle(img, shape, i, start, end):

cv2.line(img, pt1=(shape.part(i).x, shape.part(i).y), pt2=(shape.part(i + 1).x, shape.part(i + 1).y),

color=(0, 255, 0), thickness=1, lineType=cv2.LINE_AA)

cv2.line(img, pt1=(shape.part(start).x, shape.part(start).y), pt2=(shape.part(end).x, shape.part(end).y),

color=(0, 255, 0), thickness=1, lineType=cv2.LINE_AA)

def dlib_face_keypoint_detector(img_path, save_result=True):

# 检测人脸框

detector = dlib.get_frontal_face_detector()

predictor_path = './model/shape_predictor_68_face_landmarks.dat'

# 检测人脸关键点

predictor = dlib.shape_predictor(predictor_path)

img = cv2.imread(img_path)

print("Processing file: {}".format(img_path))

dets = detector(img, 1)

print("Number of faces detected: {}".format(len(dets)))

for k, d in enumerate(dets):

x1 = d.left()

y1 = d.top()

x2 = d.right()

y2 = d.bottom()

print("Detection {}: Left: {} Top: {} Right: {} Bottom: {}".format(k, x1, y1, x2, y2))

cv2.rectangle(img, (x1, y1), (x2, y2), color=(0, 255, 255), thickness=1, lineType=cv2.LINE_AA)

shape = predictor(img, d)

print(shape.num_parts)

print(shape.rect)

print(

shape.parts())

print("Part 0: {}, Part 1: {} ...".format(shape.part(0), shape.part(1)))

landmarks = np.matrix([[p.x, p.y] for p in shape.parts()])

# 绘制所有的关键点

for i, point in enumerate(shape.parts()):

x = point.x

y = point.y

cv2.circle(img, (x, y), 1, color=(255, 0, 255), thickness=1, lineType=cv2.LINE_AA)

cv2.putText(img, str(i + 1), (x, y), fontFace=cv2.FONT_HERSHEY_SCRIPT_SIMPLEX,

fontScale=0.3, color=(255, 255, 0))

# 连接关键点

if i + 1 < 17: # face

draw_line(img, shape, i)

elif 17 < i + 1 < 22: # eyebrow1

draw_line(img, shape, i)

elif 22 < i + 1 < 27: # eyebrow2

draw_line(img, shape, i)

elif 27 < i + 1 < 31: # nose

draw_line(img, shape, i)

elif 31 < i + 1 < 36: # nostril

draw_line(img, shape, i)

elif 36 < i + 1 < 42: # eye1

draw_line_circle(img, shape, i, 36, 42 - 1)

elif 42 < i + 1 < 48: # eye2

draw_line_circle(img, shape, i, 42, 48 - 1)

elif 48 < i + 1 < 60: # lips

draw_line_circle(img, shape, i, 48, 60 - 1)

elif 60 < i + 1 < 68: # teeth

draw_line_circle(img, shape, i, 60, 68 - 1)

cv2.imshow('detect keypoints', img)

if save_result:

dir, filename = os.path.split(img_path)

save_filename = os.path.join(dir, filename.split('.')[0] + '_keypoint' + '.' + filename.split('.')[1])

cv2.imwrite(save_filename, img)

cv2.waitKey(0)

if __name__ == '__main__':

dlib_face_keypoint_detector('./images/test.jpg')

7 总结

通过这篇文章,我们展示了如何利用Dlib和OpenCV来检测和绘制人脸关键点。这项技术可以广泛应用于人脸识别、表情分析和美颜效果等领域。你可以根据自己的需求进行调整或扩展。如果你有任何问题或建议,欢迎留言讨论!