Opencv2.4.9源码分析——SimpleBlobDetector.doc
《Opencv2.4.9源码分析——SimpleBlobDetector.doc》由会员分享,可在线阅读,更多相关《Opencv2.4.9源码分析——SimpleBlobDetector.doc(11页珍藏版)》请在冰豆网上搜索。
Opencv2.4.9源码分析——SimpleBlobDetector
OpenCV中提供了SimpleBlobDetector的特征点检测方法,正如它的名称,该算法使用最简单的方式来检测斑点类的特征点。
下面我们就来分析一下该算法。
首先通过一系列连续的阈值把输入的灰度图像转换为一个二值图像的集合,阈值范围为[T1,T2],步长为t,则所有阈值为:
T1,T1+t,T1+2t,T1+3t,……,T2
(1)
第二步是利用Suzuki提出的算法通过检测每一幅二值图像的边界的方式提取出每一幅二值图像的连通区域,我们可以认为由边界所围成的不同的连通区域就是该二值图像的斑点;
第三步是根据所有二值图像斑点的中心坐标对二值图像斑点进行分类,从而形成灰度图像的斑点,属于一类的那些二值图像斑点最终形成灰度图像的斑点,具体来说就是,灰度图像的斑点是由中心坐标间的距离小于阈值Tb的那些二值图像斑点所组成的,即这些二值图像斑点属于该灰度图像斑点;
最后就是确定灰度图像斑点的信息——位置和尺寸。
位置是属于该灰度图像斑点的所有二值图像斑点中心坐标的加权和,即公式2,权值q等于该二值图像斑点的惯性率的平方,它的含义是二值图像的斑点的形状越接近圆形,越是我们所希望的斑点,因此对灰度图像斑点位置的贡献就越大。
尺寸则是属于该灰度图像斑点的所有二值图像斑点中面积大小居中的半径长度。
其中,H表示该斑点的凸壳面积
在计算斑点的面积,中心处的坐标,尤其是惯性率时,都可以应用图像矩的方法。
下面我们就介绍该方法。
矩在统计学中被用来反映随机变量的分布情况,推广到力学中,它被用来描述空间物体的质量分布。
同样的道理,如果我们将图像的灰度值看作是一个二维的密度分布函数,那么矩方法即可用于图像处理领域。
设f(x,y)是一幅数字图像,则它的矩Mij为:
下面给出SimpleBlobDetector的源码分析。
我们先来看看SimpleBlobDetector类的默认参数的设置:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
SimpleBlobDetector:
:
Params:
:
Params()
{
thresholdStep=10;//二值化的阈值步长,即公式1的t
minThreshold=50;//二值化的起始阈值,即公式1的T1
maxThreshold=220;//二值化的终止阈值,即公式1的T2
//重复的最小次数,只有属于灰度图像斑点的那些二值图像斑点数量大于该值时,该灰度图像斑点才被认为是特征点
minRepeatability=2;
//最小的斑点距离,不同二值图像的斑点间距离小于该值时,被认为是同一个位置的斑点,否则是不同位置上的斑点
minDistBetweenBlobs=10;
filterByColor=true;//斑点颜色的限制变量
blobColor=0;//表示只提取黑色斑点;如果该变量为255,表示只提取白色斑点
filterByArea=true;//斑点面积的限制变量
minArea=25;//斑点的最小面积
maxArea=5000;//斑点的最大面积
filterByCircularity=false;//斑点圆度的限制变量,默认是不限制
minCircularity=0.8f;//斑点的最小圆度
//斑点的最大圆度,所能表示的float类型的最大值
maxCircularity=std:
:
numeric_limits:
:
max();
filterByInertia=true;//斑点惯性率的限制变量
//minInertiaRatio=0.6;
minInertiaRatio=0.1f;//斑点的最小惯性率
maxInertiaRatio=std:
:
numeric_limits:
:
max();//斑点的最大惯性率
filterByConvexity=true;//斑点凸度的限制变量
//minConvexity=0.8;
minConvexity=0.95f;//斑点的最小凸度
maxConvexity=std:
:
numeric_limits:
:
max();//斑点的最大凸度
}
我们再来介绍检测二值图像斑点的函数findBlobs。
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
//image为输入的灰度图像
//binaryImage为二值图像
//centers表示该二值图像的斑点
voidSimpleBlobDetector:
:
findBlobs(constcv:
:
Mat&image,constcv:
:
Mat&binaryImage,vector
¢ers)const{
(void)image;
centers.clear();//斑点变量清零
vector>contours;//定义二值图像的斑点的边界像素变量
MattmpBinaryImage=binaryImage.clone();//复制二值图像
//调用findContours函数,找到当前二值图像的所有斑点的边界
findContours(tmpBinaryImage,contours,CV_RETR_LIST,CV_CHAIN_APPROX_NONE);
#ifdefDEBUG_BLOB_DETECTOR
//MatkeypointsImage;
//cvtColor(binaryImage,keypointsImage,CV_GRAY2RGB);
//
//MatcontoursImage;
//cvtColor(binaryImage,contoursImage,CV_GRAY2RGB);
//drawContours(contoursImage,contours,-1,Scalar(0,255,0));
//imshow("contours",contoursImage);
#endif
//遍历当前二值图像的所有斑点
for(size_tcontourIdx=0;contourIdx{
//结构类型Center代表着斑点,它包括斑点的中心位置,半径和权值
Centercenter;//斑点变量
//初始化斑点中心的置信度,也就是该斑点的权值
center.confidence=1;
//调用moments函数,得到当前斑点的矩
Momentsmoms=moments(Mat(contours[contourIdx]));
if(params.filterByArea)//斑点面积的限制
{
doublearea=moms.m00;//零阶矩即为二值图像的面积
//如果面积超出了设定的范围,则不再考虑该斑点
if(area=params.maxArea)
continue;
}
if(params.filterByCircularity)//斑点圆度的限制
{
doublearea=moms.m00;//得到斑点的面积
//计算斑点的周长
doubleperimeter=arcLength(Mat(contours[contourIdx]),true);
//由公式3得到斑点的圆度
doubleratio=4*CV_PI*area/(perimeter*perimeter);
//如果圆度超出了设定的范围,则不再考虑该斑点
if(ratio=params.maxCircularity)
continue;
}
if(params.filterByInertia)//斑点惯性率的限制
{
//计算公式13中最右侧等式中的开根号的值
doubledenominator=sqrt(pow(2*moms.mu11,2)+pow(moms.mu20-moms.mu02,2));
constdoubleeps=1e-2;//定义一个极小值
doubleratio;
if(denominator>eps)
{
//cosmin和sinmin用于计算图像协方差矩阵中较小的那个特征值λ2
doublecosmin=(moms.mu20-moms.mu02)/denominator;
doublesinmin=2*moms.mu11/denominator;
//cosmin和sinmin用于计算图像协方差矩阵中较大的那个特征值λ1
doublecosmax=-cosmin;
doublesinmax=-sinmin;
//imin为λ2乘以零阶中心矩μ00
doubleimin=0.5*(moms.mu20+moms.mu02)-0.5*(moms.mu20-moms.mu02)*cosmin-moms.mu11*si