一、dlib库简介
dlib是一个包含机器学习算法的现代C++工具包,它提供了丰富的图像处理、人脸识别等功能。在表情识别中,dlib库常被用来进行人脸特征点的检测,这些特征点包括嘴、眼睛、眉毛、鼻子等关键部位的坐标。
二、表情识别
1.基本原理
表情识别主要是通过对人脸表情的显著特征的形状和位置变化进行定位和测量,从而确定其形状、大小、距离及相互比例,进而进行表情的判断。这些显著特征通常包括嘴、眉毛、眼睛等部位的形状和位置变化。
2.表情识别应用
人脸特征点检测:
- 使用dlib库中的get_frontal_face_detector函数初始化人脸检测器。
- 使用shape_predictor函数加载人脸关键点预测模型,该模型通常是一个预训练好的.dat文件,如“shape_predictor_68_face_landmarks.dat”,它包含了68个人脸特征点的信息。
- 对于输入的人脸图像,使用人脸检测器检测人脸,并使用关键点预测器预测人脸的关键点位置。
表情特征提取:
- 在检测到人脸特征点后,可以提取与表情相关的特征值。这些特征值通常包括嘴巴的宽度和高度、眉毛的高度和倾斜程度、眼睛的睁开程度等。
- 这些特征值可以通过计算特征点之间的距离、比例或角度等得到。
表情分类:
- 提取到表情特征后,可以使用机器学习算法对这些特征进行分类,从而识别出具体的表情。
- 常用的机器学习算法包括KNN、SVM、神经网络等。这些算法需要事先使用带有表情标签的数据集进行训练。
3.注意事项
- 在使用dlib库进行表情识别时,需要确保已经正确安装了dlib库和相关的依赖项。
- 人脸特征点的检测精度对表情识别的准确性有很大影响,因此需要使用高质量的预训练模型和合适的参数进行人脸特征点的检测。
- 表情识别的准确性还受到光照、姿态、遮挡等因素的影响,因此在实际应用中需要采取相应的措施来提高识别的鲁棒性。
三、代码实现
这里我们为大家提供了表情识别中微笑识别的代码,下面为大家进行讲解。
1.定义特征函数
import numpy as np
import dlib
import cv2
from sklearn.metrics.pairwise import euclidean_distances
from PIL import Image, ImageDraw, ImageFont
def MAR(shape): # 计算嘴的宽高比
x = shape[50]
y = shape[50].reshape(1, 2)
A = euclidean_distances(shape[50].reshape(1, 2), shape[58].reshape(1, 2))
B = euclidean_distances(shape[51].reshape(1, 2), shape[57].reshape(1, 2))
C = euclidean_distances(shape[52].reshape(1, 2), shape[56].reshape(1, 2))
D = euclidean_distances(shape[48].reshape(1, 2), shape[54].reshape(1, 2))
return ((A + B + C) / 3) / D
def MJR(shape): # 计算嘴宽度与脸颊比
M = euclidean_distances(shape[48].reshape(1, 2), shape[54].reshape(1, 2)) # 嘴宽度
J = euclidean_distances(shape[3].reshape(1, 2), shape[13].reshape(1, 2)) # 下颚的宽度
return M / J
这里我们定义了两个特征函数,分别为MAR与MJR函数,下面是详细解。
- MAR函数:计算嘴的宽高比。它使用欧几里得距离来计算嘴的宽度(嘴角之间的距离的平均值)和高度(上唇和下唇之间的距离)。
- MJR函数:计算嘴宽度与脸颊宽度的比值(Mouth Width to Jaw Ratio)。这里脸颊宽度近似为下颚的宽度。
2.定义添加文本函数
def cv2AddChineseText(img, text, position, textColor=(0, 255, 0), textSize=30):
if (isinstance(img, np.ndarray)):
img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
draw = ImageDraw.Draw(img)
fontStyle = ImageFont.truetype("simkai.ttf", textSize, encoding="utf-8")
draw.text(position, text, textColor, font=fontStyle)
return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)
该函数用于在OpenCV图像上添加中文文本。它首先将NumPy数组(图像)转换为PIL图像,然后使用PIL的ImageDraw和ImageFont在指定位置添加文本,最后将PIL图像转换回NumPy数组。这里cv2AddChineseText函数中使用了一个名为simkai.ttf的字体文件来支持中文显示。字体文件我们可以通过在路径C:\Windows\Fonts中获取,找到想要添加的字体类型,复制到代码目录文件中。
3.主程序
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')
cap = cv2.VideoCapture(0)
初始化人脸检测器和形状预测器,其中形状预测器使用提供的.dat文件(在此例中为shape_predictor_68_face_landmarks.dat)来预测人脸的68个特征点(也称为地标或关键点)。可以通过链接: https://pan.baidu.com/s/13DFQTxHN87AE6o4xAgzGRw?pwd=d37w 提取码: d37w 获取,最后我们打开摄像头。
while True:
ret, frame = cap.read()
faces = detector(frame, 0)
for face in faces:
shape = predictor(frame, face)
shape = np.array([[p.x, p.y] for p in shape.parts()])
mar = MAR(shape) # 计算嘴部宽高比
mjr = MJR(shape) # 计算嘴与脸颊比
result = '正常'
print('mar', mar, '\tmjr', mjr)
if mar > 0.5:
result = '大笑'
elif mjr > 0.45:
result = '微笑'
这里我们通过循环来连续处理从摄像头捕获的每一帧,然后使用人脸检测器检测帧中的人脸,并使用形状检测器获取买个人脸的68个关键点。68个关键点位置大致如下:
再使用列表生成式获取68个关键点的x与y的坐标,将其转换为NumPy数组。提供了高效的数值计算和数组操作功能。最后调用上述定义的特征函数计算嘴部、嘴与脸颊的比值,通过比值判断表情状态。
注意:
关键点图像中
0-16为脸庞边缘关键点;
17-21与22-26为左右眉毛的关键点;
27-35为鼻梁到鼻子的关键点;
36-41与42-47为左右眼睛的关键点;
48-67为嘴唇的关键点。
# frame = cv2AddChineseText(frame,result,(50,100)) # 单人输出中文
mouthHull = cv2.convexHull(shape[48:61]) # 嘴巴绘制凸包
frame = cv2AddChineseText(frame, result, mouthHull[0, 0]) # 多人
cv2.drawContours(frame, [mouthHull], -1, (0, 255, 0), 1)
cv2.imshow('a', frame)
if cv2.waitKey(1) == 27:
break
cv2.destroyAllWindows()
cap.release()
这里我们使用cv2.convexHull来计算嘴巴区域的凸包,然后调用函数在图像上添加中文文本,并使用cv2.drawContours用于在图像上绘制凸包。最后将图像进行展示,然后可以通过ESC键退出循环。
四、总结
本次围绕dlib库的表情识别展开,介绍了表情识别的原理与应用场景,让大家了解了表情识别的作用。然后举例说明表情识别的具体实现,通过对人脸的检测,利用形状检测器描述68个关键点。通过关键点计算特征值,并规定在一定特征值范围内的表情状态,最后为大家展示绘制的凸包和表情状态。通过部分代码为大家展示了表情识别的实现。