OpenCV函数解读之groupRectangles

不管新版本的CascadeClassifier,还是老版本的HAAR检测函数cvHaarDetectObjects,都使用了groupRectangles函数进行窗口的组合,其函数原型有以下几个:

CV_EXPORTS void groupRectangles(CV_OUT CV_IN_OUT vector<Rect>& rectList, int groupThreshold, double eps=0.2);

CV_EXPORTS_W void groupRectangles(CV_OUT CV_IN_OUT vector<Rect>& rectList, CV_OUT vector<int>& weights, int groupThreshold, double eps=0.2);

CV_EXPORTS void groupRectangles( vector<Rect>& rectList, int groupThreshold, double eps, vector<int>* weights, vector<double>* levelWeights );

CV_EXPORTS void groupRectangles(vector<Rect>& rectList, vector<int>& rejectLevels,

vector<double>& levelWeights, int groupThreshold, double eps=0.2);

CV_EXPORTS void groupRectangles_meanshift(vector<Rect>& rectList, vector<double>& foundWeights, vector<double>& foundScales,

double detectThreshold = 0.0, Size winDetSize = Size(64, 128));

最后一个函数添加mean shift进行组合聚类,下面针对groupRectangles函数进行说明(前三个函数都调用了参数最多的第四个函数实现):

rectList:带组合的窗口,即作为输入又作为输出

rejectLevels:通过分类器的stage数,一般不小于stage总数-4,也就是weights

levelWeights:通过上述stage数的输出权重,也就是通过的stage数的所有node之和,里面即包含left_val又right_val,同一个node只包含其中的一个

groupThreshold:组合阈值,当没有输入rejectLevels的时候,当待合并的窗口数大于该阈值的时候才可能进行合并,否则放弃;当输入rejectLevels的时候,当前组合下通过检测的stage最大值数大于该阈值的时候才可能进行合并,否则放弃

eps:待合并的两个窗口的相关性,从矩形所在位置的像素差值考虑,当eps为0的时候不进行合并,直接返回

该函数的内部执行流程

1) 当组合阈值groupThreshold小于等于0的时候,如果输出weights,则weights中返回与rectList同样个数个1,函数直接返回,不进行合并操作

2) 调用partition函数对rectList中的矩形进行分类

vector<int> labels;

int nclasses = partition(rectList, labels, SimilarRects(eps));

其中nclasses表示组合类别,labels表示每个rect属于哪个类别的,相似度计算使用SimilarRects类

关于partition函数简介:http://docs.opencv.org/modules/core/doc/clustering.html#partition,实现不相交集合数据结构的类别

值得一提的是,该函数的调用必须输入不相交的计算方法,在groupRectangles函数中使用SimilarRects计算相似度,输入参数为eps,相似的矩形是要被分为同一类的

SimilarRect中计算相似度的方法:

inline bool operator()(const Rect& r1, const Rect& r2) const

{

// delta为最小长宽的eps倍

double delta = eps*(std::min(r1.width, r2.width) + std::min(r1.height, r2.height))*0.5;

// 如果矩形的四个顶点的位置差别都小于delta,则表示相似的矩形

return std::abs(r1.x - r2.x) <= delta &&

std::abs(r1.y - r2.y) <= delta &&

std::abs(r1.x + r1.width - r2.x - r2.width) <= delta &&

std::abs(r1.y + r1.height - r2.y - r2.height) <= delta;

}

3) 组合分到同一类别的矩形并保存当前类别下通过stage的最大值以及最大的权重

for( i = 0; i < nlabels; i++ )

{

int cls = labels[i];

rrects[cls].x += rectList[i].x;

rrects[cls].y += rectList[i].y;

rrects[cls].width += rectList[i].width;

rrects[cls].height += rectList[i].height;

rweights[cls]++;

}

for( i = 0; i < nclasses; i++ )

{

Rect r = rrects[i];

float s = 1.f/rweights[i];

rrects[i] = Rect(saturate_cast<int>(r.x*s),

saturate_cast<int>(r.y*s),

saturate_cast<int>(r.width*s),

saturate_cast<int>(r.height*s));

}

for( i = 0; i < nlabels; i++ )

{

int cls = labels[i];

if( (*weights)[i] > rejectLevels[cls] )

{

rejectLevels[cls] = (*weights)[i];

rejectWeights[cls] = (*levelWeights)[i];

}

else if( ( (*weights)[i] == rejectLevels[cls] ) && ( (*levelWeights)[i] > rejectWeights[cls] ) )

rejectWeights[cls] = (*levelWeights)[i];

}

4) 按照groupThreshold合并规则,以及是否存在包含关系输出合并后的矩形

for( i = 0; i < nclasses; i++ )

{

Rect r1 = rrects[i];

int n1 = levelWeights ? rejectLevels[i] : rweights[i];

double w1 = rejectWeights[i];

// 合并的矩形数小于等于组合阈值不进行输出

if( n1 <= groupThreshold )

continue;

// filter out small face rectangles inside large rectangles

for( j = 0; j < nclasses; j++ )

{

int n2 = rweights[j];

if( j == i || n2 <= groupThreshold )

continue;

Rect r2 = rrects[j];

int dx = saturate_cast<int>( r2.width * eps );

int dy = saturate_cast<int>( r2.height * eps );

// 当r1在r2的内部的时候,停止

if( i != j &&

r1.x >= r2.x - dx &&

r1.y >= r2.y - dy &&

r1.x + r1.width <= r2.x + r2.width + dx &&

r1.y + r1.height <= r2.y + r2.height + dy &&

(n2 > std::max(3, n1) || n1 < 3) )

break;

}

// r1不在r2的内部时j才可能等于nclasses

if( j == nclasses )

{

rectList.push_back(r1);

if( weights )

weights->push_back(n1);

if( levelWeights )

levelWeights->push_back(w1);

}

}

感谢:http://blog.csdn.net/xidianzhimeng/article/details/40107763

时间: 2025-01-16 19:46:19

OpenCV函数解读之groupRectangles的相关文章

OpenCV原理解读之HAAR+Adaboost

由于在做人脸检测的项目,用到了OpenCV的训练结果中的老分类器,因此将旧分类器的检测方法进行了总结,加上了一些自己的理解,并转载了一些较好的文章记录下来. 文章http://www.61ic.com/Article/DaVinci/TMS320DM646x/201310/50733.html解决了以下函数移植到DSP上的一些问题 下面为HAAR特征检测的具体流程:http://blog.csdn.net/nongfu_spring/article/details/38977555 一.在计算每

OpenCv函数学习(一)

Intel Image Processing Library (IPL) 1 typedef struct _IplImage 2 { 3 int nSize; /* IplImage大小 */ 4 int ID; /* 版本 (=0)*/ 5 int nChannels; /* 大多数OPENCV函数支持1,2,3 或 4 个通道 */ 6 int alphaChannel; /* 被OpenCV忽略 */ 7 int depth; /* 像素的位深度,主要有以下支持格式: IPL_DEPTH

常用的OpenCV函数速查

常用的OpenCV函数速查 1.cvLoadImage:将图像文件加载至内存: 2.cvNamedWindow:在屏幕上创建一个窗口: 3.cvShowImage:在一个已创建好的窗口中显示图像: 4.cvWaitKey:使程序暂停,等待用户触发一个按键操作: 5.cvReleaseImage:释放图像文件所分配的内存: 6.cvDestroyWindow:销毁显示图像文件的窗口: 7.cvCreateFileCapture:通过参数设置确定要读入的AVI文件: 8.cvQueryFrame:用

[转] matlab调用opencv函数的配置

原文地址百度账户 aleasa123 1.  首先保证vs2010能正确调用opencv函数, 2.  Matlab中选择编译器,操作如下: 打开matlab2012,输入mex –setup,出现如下提示: Welcome to mex -setup. This utility will help you set up a default compiler. For a list of supported compilers, see http://www.mathworks.com/supp

OpenCV2学习笔记(十五):利用Cmake高速查找OpenCV函数源代码

在使用OpenCV时,在对一个函数的调用不是非常了解的情况下,通常希望查到该函数的官方声明.而假设想进一步研究OpenCV的函数,则必须深入到源码. 在VS中我们能够选中想要查看的OpenCV函数,点击右键-> 转到定义.我们能够非常清楚地了解到函数的简单声明,可是并没有给出源码. 这是由于openCV将非常多函数被增加了函数库,并被编译成了dll.所以仅仅能看到函数申明,没法看到源码. 第一个方法:在官网下载OpenCV后须要解压缩,完毕后能够找到OpenCV的解压文件夹打开,在source/

[blog 项目实战派]csharp通过dll调用opencv函数,图片作为参数

?一直想做着方面的研究,但是因为这个方面的知识过于小众,也是由于自己找资料的能力比较弱,知道今天才找到了比较好的资料.一个是thinimage,一个是basework,里面都实现了这里的“csharp通过dll调用opencv函数,并且采用图片作为参数”.这里小结如下. 关于如何“csharp通过dll调用opencv函数”,请参考前面博文,这里主要说如何“采用图片为参数”. 在编写图像识别/增强/机器视觉等项目的时候,一般会将算法打包成dll文件给客户,如果界面是用mfc写的话,是很好实现这个

[blog 项目实战派]csharp通过dll调用opencv函数

[blog 项目实战派]opencv通过dll调用matlab函数,图片作为参数 前文介绍了如何“csharp通过dll调用opencv函数,图片作为参数”.而在实际的代码编写过程中,很多时候想把已经写好的matlab函数融合进去,但是依然是将图片作为参数传递比较成为问题.这里我经过一段时间的研究解决了这个问题(目前只解决了灰度图片下的图片传递问题).这个问题包含几个难点,一个是mxmatrix的使用,一个是matlab和opencv对于图片的格式处理是不一样的. 本次这个项目,是opencv通

matlab调用opencv函数的配置

环境: VS2010 活动解决方案平台x64 WIN 8.1 Opencv 2.4.3 Matlab 2012a 1.  首先保证vs2010能正确调用opencv函数, 2.  Matlab中选择编译器,操作如下: 打开matlab2012,输入mex –setup,出现如下提示: Welcome to mex -setup.  This utility will help you set up a default compiler.  For a list of supported comp

图像增强︱window7+opencv3.2+keras/theano简单应用(函数解读)

在服务器上安装opencv遇到跟CUDA8.0不适配的问题,于是不得不看看其他机器是否可以预装并使用. . 一.python+opencv3.2安装 opencv在windows安装为啥这么简单? 安装流程: 1.下载opencv文件opencv-3.2.0-vc14.exe 2.点击下载,其实就是解压过程,随便放在一个盘里面. 3.python部署阶段, 进入OpenCV的安装目录下找到+复制:\build\python\2.7\x64\cv2.pyd 将cv2.pyd复制到python的子目