最大轮廓和投影
最近非常多的用到了最大轮廓和投影运算。回想起来,这两种算法的确是属于非常常见的基础算法。这里加以总结和提取。
最大轮廓:
前提是图像经过了灰度和阈值处理,也可以直接处理canny的结果,有些时候需要预先经过色彩域的转换。最后得到的结果,应该是一个contour,当然可以采用一定的方法处理得到外接矩形。
//寻找最大的轮廓
vector <cv : :Point > FindBigestContour(Mat src)
{
int imax = 0; //代表最大轮廓的序号
int imaxcontour = - 1; //代表最大轮廓的大小
std : :vector <std : :vector <cv : :Point >>contours;
findContours(src,contours,CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE);
for ( int i = 0;i <contours.size();i ++)
{
int itmp = contourArea(contours[i]); //这里采用的是轮廓大小
if (imaxcontour < itmp )
{
imax = i;
imaxcontour = itmp;
}
}
return contours[imax];
}
vector <cv : :Point > FindBigestContour(Mat src)
{
int imax = 0; //代表最大轮廓的序号
int imaxcontour = - 1; //代表最大轮廓的大小
std : :vector <std : :vector <cv : :Point >>contours;
findContours(src,contours,CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE);
for ( int i = 0;i <contours.size();i ++)
{
int itmp = contourArea(contours[i]); //这里采用的是轮廓大小
if (imaxcontour < itmp )
{
imax = i;
imaxcontour = itmp;
}
}
return contours[imax];
}
调用方法,得到外接矩阵
Rect boundRect = boundingRect(Mat(FindBigestContour(canny)));
投影处理
:
这里的前提和最大轮廓是非常相似的。投影主要关心的是通过投影图像,获得原始图像中的ROI,或者获得有多少个上波形多少个下波形这些定量的结果。
Vector < int > vectorV; //横向循环
Vector < int > vectorH; //纵向循环
Vector < int > VUpper;
Vector < int > VDown;
vector < int > HUpper;
vector < int > HDower;
// 做横向循环
for ( int i = 0;i <ostu.cols;i ++)
{
Mat data = ostu.col(i);
int itmp = countNonZero(data);
vectorV.push_back(itmp);
}
//上波形为VUpper,下波形为VDown
for ( int i = 1;i <vectorV.size();i ++)
{
if (vectorV[i - 1] == 0 && vectorV[i] > 0)
{
VUpper.push_back(i);
}
if (vectorV[i - 1] > 0 && vectorV[i] == 0)
{
VDown.push_back(i);
}
}
//做纵向循环,这个往往处理的是横向循环的结果图片
for ( int j = 0;j <ostu.rows;j ++)
{
Mat data = roitmp.row(j);
int itmp = countNonZero(data);
vectorH.push_back(itmp);
}
for ( int j = 0;j <vectorH.size() - 1;j ++)
{
if (vectorH[j] > 0 && vectorH[j + 1] == 0)
{
HDower.push_back(j);
}
if (vectorH[j] == 0 && vectorH[j + 1] > 0)
{
HUpper.push_back(j);
}
}
//由于处理的上波形和下波形可能会有问题,需要进行一定的处理
//这里的一个处理就是提出哪些短暂的空白区域
for ( int j = 0;j <HDower.size() - 1;j ++)
{
//得出之间空白的区域
int iwidth = HUpper[j + 1] - HDower[j];
if (iwidth > 10)
{
iresult = iresult + 1;
}
}