1、轮廓之外的区域像素置0
根据最小外接矩形,仿射变换至无偏转矩形。外接矩形结构体导出顶点是按顺时针结构排列的,但是起点不定。
int SetExcludeRectZero(Mat & gray, RotatedRect rect)
{
Point2f vertex1[4], vertex2[4]; //定义外接矩形的4个顶点
//定点的排序为逆时针
rect.points(vertex1);
rect.points(vertex2);
int width = rect.size.width;
int height = rect.size.height;
Point2f certer = rect.center;
//修正vertex2,使其无倾斜
for (int k = 0; k < 4; k++)
{
int index1 = k;
int index2 = (k + 1) % 4;
if (vertex2[index1].x < rect.center.x && vertex2[index2].x < rect.center.x)
{
//坐标逆时针排序
vertex2[index1].x = certer.x - width / 2;
vertex2[index1].y = certer.y + height / 2;
vertex2[index2].x = certer.x - width / 2;
vertex2[index2].y = certer.y - height / 2;
index1 = (k + 2) % 4;
index2 = (k + 3) % 4;
vertex2[index1].x = certer.x + width / 2;
vertex2[index1].y = certer.y - height / 2;
vertex2[index2].x = certer.x + width / 2;
vertex2[index2].y = certer.y + height / 2;
break;
}
}
/// 求得仿射变换
Mat warp_dst = gray.clone();
Mat warp_mat = getAffineTransform(vertex1, vertex2);
/// 对源图像应用上面求得的仿射变换
warpAffine(gray, warp_dst, warp_mat, warp_dst.size());
Rect lcdrect(certer.x - width / 2, certer.y - height / 2 - 10, width, height + 30);
Mat lcd = warp_dst(lcdrect).clone();
warp_dst = 0;
lcd.copyTo(warp_dst(lcdrect));
warp_mat = getAffineTransform(vertex2, vertex1);
warpAffine(warp_dst, gray, warp_mat, warp_dst.size());
return 0;
}
2、轮廓匹配
无法跟普通模板匹配一样定位最佳点,轮廓列表逐个匹配找到最匹配的轮廓索引
//CURZR 轮廓匹配找到最佳值
int FindSimilarContours(Mat & img, vector<Point> srccontours, vector<vector<Point>> contourslist, vector<Point>& dstcontours)
{
int index = -1;
double ratio = 100;
Point2f vertex1[4], vertex2[4];
RotatedRect rect1 = minAreaRect(srccontours);
double area1 = rect1.size.width * rect1.size.height;
int width1 = rect1.size.width > rect1.size.height ? rect1.size.width : rect1.size.height;
int height1 = rect1.size.width <= rect1.size.height ? rect1.size.width : rect1.size.height;
rect1.points(vertex1);
int lengthsrc1 = sqrt(pow(vertex1[0].x-vertex1[2].x, 2)+pow(vertex1[0].y-vertex1[2].y, 2));
int lengthsrc2 = sqrt(pow(vertex1[1].x-vertex1[3].x, 2)+pow(vertex1[1].y-vertex1[3].y, 2));
for (int k = 0; k<contourslist.size(); k++)
{
Rect rect = boundingRect(contourslist[k]);
//rectangle(img, rect, Scalar(255,255,255),3);
RotatedRect rect2 = minAreaRect(contourslist[k]);
double area2 = rect2.size.width * rect2.size.height;
int width2 = rect2.size.width>rect2.size.height ? rect2.size.width : rect2.size.height;
int height2 = rect2.size.width<rect2.size.height ? rect2.size.width : rect2.size.height;
rect2.points(vertex2);
for (int i = 0; i < 4; i++)
{
//putText(img, format("%d", i), Point(vertex2[i].x, vertex2[i].y), FONT_HERSHEY_COMPLEX, 2, Scalar(0, 0, 0));
//line(img, vertex2[i], vertex2[(i + 1) % 4], Scalar(0, 255, 0));
}
int lengthdst1 = sqrt(pow(vertex2[0].x - vertex2[2].x, 2) + pow(vertex2[0].y - vertex2[2].y, 2));
int lengthdst2 = sqrt(pow(vertex2[1].x - vertex2[3].x, 2) + pow(vertex2[1].y - vertex2[3].y, 2));
if (lengthsrc1<lengthdst1*1.5 && lengthsrc1>lengthdst1*0.5 && lengthsrc2<lengthdst2*1.5 && lengthsrc2>lengthdst2*0.5)
{
//drawContours(img, contourslist, k, Scalar(255, 0, 255));
double ret = matchShapes(srccontours, contourslist[k], CV_CONTOURS_MATCH_I1, 0);
if (ret<ratio)
{
ratio = ret;
index = k;
}
}
}
if (index<0)
{
return index;
}
dstcontours = contourslist[index];
//imshow("img", img);
//waitKey();
return 0;
}