级联分类器是一种在图像中检测特定对象(如人脸、眼睛、车辆等)的算法。OpenCV库提供了一个强大的级联分类器实现。
级联分类器的工作原理是将多个简单的分类器(通常是决策树)组合成一个级联结构,每个分类器都会对图像进行评估,并且只有当图像通过这个分类器的测试时,才会继续进行下一个分类器的测试。如果图像在任何阶段失败,那么它就被认为是负样本,不会进行进一步的测试。
如何在QT中使用OpenCV级联分类器呢?在OpenCV中,级联分类器是通过CascadeClassifier
类实现的。以下是如何在OpenCV中使用级联分类器查找人脸的基本步骤:
1.创建对象
(.xml文件是人脸数据模型文件,通过这个文件可以识别到人脸)
2.在图片中查找人脸
detectMultiScale
是 OpenCV 中 CascadeClassifier
类的一个方法,用于在图像中检测不同大小的对象。
void CascadeClassifier::detectMultiScale(
InputArray image,
std::vector<Rect>& objects,
double scaleFactor = 1.1,
int minNeighbors = 3,
int flags = 0,
Size minSize = Size(),
Size maxSize = Size()
)
参数说明:
image
: 输入的图像,可以是灰度图像或者与加载的级联分类器相匹配的彩色图像。objects
: 检测到的对象的矩形框列表,每个矩形框用cv::Rect
表示。(用来存查到的人脸)scaleFactor
: 图像缩放的比例,用于对图像进行多尺度检测。典型的值是 1.1,这意味着每次迭代图像大小都会增加 10%。minNeighbors
: 检测到的对象矩形框要被认为是真正的对象,有多少个重叠的检测标记才被认为有效数字越大识别准确率越高flags
: 这个参数通常设置为 0 或者CASCADE_SCALE_IMAGE
,后者表示图像在每次迭代时都会被缩放。minSize
: 检测窗口的最小大小。如果检测对象非常小,可以设置这个参数来排除太小的对象。maxSize
: 检测窗口的最大大小。如果检测对象非常大,可以设置这个参数来排除太大的对象。
使用 detectMultiScale
方法时,通常需要对图像进行预处理,例如转换为灰度图像,因为大多数预训练的级联分类器都是在灰度图像上训练的。
以下是一个简单的示例,展示如何使用在图片中查找人脸
Mat src = imread("D:/farsight/opencv/testres/head2.jpg"); //打开有人脸的图片
Mat gray;
cvtColor(src, gray, CV_BGR2GRAY); //转灰度图
vector<Rect> faces; //vector容器,用来存储查找到的人脸
CascadeClassifier classifier("D:/opencv/opencv3.4install/install/etc
/haarcascades/haarcascade_frontalface_alt2.xml"); //打开人脸数据模型
classifier.detectMultiScale(gray,faces); //这里只用了两个参数
for(int i = 0;i < faces.size();i++)
{
rectangle(src, faces[i], Scalar(0, 0, 255)); //rectangle为矩形类,给识别到的人脸画一个矩形框
//src为输出图像 faces[i]为输入图像 scalar()为矩形框的颜色
}
imshow("src", src); //展示识别到人脸的图片
3.在摄像头中查找人脸
3.1打开摄像头
VideoCapture
是 OpenCV 库中用于从视频文件、图像序列或摄像头捕获视频流的类。使用 VideoCapture
类,你可以轻松地读取视频帧并进行处理。以下是如何在 OpenCV 中使用 VideoCapture
类的基本步骤:
3.11 创建 VideoCapture 对象
cv::VideoCapture capture;
3.12 打开视频文件或摄像头
// 打开视频文件
capture.open("path/to/your/video/file.mp4");
// 或者打开摄像头,0 通常代表默认摄像头
capture.open(0);
3.13检查视频是否成功打开
if (!capture.isOpened()) {
std::cerr << "Error opening video stream or file" << std::endl;
return -1;
}
3.14 读取视频帧
cv::Mat frame;
while (capture.read(frame)) { // 处理每一帧
cv::imshow("Video Frame", frame); // 显示帧
if (cv::waitKey(30) == 'q') { // 按 'q' 键退出循环
break;
}
}
3.2在摄像头查找人脸并画上矩形框,并用QT的label将摄像头的视频显示出来。
首先把读取到的摄像头图像给frame,然后frame转灰度图gray去识别人脸,识别到的人脸存储在faces容器中,之后在摄像头图像frame画出人脸框,并在label中显示。
(需要提前在UI文件上创建一个label)
cv::VideoCapture capture;
// 打开打开摄像头
capture.open(0);
if (!capture.isOpened()) {
std::cerr << "Error opening video stream or file" << std::endl;
return -1;
}
cv::Mat frame;
vector<Rect> faces; //vector容器,用来存储查找到的人脸
CascadeClassifier classifier("D:/opencv/opencv3.4install/install/etc
/haarcascades/haarcascade_frontalface_alt2.xml"); //打开人脸数据模型
while (capture.read(frame)) { // 摄像头图像加载到frame,每次加载一帧
Mat grey
cvtColor(frame,grey,CV_BGR2GRAY); //转灰度图去识别人脸
//识别人脸
classifier.detectMultiScale(gray,faces,
1.1,3,0,
Size(100,100),
Size(200,200));
cvtColor(frame,frame,CV_BGR2RGB); //OpenCV色彩空间转QT色彩空间
for(int i = 0 ; i < faces.size(); i++)
{
rectangle(frame,faces[i],Scalar(255,0,0));
}
QImage img(frame.data,frame.cols,frame.rows,
frame.cols*frame.channels(),
QImage::Format_RGB888);
ui->label->resize(QSize(frame.cols,frame.rows)); //label大小要和frame大小一样
if (cv::waitKey(30) == 'q') { // 按 'q' 键退出循环
break;
}
}
这里需要把OpenCV(BGR)Mat图片转换成qt(RGB)QImage 图片,不了解的可以看我之前发的Mat在QT的基本使用的文章。然后就能查到人脸并用QT的label将摄像头的视频显示出来。
最后的最后,非常感谢大家的观看,请大家点点赞,点点关注,后续会出OpenCV人脸识别器,
谢谢!