基于OpenCV构建人脸检测与跟踪系统
在机器人编程领域,人脸检测与跟踪是一项非常重要的技术。本文将详细介绍如何使用OpenCV实现人脸、眼睛检测以及微笑识别功能。
1. 技术要求
在开始之前,你需要准备以下设备和文件:
- 三个LED灯
- 搭载树莓派相机模块的树莓派(RPi)机器人
- 相关代码文件可从 此处 下载
2. 基于Haar级联的人脸检测
2001年,Paul Viola和Micheal Jones在论文中提出了基于Haar特征的级联分类器,也被称为Viola - Jones算法。该分类器使用人脸图像和非人脸图像进行训练,不仅可以检测正面人脸,还能检测人的眼睛、嘴巴和鼻子。
2.1 Viola - Jones算法的基本原理
Viola - Jones算法使用Haar特征来检测人脸,Haar特征主要包括边缘特征和线条特征:
- 边缘特征 :用于检测边缘,由白色和黑色像素组成,可进一步分为水平边缘特征和垂直边缘特征。
- 线条特征 :用于检测线条,白色像素夹在两个黑色像素之间,或者黑色像素夹在两个白色像素之间。
人脸检测通常在灰度图像上进行,因为在灰度图像中,不同面部区域的亮度不同。例如,额头区域比眉毛区域亮,鼻梁区域比眼睛和脸颊区域亮,上唇区域较暗,牙齿区域较亮,下唇区域又较暗。通过利用Haar级联的边缘和线条特征,我们可以检测人脸中最相关的特征点,如眼睛、鼻子和嘴巴。
OpenCV 4.0包含不同的预训练Haar检测器,可用于检测人脸及其眼睛、鼻子、微笑等。在 Opencv - 4.0.0 文件夹的 Data 文件夹中,有一个 haarcascades 文件夹,其中包含不同的Haar级联分类器。对于正面人脸检测,我们将使用 haarcascade_frontalface_alt2.xml 检测器。
2.2 人脸检测程序
以下是编写人脸检测程序的步骤:
1. 加载预训练的Haar正面人脸XML文件 :
CascadeClassifier faceDetector("haarcascade_frontalface_alt2.xml");
- 声明矩阵变量和视频捕获变量 :
Mat videofeed, grayfeed;
VideoCapture vid(0);
- 读取相机馈送,翻转图像并转换为灰度 :
vid.read(videofeed);
flip(videofeed, videofeed, 1);
cvtColor(videofeed, grayfeed, COLOR_BGR2GRAY);
- 进行直方图均衡化 :
equalizeHist(grayfeed, grayfeed);
- 使用
detectMultiScale函数检测人脸 :
detectMultiScale(image, object, scalefactor, min neighbors, flags, min size, max size);
该函数的参数说明如下:
| 参数 | 说明 |
| ---- | ---- |
| image | 输入视频馈送,这里是 grayfeed |
| object | 包含检测到的人脸的矩形向量 |
| scalefactor | 图像尺寸缩小的比例,理想值在1.1到1.3之间 |
| flags | 可设置为 CASCADE_SCALE_IMAGE 、 CASCADE_FIND_BIGGEST_OBJECT 、 CASCADE_DO_ROUGH_SEARCH 或 CASCADE_DO_CANNY_PRUNING |
| min neighbors | 影响检测到的人脸质量,理想值在3到5之间 |
| min size | 检测的最小人脸尺寸,理想值为30 x 30像素 |
| max size | 检测的最大人脸尺寸 |
- 声明矩形向量并进行人脸检测 :
vector<Rect> face;
faceDetector.detectMultiScale(grayfeed, faces, 1.3, 5, 0 | CASCADE_SCALE_IMAGE, Size(30, 30));
- 在检测到的人脸周围绘制矩形并显示文本 :
for (size_t f = 0; f < face.size(); f++)
{
rectangle(videofeed, face[f], Scalar(255, 0, 0), 2);
putText(videofeed, "Face Detected", Point(face[f].x, face[f].y), FONT_HERSHEY_PLAIN, 1.0, Scalar(0, 255, 0), 2.0);
}
- 显示视频馈送 :
imshow("Face Detection", videofeed);
3. 眼睛和微笑检测
接下来,我们将检测人的眼睛并识别微笑。相关程序 SmilingFace.cpp 可从上述GitHub链接下载。
3.1 眼睛检测
OpenCV 4.0有三种主要的眼睛级联分类器:
- haarcascade_eye.xml :同时检测两只眼睛
- haarcascade_lefteye_2splits.xml :仅检测左眼
- haarcascade_righteye_2splits.xml :仅检测右眼
以下是使用不同分类器进行眼睛检测的步骤:
使用 haarcascade_eye 检测眼睛 :
1. 加载分类器 :
CascadeClassifier eyeDetector("haarcascade_eye.xml");
- 找到人脸区域 :
Mat faceroi = videofeed(face[f]);
- 检测眼睛区域 :
vector<Rect> eyes;
eyeDetector.detectMultiScale(faceroi, eyes, 1.3, 5, 0 | CASCADE_SCALE_IMAGE, Size(30, 30));
- 在眼睛周围绘制圆圈 :
for (size_t e = 0; e < eyes.size(); e++)
{
Point eyecenter(face[f].x + eyes[e].x + eyes[e].width / 2, face[f].y + eyes[e].y + eyes[e].height / 2);
int radius = cvRound((eyes[e].width + eyes[e].height) * 0.20);
circle(videofeed, eyecenter, radius, Scalar(0, 0, 255), 2);
}
使用 haarcascade_lefteye_2splits 和 haarcascade_righteye_2splits 分别检测左眼和右眼 :
- 检测左眼 :
CascadeClassifier eyeDetectorleft("haarcascade_lefteye_2splits.xml");
Mat faceroi = videofeed(face[f]);
vector<Rect> lefteye;
eyeDetectorleft.detectMultiScale(faceROI, lefteye, 1.3, 25, 0 | CASCADE_SCALE_IMAGE, Size(30, 30));
for (size_t le = 0; le < lefteye.size(); le++)
{
Point center(face[f].x + lefteye[le].x + lefteye[le].width * 0.5, face[f].y + lefteye[le].y + lefteye[le].height * 0.5);
int radius = cvRound((lefteye[le].width + lefteye[le].height) * 0.20);
circle(videofeed, center, radius, Scalar(0, 0, 255), 2);
}
- 检测右眼 :
CascadeClassifier eyeDetectorright("haarcascade_righteye_2splits.xml");
Mat faceroi = videofeed(face[f]);
vector<Rect> righteye;
eyeDetectorright.detectMultiScale(faceROI, righteye, 1.3, 25, 0 | CASCADE_SCALE_IMAGE, Size(30, 30));
for (size_t re = 0; re < righteye.size(); re++)
{
Point center(face[f].x + righteye[re].x + righteye[re].width * 0.5, face[f].y + righteye[re].y + righteye[re].height * 0.5);
int radius = cvRound((righteye[re].width + righteye[re].height) * 0.20);
circle(videofeed, center, radius, Scalar(0, 255, 0), 2);
}
通过以上步骤,我们可以实现人脸、眼睛的检测以及微笑的识别。在实际应用中,可以根据具体需求调整参数,以获得更好的检测效果。
以下是人脸检测和眼睛检测的流程图:
graph TD;
A[开始] --> B[加载Haar分类器];
B --> C[捕获视频馈送];
C --> D[翻转并转换为灰度图像];
D --> E[直方图均衡化];
E --> F[检测人脸];
F --> G{是否检测到人脸};
G -- 是 --> H[绘制人脸矩形并显示文本];
H --> I[检测眼睛];
I --> J{是否检测到眼睛};
J -- 是 --> K[在眼睛周围绘制圆圈];
K --> L[显示视频馈送];
L --> C;
G -- 否 --> C;
J -- 否 --> C;
通过这个流程图,我们可以清晰地看到整个检测过程的步骤和逻辑。从开始加载分类器,到捕获视频、处理图像、检测人脸和眼睛,最后显示结果,形成了一个循环的检测系统。
3.2 微笑识别
在检测到人脸和眼睛后,我们还可以进行微笑识别。当网络摄像头检测到嘴巴周围有黑白黑的线条特征时,即上唇和下唇比牙齿区域颜色深时,就会识别出微笑的人脸。
以下是实现微笑识别的编程步骤:
1. 加载微笑级联分类器 :
CascadeClassifier smileDetector("haarcascade_smile.xml");
- 找到人脸区域(感兴趣区域) :
Mat faceroi = videofeed(face[f]);
- 声明微笑检测的矩形向量并进行检测 :
vector<Rect> smile;
smileDetector.detectMultiScale(faceroi, smile, 1.3, 25, 0 | CASCADE_SCALE_IMAGE, Size(30, 30));
这里将 min neighbors 设置为25,这样只有当人微笑时才会创建圆圈。你可以在25 - 35之间调整该值。
4. 在嘴巴周围绘制绿色圆圈 :
for (size_t s = 0; s < smile.size(); s++)
{
Point center(face[f].x + smile[s].x + smile[s].width * 0.5, face[f].y + smile[s].y + smile[s].height * 0.5);
int radius = cvRound((smile[s].width + smile[s].height) * 0.20);
circle(videofeed, center, radius, Scalar(0, 255, 0), 2);
}
4. 参数调整与注意事项
在使用上述检测功能时,各个参数的设置对检测效果有重要影响,以下是一些关键参数的调整建议和注意事项:
| 参数 | 影响 | 建议值 |
| ---- | ---- | ---- |
| scalefactor | 图像尺寸缩小比例,值越大,图像缩小越快,检测速度可能加快,但可能遗漏小目标 | 1.1 - 1.3 |
| min neighbors | 影响检测到的目标质量,值越大,检测到的目标越准确,但可能漏检;值越小,可能检测到更多目标,但可能误检 | 人脸检测:3 - 5;眼睛检测:5;微笑检测:25 - 35 |
| min size | 检测的最小目标尺寸,小于该尺寸的目标将被忽略 | 30 x 30像素 |
| max size | 检测的最大目标尺寸,大于该尺寸的目标将被忽略 | 根据实际情况设置 |
同时,要确保相关的XML文件(如 haarcascade_frontalface_alt2.xml 、 haarcascade_eye.xml 等)与代码文件在同一文件夹中,否则会导致分类器加载失败。
5. 总结
本文详细介绍了如何使用OpenCV实现人脸、眼睛检测以及微笑识别功能。通过使用Haar级联分类器,我们可以方便地在图像或视频中检测出目标。整个过程包括加载分类器、捕获视频、处理图像、检测目标以及绘制标记等步骤。
以下是完整的检测流程总结:
1. 加载所需的Haar级联分类器(人脸、眼睛、微笑)。
2. 初始化视频捕获设备。
3. 循环读取视频帧。
- 翻转并将视频帧转换为灰度图像。
- 进行直方图均衡化以提高图像质量。
- 检测人脸。
- 如果检测到人脸,在人脸周围绘制矩形并显示文本。
- 在人脸区域内检测眼睛。
- 如果检测到眼睛,在眼睛周围绘制圆圈。
- 在人脸区域内检测微笑。
- 如果检测到微笑,在嘴巴周围绘制圆圈。
4. 显示处理后的视频帧。
通过合理调整参数和优化代码,我们可以提高检测的准确性和效率,使系统在不同的场景下都能有良好的表现。希望本文能为你在人脸检测与跟踪领域的开发提供有价值的参考。
以下是包含微笑识别的完整流程图:
graph TD;
A[开始] --> B[加载Haar分类器(人脸、眼睛、微笑)];
B --> C[捕获视频馈送];
C --> D[翻转并转换为灰度图像];
D --> E[直方图均衡化];
E --> F[检测人脸];
F --> G{是否检测到人脸};
G -- 是 --> H[绘制人脸矩形并显示文本];
H --> I[检测眼睛];
I --> J{是否检测到眼睛};
J -- 是 --> K[在眼睛周围绘制圆圈];
K --> L[检测微笑];
L --> M{是否检测到微笑};
M -- 是 --> N[在嘴巴周围绘制圆圈];
N --> O[显示视频馈送];
O --> C;
G -- 否 --> C;
J -- 否 --> L;
M -- 否 --> O;
这个流程图展示了从开始到完成人脸、眼睛和微笑检测的完整过程,涵盖了各个检测步骤和条件判断,有助于我们更清晰地理解整个系统的工作逻辑。
超级会员免费看
2001

被折叠的 条评论
为什么被折叠?



