使用opencv、python、dlib实现人脸关键点检测、眨眼检测和嘴巴开闭检测,可简单用于疲劳检测
- 环境准备
- opencv
- dlib
- 原理
- 眨眼检测
- 张嘴检测原理
- 代码示例
- 人脸关键点检测
- 眨眼检测
- 张嘴检测
- 写在最后
环境准备
opencv
一、简单介绍
OpenCV (Open Source Computer Vision Library) 是一个开源计算机视觉和图像处理库,它提供了大量的工具和算法,涵盖了从基础图像处理到高级计算机视觉任务的各个方面。以下是关于 OpenCV 的一些主要特点和功能:
跨平台性: OpenCV 可以在多个平台上运行,包括 Windows、Linux、macOS、Android 等。
开源: OpenCV 是一个开源项目,任何人都可以查看、使用和修改其源代码,符合 BSD 许可证。
丰富的功能: OpenCV 提供了丰富的功能和算法,包括图像处理、计算机视觉、机器学习、深度学习等领域。
图像处理: OpenCV 提供了用于图像处理的基础功能,如图像读写、颜色空间转换、滤波、形态学操作等。
计算机视觉: OpenCV 包括了大量的计算机视觉算法,例如特征检测与匹配、目标检测、图像分割等。
机器学习: OpenCV 提供了机器学习算法的实现,包括支持向量机 (SVM)、k-最近邻 (k-NN)、决策树等。
深度学习: OpenCV 支持深度学习框架,如 TensorFlow 和 PyTorch,可以进行深度学习模型的加载、预测和微调。
相机标定: OpenCV 提供了相机标定的工具,用于校正相机畸变,获取相机内参和外参等信息。
图像和视频的读写: OpenCV 可以读取和写入各种图像和视频格式,包括 JPEG、PNG、BMP、AVI 等。
实时处理和摄像头支持: OpenCV 支持实时图像处理,可以直接从摄像头中捕获图像,进行实时的计算机视觉任务。
Python 接口: OpenCV 提供了 Python 接口,使得在 Python 中使用 OpenCV 变得非常方便。
社区支持: OpenCV 拥有庞大的社区支持,有着丰富的文档和社区资源,便于用户学习和解决问题。
由于 OpenCV 的强大功能和广泛应用领域,它成为了计算机视觉和图像处理领域中的重要工具之一。许多研究、工业应用和个人项目都采用了 OpenCV 来实现各种图像处理和计算机视觉任务。
二、python安装opencv
可以使用以下命令使用 pip 在 Python 中安装 OpenCV:
pip install opencv-python
dlib
一、简单介绍
dlib 是一个强大的C++工具包,主要用于机器学习、计算机视觉和图像处理任务。它提供了一系列的工具和算法,包括面部检测、关键点检测、人脸识别、对象检测、图像处理等功能。以下是dlib的一些主要特点和功能:
面部检测和关键点检测: dlib 提供了先进的面部检测和关键点检测功能。它可以检测图像中的面部,并标识出面部的关键点,如眼睛、鼻子、嘴巴等。
人脸识别: dlib 提供了人脸识别的工具,可以用于识别图像中的人脸,并进行人脸验证或识别。
形状预测: dlib 可以用于形状预测,即根据检测到的关键点,预测面部或物体的形状。
对象检测: dlib 提供了支持对象检测的工具,可以用于在图像中检测并标识出特定对象。
机器学习算法: dlib 包括一系列的机器学习算法,例如支持向量机(SVM)、k最近邻(k-NN)等,可用于分类、回归和聚类任务。
图像处理: dlib 提供了一些图像处理的功能,包括图像变换、几何变换、颜色空间转换等。
跨平台: dlib 可以在多个平台上运行,包括Windows、Linux和macOS。
开源: dlib 是一个开源项目,可以通过其 GitHub 存储库获取源代码并进行定制。
Python接口: dlib 提供了与Python的接口,可以通过Python调用dlib的功能,便于在Python环境中进行快速开发。
dlib 的灵活性和强大的功能使其在计算机视觉和机器学习社区中得到广泛应用。由于其在人脸检测、关键点检测和人脸识别方面的卓越性能,dlib常被用于人脸相关的应用,如人脸表情识别、眨眼检测、人脸特征生成等。
二、python安装dlib
可以使用以下命令使用 pip 在 Python 中安装 dlib:
pip install dlib
三、shape_predictor_68_face_landmarks.dat
介绍
shape_predictor_68_face_landmarks 是 dlib 库中的一个预训练模型,用于预测面部的 68 个关键点(landmarks)。这些关键点涵盖了面部的各个部位,包括眼睛、鼻子、嘴巴、眉毛等,可以用于进行面部特征分析、姿态估计、表情识别等应用。
这个模型是通过机器学习技术训练得到的,它基于大量带有人工标注关键点的面部图像数据。一旦训练完成,这个模型就可以用于在新的面部图像上进行关键点的预测。
下载
官方下载地址(会比较慢): http://dlib.net/files/
**网盘:**链接:https://pan.baidu.com/s/1jXZyuJvRItECIeNVFdElew?pwd=27r6
提取码:27r6
原理
dlib 生成的面部标志遵循可索引的列表,如下:
眨眼检测
眨眼检测的原理通常涉及对眼睛的状态进行分析,以识别眨眼动作。以下是一种基本的眨眼检测原理:
关键点检测: 使用面部关键点检测算法,例如 dlib 提供的 shape_predictor_68_face_landmarks 模型,检测眼睛区域的关键点。这些关键点通常包括眼睛的轮廓、眼球中心、眉毛等。
计算眼睛的纵横比(Eye Aspect Ratio,EAR): 纵横比是眨眼检测中常用的特征。它是通过计算眼睛的水平方向上的距离与垂直方向上的距离之比得到的。纵横比可用于描述眼睛的形状,而眨眼时,纵横比通常会发生较大的变化。
纵横比的计算公式通常如下:
其中,P1 到 P6 是眼睛轮廓的关键点。
设定眨眼阈值: 通过观察一些样本数据,确定一个适当的纵横比阈值,以便检测到眨眼动作。阈值的设定可能会根据具体应用的要求而变化。
实时监测: 在实时视频或图像中,不断地计算眼睛的纵横比,并与设定的阈值进行比较。当纵横比降低到阈值以下时,可以判定为眨眼动作发生。
张嘴检测原理
关键点检测: 使用面部关键点检测算法,例如 dlib 提供的 shape_predictor_68_face_landmarks 模型,检测嘴巴区域的关键点。这些关键点通常包括嘴巴的轮廓、上下唇的中心、嘴角等。
计算嘴巴的张嘴程度: 通过对关键点进行分析,计算嘴巴的张嘴程度。一种常用的方法是计算嘴巴的纵向距离,即上唇与下唇之间的垂直距离。
嘴巴张嘴程度的计算可以使用以下公式之一:
其中,P51 到 P57 是上嘴唇的关键点,P62 到 P66 是下嘴唇的关键点。
设定张嘴阈值: 通过观察一些样本数据,确定一个适当的张嘴程度阈值,以便检测到张嘴动作。阈值的设定可能会根据具体应用的要求而变化。
实时监测: 在实时视频或图像中,不断地计算嘴巴的张嘴程度,并与设定的阈值进行比较。当嘴巴张嘴程度超过阈值时,可以判定为张嘴动作发生。
代码示例
人脸关键点检测
import cv2
import dlib
# 加载人脸检测器和关键点检测器
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
shape_predictor = dlib.shape_predictor('D:/DownLoad/shape_predictor_68_face_landmarks/shape_predictor_68_face_landmarks.dat')
# 打开摄像头
cap = cv2.VideoCapture(0)
while True:
# 读取一帧
ret, frame = cap.read()
# 将图像转换为灰度图
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 进行人脸检测
faces = face_cascade.detectMultiScale(gray, scaleFactor=1.3, minNeighbors=5, minSize=(30, 30))
# 对每个检测到的人脸进行关键点检测
for (x, y, w, h) in faces:
roi_gray = gray[y:y+h, x:x+w]
rect = dlib.rectangle(x, y, x+w, y+h)
shape = shape_predictor(gray, rect)
# 在图像上绘制人脸关键点
for i in range(68):
cv2.circle(frame, (shape.part(i).x, shape.part(i).y), 2, (0, 255, 0), -1)
# 显示结果
cv2.imshow('Face Landmarks', frame)
# 按下ESC键退出
if cv2.waitKey(1) == 27:
break
# 释放摄像头资源
cap.release()
cv2.destroyAllWindows()
眨眼检测
import cv2
import dlib
import numpy as np
# 加载人脸检测器和关键点检测器
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
shape_predictor = dlib.shape_predictor('D:/DownLoad/shape_predictor_68_face_landmarks/shape_predictor_68_face_landmarks.dat')
# 打开摄像头
cap = cv2.VideoCapture(0)
# 定义一个函数用于计算两个眼睛之间的距离
def eye_aspect_ratio(eye):
eye_np = np.array([[p.x, p.y] for p in eye], dtype=np.float32)
A = np.linalg.norm(eye_np[1] - eye_np[5])
B = np.linalg.norm(eye_np[2] - eye_np[4])
C = np.linalg.norm(eye_np[0] - eye_np[3])
ear = (A + B) / (2.0 * C)
return ear
# 定义一些常量
EYE_AR_THRESH = 0.25 # 眨眼的阈值
EYE_AR_CONSEC_FRAMES = 1 # 检测到闭眼的帧数
# 初始化帧计数器和眼睛状态
frame_counter = 0
eye_closed = False
while True:
# 读取一帧
ret, frame = cap.read()
# 将图像转换为灰度图
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 进行人脸检测
faces = face_cascade.detectMultiScale(gray, scaleFactor=1.3, minNeighbors=5, minSize=(30, 30))
for (x, y, w, h) in faces:
# 提取人脸关键点
rect = dlib.rectangle(x, y, x+w, y+h)
shape = shape_predictor(gray, rect)
# 在图像上绘制关键点
for i in range(68):
cv2.circle(frame, (shape.part(i).x, shape.part(i).y), 2, (0, 255, 0), -1)
# 获取左眼和右眼的关键点坐标
left_eye = shape.parts()[36:42]
right_eye = shape.parts()[42:48]
# 计算眼睛的纵横比
left_ear = eye_aspect_ratio(left_eye)
right_ear = eye_aspect_ratio(right_eye)
# 计算双眼的平均纵横比
ear = (left_ear + right_ear) / 2.0
# 检查是否眼睛状态改变
if ear < EYE_AR_THRESH:
frame_counter += 1
if frame_counter >= EYE_AR_CONSEC_FRAMES:
if not eye_closed:
print("眨眼了")
eye_closed = True
else:
frame_counter = 0
eye_closed = False
# 显示结果
cv2.imshow('Facial Landmarks and Blink Detection', frame)
# 按下ESC键退出
if cv2.waitKey(1) == 27:
break
# 释放摄像头资源
cap.release()
cv2.destroyAllWindows()
张嘴检测
import cv2
import dlib
import numpy as np
import time
# 加载人脸检测器和关键点检测器
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
shape_predictor = dlib.shape_predictor('D:/DownLoad/shape_predictor_68_face_landmarks/shape_predictor_68_face_landmarks.dat')
# 打开摄像头
cap = cv2.VideoCapture(0)
# 定义一个函数用于计算嘴巴的纵横比
def mouth_aspect_ratio(mouth):
mouth_np = np.array([[p.x, p.y] for p in mouth], dtype=np.float32)
A = np.linalg.norm(mouth_np[1] - mouth_np[7])
B = np.linalg.norm(mouth_np[3] - mouth_np[5])
mar = A / B
return mar
# 定义一些常量
MOUTH_AR_THRESH = 2.3 # 张嘴的阈值
MOUTH_AR_CONSEC_FRAMES = 2 # 检测到张嘴的帧数 (30帧/秒 * 1秒)
# 初始化帧计数器和嘴巴状态
frame_counter = 0
start_time = time.perf_counter()
mouth_open = False
while True:
# 读取一帧
ret, frame = cap.read()
# 将图像转换为灰度图
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 进行人脸检测
faces = face_cascade.detectMultiScale(gray, scaleFactor=1.3, minNeighbors=5, minSize=(30, 30))
for (x, y, w, h) in faces:
# 提取人脸关键点
rect = dlib.rectangle(x, y, x+w, y+h)
shape = shape_predictor(gray, rect)
# 获取嘴巴的关键点坐标
mouth = shape.parts()[48:60]
# 计算嘴巴的纵横比
mouth_ar = mouth_aspect_ratio(mouth)
# 在图像上绘制嘴巴关键点
for point in mouth:
cv2.circle(frame, (point.x, point.y), 2, (0, 255, 0), -1)
# 绘制嘴巴区域
mouth_hull = cv2.convexHull(np.array([[p.x, p.y] for p in mouth], dtype=np.int32))
cv2.drawContours(frame, [mouth_hull], -1, (0, 255, 0), 1)
# 检查是否嘴巴状态改变
if mouth_ar > MOUTH_AR_THRESH:
frame_counter += 1
if not mouth_open and frame_counter >= MOUTH_AR_CONSEC_FRAMES:
start_time = time.perf_counter()
mouth_open = True
print("张嘴开始")
else:
if mouth_open:
mouth_open = False
elapsed_time = time.perf_counter() - start_time
print(f"张嘴结束,张嘴时长: {elapsed_time:.2f} 秒")
frame_counter = 0
# 在图像上标识张嘴状态
cv2.putText(frame, f"Mouth Open: {mouth_open}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
# 显示结果
cv2.imshow('Mouth Aspect Ratio Detection', frame)
# 按下ESC键退出
if cv2.waitKey(1) == 27:
break
# 释放摄像头资源
cap.release()
cv2.destroyAllWindows()
写在最后
只是示例代码,不够完美,可以自己调整参数提高检测准确度。