最大轮廓和投影
最近非常多的用到了最大轮廓和投影运算。回想起来,这两种算法的确是属于非常常见的基础算法。这里加以总结和提取。
最大轮廓:
前提是图像经过了灰度和阈值处理,也可以直接处理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];
}
调用方法,得到外接矩阵
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;
}
}
目前方向:图像拼接融合、图像识别 联系方式:jsxyhelu@foxmail.com