3.OpenCV目标检测技术

OpevCV目标检测技术

Q1:Qt信号槽connect的第五个参数

A1:

connect(th,SIGNAL(started()),tmpmyobject,SLOT(showID()));

1、Qt::AutoConnection: 默认值,使用这个值则连接类型会在信号发送时决定。如果接收者和发送者在同一个线程,则自动使用。Qt::DirectConnection类型。如果接收者和发送者不在一个线程,则自动使用Qt::QueuedConnection类型。

2、Qt::DirectConnection:槽函数会在信号发送的时候直接被调用,槽函数运行于信号发送者所在线程。效果看上去就像是直接在信号发送位置调用了槽函数。这个在多线程环境下比较危险,可能会造成奔溃。

3、Qt::QueuedConnection:槽函数在控制回到接收者所在线程的事件循环时被调用,槽函数运行于信号接收者所在线程。发送信号之后,槽函数不会立刻被调用,等到接收者的当前函数执行完,进入事件循环之后,槽函数才会被调用。多线程环境下一般用这个。

4、Qt::BlockingQueuedConnection:槽函数的调用时机与Qt::QueuedConnection一致,不过发送完信号后发送者所在线程会阻塞,直到槽函数运行完。接收者和发送者绝对不能在一个线程,否则程序会死锁。在多线程间需要同步的场合可能需要这个。

5、Qt::UniqueConnection:这个flag可以通过按位或(|)与以上四个结合在一起使用。当这个flag设置时,当某个信号和槽已经连接时,再进行重复的连接就会失败。也就是避免了重复连接。

一、帧差法

(一)识别原理

  基于前后两帧图像之间的差异进行对比并获取图像画面中正在运动的物体,从而实现目标检测。

(二)缺点

  画面中所有运动物体均被识别。
  例如:检测车辆运动时,画面中风带动树叶也会被计算在甄别范围内。

二、级联分类器

(一)级联分类器原理

(二) 分类器样本创建

特点:耗时耗资源

样本:正样本和负样本

  一般情况下,样本基数越大,生成的分类器精度越高。如果检测的目标是一个固定物体,没有变化(如特定商标,logo等),这样的物体只要提供一份样本就可以进行训练。 但绝大数时候我们想进行训练的目标是非绝对固定的物体,如对人的检测,包括人脸识别、汽车等等,因此,创建一个合适的样本就十分重要。

正样本

  正样本,只包含检测目标的图片(最好背景一致)。

负样本

  负样本,即不包含检测目标的任何图片

操作步骤

  1. 正样本数据采集(目标检测物照片)

  2. 负样本数据采集(非目标检测物图片)

  3. 调用OpenCV程序opencv_createsample.exe程序实现样本数据采集

  4. 调用OpenCV程序opencv_traincascade.exe样本训练程序进行训练

  5. 生成级联分类器文件

(三)分类器识别流程

1. 创建级联分类器对象

创建并加载级联分类器对象。

//级联分类器加载
CascadeClassifier cascade;
cascade.load("***.xml");//xxx.xml为训练好的级联分类器模型

2. 创建视频流

读取待识别视频路径并显示。

Mat frame;
VideoCapture cap("***");//待检测视频路径
while(cap.read(frame))
{
    
    
    imshow("frame", frame);//显示读取到的视频帧
    detectCarTarget(frame, cascade, 2);//将读取的帧传入函数执行目标检测
    waitKey(25);//帧率
}

3. 视频帧灰度处理

将读取到的视频帧进行灰度处理,压缩数据量,提升传输和计算速度。

//灰度处理:提高图像处理速度
Mat gray;
cvtColor(frame, gray, CV_RGB2GRAY);

4. 压缩多余空通道

  原通道为RGB三通道图片数据,转换为灰度图后,变为单通道数据,多余的通道可以压缩掉,可以看到图片大小缩减至三分之一。

//构建压缩容器
Mat smaller(cvRound(frame.rows/scale), cvRound(frame.cols/scale), CV_8UC1);
//压缩灰度图(线性压缩)
resize(gray, smaller, smaller.size(), 0, 0, INTER_LINEAR);

5. 直方图均值化

直方图均值化:将二次压缩后的灰度图进行对比度调整。

equalizeHist(smaller, smaller);

6. 调用级联分类器

void detectMultiScale( InputArray image,
CV_OUT std::vector & objects,
CV_OUT std::vector& rejectLevels,
CV_OUT std::vector& levelWeights,
double scaleFactor = 1.1,
int minNeighbors = 3, int flags = 0,
Size minSize = Size(),
Size maxSize = Size(),
bool outputRejectLevels = false );


参数1:image–待检测图片,一般为灰度图像加快检测速度。
参数2:objects–被检测物体的矩形框向量组。
参数3:scaleFactor–表示在前后两次相继的扫描中,搜索窗口的比例系数。默认为1.1,即每次搜索窗口依次扩大10%。
参数4:minNeighbors–表示构成检测目标的相邻矩形的最小个数(默认为3个)。
如果组成检测目标的小矩形的个数和小于 min_neighbors - 1 都会被排除。
如果min_neighbors 为 0,则函数不做任何操作就返回所有的被检候选矩形框,这种设定值一般用在用户自定义对检测结果的组合程序上。
参数5:flags–要么使用默认值,要么使用CV_HAAR_DO_CANNY_PRUNING,如果设置为CV_HAAR_DO_CANNY_PRUNING,那么函数将会使用Canny边缘检测来排除边缘过多或过少的区域,因此这些区域通常不会是人脸所在区域。
参数6、7:minSize和maxSize用来限制得到的目标区域的范围。

//保存车辆容器
vector<Rect>cars;

//级联分类器检测 甄别车辆
cascade.detectMultiScale(smaller, cars, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(30,30));

//绘制车辆矩形框
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("resframe", frame);
    

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_46134582/article/details/125702300