目录
1,原理介绍
2,代码讲解
3,全部代码
4,结果展示
1,原理介绍
haarcascade_frontalface_default.xml
是一个 XML 文件,它包含了使用 Haar 特征分类器训练得到的人脸检测模型。这个模型是 OpenCV 库自带的,常用于实时人脸检测任务。下面详细介绍这个模型的几个方面:
-
Haar 特征: Haar 特征是基于图像的小波特征,它们能够捕捉图像中的局部变化,如边缘、纹理等。这些特征对于物体检测尤其有用,因为它们能够描述物体的某些属性。
-
级联分类器:
haarcascade_frontalface_default.xml
中的模型是一个级联分类器,这意味着它由多个阶段的分类器组成。每个阶段都会对输入图像进行分类,如果图像通过了所有阶段的检测,它就被认为是正面人脸。 -
训练过程: 这个模型是通过在正面人脸和非人脸图像数据集上训练得到的。训练过程中,算法学习区分人脸和非人脸的特征。
-
实时性能: Haar 级联分类器因其计算效率较高,通常用于实时人脸检测。尽管它可能不如深度学习模型那样精确,但在许多实时应用中已经足够使用。
-
使用方式: 在 OpenCV 中,可以使用
CascadeClassifier
类加载这个 XML 文件,并调用detectMultiScale
方法来检测图像或视频流中的人脸。 -
参数调整:
detectMultiScale
方法允许调整多个参数,如缩放因子、邻居窗口的数量、检测的最小和最大邻居尺寸等,以适应不同的检测需求。 -
局限性: Haar 级联分类器可能在复杂场景中表现不佳,例如,当人脸被遮挡或光照条件不佳时。此外,它可能无法很好地处理不同姿态的人脸(如侧面人脸)。
-
可扩展性: 除了正面人脸检测,OpenCV 还提供了其他类型的 Haar 级联分类器,如
haarcascade_profileface.xml
用于检测侧脸,haarcascade_eye.xml
用于检测眼睛等。
2,代码讲解
#include <iostream> #include <opencv2/opencv.hpp>
这两行代码包含了必要的头文件。iostream
是标准输入输出流库,opencv2/opencv.hpp
是 OpenCV 的主头文件。
using namespace std; using namespace cv;
这两行代码使用 std
和 cv
命名空间中的所有名称,这样在调用函数和类型时就不需要前缀。
void face_detect_demo() { // ... }
定义了一个名为 face_detect_demo
的函数,用于执行人脸检测演示。
cv::CascadeClassifier face_cascade;
创建了一个 CascadeClassifier
对象,用于加载和使用级联分类器进行人脸检测。
if (!face_cascade.load("...")) { std::cerr << "Error loading face cascade model!" << std::endl; return; }
尝试加载人脸检测模型(XML 文件)。如果加载失败,输出错误信息并返回。
cv::VideoCapture capture(0);
创建了一个 VideoCapture
对象,尝试打开默认摄像头。
if (!capture.isOpened()) { std::cerr << "Error opening camera!" << std::endl; return; }
检查摄像头是否成功打开,如果失败,输出错误信息并返回。
cv::Mat frame; while (capture.read(frame)) { // ... }
循环读取摄像头的每一帧图像。如果无法读取帧,循环将终止。
cv::cvtColor(frame, gray, cv::COLOR_BGR2GRAY);
将当前帧从 BGR 颜色空间转换为灰度图像。
cv::equalizeHist(gray, gray);
对灰度图像进行直方图均衡化,以提高图像的对比度。
cv::bilateralFilter(gray, dst, 20, 150, 150);
对灰度图像应用双边滤波,以减少噪声并保留边缘。
std::vector<cv::Rect> faces; face_cascade.detectMultiScale(dst, faces, 1.1, 3, 0, cv::Size(30, 30));
使用 CascadeClassifier
对象在图像 dst
中检测人脸,并返回检测到的人脸区域列表。
for (const auto& face : faces) { cv::rectangle(frame, face, cv::Scalar(255, 0, 0), 2); }
遍历检测到的每个人脸区域,并在原始帧图像上绘制蓝色矩形框。
cv::imshow("Face Detection Demo", frame);
在窗口 "Face Detection Demo" 中显示带有人脸标记的帧图像。
if (cv::waitKey(30) == 27) { break; }
等待 30 毫秒的按键事件,如果检测到按键值为 27(ESC 键),则退出循环。
capture.release(); cv::destroyAllWindows();
释放摄像头资源并销毁所有创建的窗口。
int main() { // ... }
程序的入口点。
Mat img = imread("2.png"); if (img.empty()) { cout << "Could not open or find the image" << endl; return -1; }
尝试读取名为 "2.png" 的图像文件。如果文件无法打开或找不到,输出错误信息并返回 -1
。
face_detect_demo();
调用 face_detect_demo
函数执行人脸检测演示。
return 0;
正常退出程序,返回 0
表示成功状态。
3,全部代码
#include <iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
void face_detect_demo()
{
// 加载人脸检测器模型
cv::CascadeClassifier face_cascade;
if (!face_cascade.load("E:/Opencv/opencv/build/etc/haarcascades/haarcascade_frontalface_default.xml"))
{
std::cerr << "Error loading face cascade model!" << std::endl;
return;
}
// 在这里添加进行人脸检测的代码
// 例如,可以在摄像头捕获的每一帧上运行人脸检测
cv::VideoCapture capture(0); // 打开默认摄像头
if (!capture.isOpened())
{
std::cerr << "Error opening camera!" << std::endl;
return;
}
cv::Mat frame;
while (capture.read(frame))
{
// 转换图像为灰度图
cv::Mat gray;
cv::cvtColor(frame, gray, cv::COLOR_BGR2GRAY);
cv::equalizeHist(gray, gray); // 直方图均衡化提高对比度
//进行双边滤波
cv::Mat dst;
cv::bilateralFilter(gray, dst, 20, 150, 150);
// 进行人脸检测
std::vector<cv::Rect> faces;
face_cascade.detectMultiScale(dst, faces, 1.1, 3, 0, cv::Size(30, 30));
// 在图像上标记检测到的人脸
for (const auto& face : faces)
{
cv::rectangle(frame, face, cv::Scalar(255, 0, 0), 2); // 用蓝色矩形标记人脸
}
// 显示结果
cv::imshow("Face Detection Demo", frame);
// 检测按键,按下ESC键退出循环
if (cv::waitKey(30) == 27)
{
break;
}
}
capture.release(); // 释放摄像头
cv::destroyAllWindows(); // 销毁所有窗口
}
int main()
{
Mat img = imread("2.png");
if (img.empty())
{
cout << "Could not open or find the image" << endl;
return -1; //return -1; 通常用作从 main 函数返回一个错误状态码
}
face_detect_demo();
return 0;
}