背景:
vs2015+opencv3.4.14
图像中斑点的轮廓提取、轮廓信息自定义保存和对于提取出的轮廓的连接操作。
//寻找轮廓
findContours();
//绘制每个轮廓的最小外接矩形
RotatedRect rect= minAreaRect(contours[i]);
Point2f P[4];//初始化矩形四个顶点坐标
rect.points(P);
for (int i = 0; i < 4; i++)
{
//line(imageContours, P[i], P[(i + 1) % 4], Scalar(255), 2);
}
上面是轮廓提取的关键函数以及最小外接矩形的和其四个顶点的表示。
其中P四个点的位置是后面要着重注意的,弄不清楚后面的操作也就乱了,注意**的图。
1、定义结构体保存轮廓点信息
//定义结构图:轮廓信息
struct P_Rect
{
//提取特征:
//最小外接矩形的质心、长宽、旋转角度
//轮廓面积
int px;
int py;
float pwidth;
float pheight;
float pangle;
float parea;
};
//定义结构图:轮廓外部信息
struct P_Rectout
{
//在一定范围内点的位置,各个距离
int ox;
int oy;
float odistance;
float oarea;
};
//矩形相邻的两个边的长度
float length1= abs(sqrtf(powf((P[0].x - P[1].x), 2) + powf((P[0].y - P[1].y), 2)));
float length2 = abs(sqrtf(powf((P[1].x - P[2].x), 2) + powf((P[1].y - P[2].y), 2)));
//正确找到长边和短边
if (length1 >= length2)
{
p_rect.pwidth = length1;
p_rect.pheight = length2;
p_rect.pangle = cvFastArctan(abs(P[1].y - P[0].y), abs(P[1].x - P[0].x));//指向长的方向的角度,不是矩形原来的角度,矩形原来的角度解析可去 查找findContours函数
}
else
{
p_rect.pwidth = length2;
p_rect.pheight = length1;
if (P[2].x == P[1].x)//使用arctan的注意事项
{
p_rect.pangle = 90;
}
else
{
p_rect.pangle = -abs(cvFastArctan(abs(P[2].y - P[1].y), abs(P[2].x - P[1].x)));
}
}
//中心x和y
p_rect.px=rect.center.x;
p_rect.py = rect.center.y;
//面积,是真实面积不是最小外接矩形面积
p_rect.parea = contourArea(contours[i]);
//保存到容器中
P_rect.push_back(p_rect);
//小于半径范围内点的集合
vector<P_Rectout> p_rectOut;
float r = 20;
for (int j = 0; j < contours.size(