C++使用opencv调用级联分类器来识别目标物体的详细流程
脚本之家 / 编程助手:解决程序员“几乎”所有问题!
脚本之家官方知识库 → 点击立即使用
使用编译器:Qt Creator 4.2.1
前言:
相较于帧差法捕捉目标物体识别,级联分类器识别目标物体更加具有针对性,使用前者只要是动的物体都会被捕捉识别到,画面里有一点风吹草动,都会被捕捉识别下来,如果我想识别具体的人或者物,都无法做到精准的目标识别,所以有了级联分类器识别(即模型识别),会按照训练好的级联分类器(模型)来进行目标识别
流程讲解:
1.创建一个级联分类器对象
创建一个级联分类器对象,并读取已经已经训练好的模型
1 2 | CascadeClassifier cascade; //级联分类器(模型) cascade.load( "D:/Qt_Opencv_Project/cars.xml" ); //读取级联分类器 |
2.创建一个视频流
读取一个要识别的视频路径
1 2 3 4 5 6 7 8 | Mat frame; VideoCapture cap( "D:/VideoTraining/carMove.mp4" ); while (cap.read(frame)) { imshow( "video" ,frame); //将读到的帧显示出来 datectCarDaw(frame,cascade,2); //将读到的帧传入函数用作识别 waitKey(25); //延时25ms,避免播放过快 } |
3.将传入的视频帧转换为灰度图
转换为灰度图,色彩通道缩小一半,减少图片数据计算量,提升计算速度
效果如下:
4.将多余的空通道进行压缩
原通道为RGB三通道图片数据,转换为灰度图后,变为单通道数据,多余的通道可以压缩掉,可以看到图片减小三分之二
1 2 3 | //再将灰度图缩小一半 Mat smalling(cvRound(frame.rows/scale),cvRound(frame.cols/scale),CV_8UC1); resize(gray,smalling,smalling.size(),0,0,INTER_LINEAR); |
效果如下:
可以发现,图一下子小了很多,大大降低了计算量
5.直方图均衡化
将缩小一半的灰度图进行均衡化,使其更加黑白分明,增强局部的对比度,便于计算机识别
效果如下:
降低了渐进效果的像素数目,更加的黑白分明
6.调用级联分类器,并将内容框出,然后将此帧显示出来
调用读取已经训练好的模型,调用detectMultiScale函数器参数含义为:
待检测的图片帧(此处为均衡化后的图片帧)
被检测物体的矩形向量容器(调用前声明了一个向量容器cars)
每次搜索减小的图像比例(每次缩小1.05倍,扫描的细致一点)
检测目标周围相邻矩形的最小个数(此处设为5个,此处视道路情况可以适当增加个数)
类型(扫描类型)
目标区域可能的最小尺寸(此处为25*25,太小了会识别不到,太大了可能几辆车贴的很近可能只能识别出一辆)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | //调用级联分类器进行模型匹配并框出内容 vector<Rect>cars; //此函数参数说明: 待检测的图片帧 被检测物体的矩形向量容器 每次搜索减小的图像比例 //检测目标周围相邻矩形的最小个数(此处设为2个) 类型 目标区域的大小尺寸 cascade.detectMultiScale(smalling,cars,1.05,5,0|CV_HAAR_SCALE_IMAGE,Size(25,25)); vector<Rect>::const_iterator iter; //绘制方块,标记目标,注意,标记要画在原帧上,要讲方框的大小和帧坐标扩大,因为是根据灰度图识别的,灰度图被缩小了 for (iter=cars.begin();iter!=cars.end();iter++) { rectangle(frame, cvPoint(cvRound(iter->x*scale),cvRound(iter->y*scale)), cvPoint(cvRound((iter->x+iter->width)*scale),cvRound((iter->y+iter->height)*scale)), Scalar(0,255,0),2,8 ); } imshow( "frame" ,frame); |
效果如下:
循环显示每一帧,最终成果展示:
博主所使用的这个模型训练的样本较为有限,主要训练的是普通轿车的车头,车尾训练较少,货车等其他车型没有做特别的训练,所以只能保证识别轿车的车头
可以根据实际车流量和车辆距离摄像头的距离来调整最小目标大小和最大矩形框个数
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | #include <iostream> #include <opencv2/opencv.hpp> using namespace cv; using namespace std; void datectCarDaw(Mat &frame,CascadeClassifier cascade, double scale) { Mat gray; //转换为灰度图,色彩通道缩小一半 cvtColor(frame,gray,CV_RGB2GRAY); //imshow("huidu",gray); //再将灰度图缩小一半 Mat smalling(cvRound(frame.rows/scale),cvRound(frame.cols/scale),CV_8UC1); resize(gray,smalling,smalling.size(),0,0,INTER_LINEAR); //直方图均衡化:将缩小一半的灰度图进行均值化 使其更加黑白分明 equalizeHist(smalling,smalling); //imshow("smalling",smalling); //调用级联分类器进行模型匹配并框出内容 vector<Rect>cars; //此函数参数说明: 待检测的图片帧 被检测物体的矩形向量容器 每次搜索减小的图像比例 检测目标周围相邻矩形的最小个数(此处设为2个) 类型 目标区域的大小尺寸 cascade.detectMultiScale(smalling,cars,1.05,5,0|CV_HAAR_SCALE_IMAGE,Size(25,25)); vector<Rect>::const_iterator iter; //绘制方块,标记目标,注意,标记要画在原帧上,要讲方框的大小和帧坐标扩大,因为是根据灰度图识别的,灰度图被缩小了 for (iter=cars.begin();iter!=cars.end();iter++) { rectangle(frame, cvPoint(cvRound(iter->x*scale),cvRound(iter->y*scale)), cvPoint(cvRound((iter->x+iter->width)*scale),cvRound((iter->y+iter->height)*scale)), Scalar(0,255,0),2,8 ); } imshow( "frame" ,frame); } int main( int argc, char *argv[]) { CascadeClassifier cascade; //级联分类器(模型) cascade.load( "D:/Qt_Opencv_Project/cars.xml" ); //读取级联分类器 //cascade.load("D:/Qt_Opencv_Project/face.xml"); Mat frame; VideoCapture cap( "D:/VideoTraining/carMove.mp4" ); //VideoCapture cap(0); while (cap.read(frame)) { imshow( "video" ,frame); //将读到的帧显示出来 datectCarDaw(frame,cascade,2); //将读到的帧传入函数用作识别 waitKey(25); //延时25ms,避免播放过快 } return 0; } |
有兴趣也可以看看无需使用模型但是只能捕捉动态目标的帧差法识别:
Qt Creator配置使用opencv:
总结
到此这篇关于C++使用opencv调用级联分类器来识别目标物体的文章就介绍到这了,更多相关C++ opencv识别目标物体内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

微信公众号搜索 “ 脚本之家 ” ,选择关注
程序猿的那些事、送书等活动等着你
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 reterry123@163.com 进行投诉反馈,一经查实,立即处理!
相关文章
C/C++ Qt数据库与SqlTableModel组件应用教程
SqlTableModel 组件可以将数据库中的特定字段动态显示在TableView表格组件中,这篇文章将主要介绍SqlTableModel组件一些常用的操作,需要的朋友可以参考一下2021-12-12VSstudio中scanf返回值被忽略的原因及解决方法(推荐)
这篇文章主要介绍了VSstudio中scanf返回值被忽略的原因及其解决方法,scanf返回值被忽略,接下来我就告诉大家该如何解决这个问题,需要的朋友可以参考下2022-09-09
最新评论