今天来说一下怎么样将这个旋转的文本框矫正,大体思路:
二值化分割+边缘检测+最大外接矩形+透视变换 => 最终图像
ps: 本人用word画的测试图像,另外是基于opencv3.3+vs2015
首先读入图片,并且灰度转换
g_src = imread("rotate.png");
if (g_src.empty())
{
cout << "无法打开图片";
return -1;
}
//imshow("原始图片", g_src);
cvtColor(g_src, g_img_gray,COLOR_BGR2GRAY);
namedWindow(NAMEWINDOW1, WINDOW_AUTOSIZE);
创建一个滑动条,进行二值化找到阈值
createTrackbar("阈值", NAMEWINDOW1, &threshold_value, threshold_max, On_threshold);
On_threshold(0, 0);
能很明显的看到矩形轮廓,接下来进行轮廓查找
vector<Vec4i>hierarchy;
vector<vector<Point>>contours;
findContours(img_thres, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);
for (int i = 0;i < contours.size();i++)
{
Point2f vertices[4]; //用来存放旋转矩形四个顶点
RotatedRect mr = minAreaRect(Mat(contours[i]));
if (VerifySize(mr)) //验证是否是所需要尺寸
这是验证尺寸的函数
bool VerifySize(RotatedRect candidate)
{
float minError = 0.4; //40%的误差范围
float maxError = 0.8; //80%的误差范围
float srcArea = g_src.rows*g_src.cols;
float area = candidate.size.height*candidate.size.width;
if (area > (srcArea*minError) && area < (srcArea*maxError))
return true;
else
return false;
}
本来我们只需要根据边缘寻找最小外接矩形,验证尺寸是否是我们想要的,就可以了
但是遇到很一个问题,也是我自己作死,用word画图,他会出现以下情况:
你以为只有一个矩形框?那就错了,其实它是类似这样的:
两个矩形框基本重叠在一起,我试着输出了一下矩形四个顶点
会发现这两个矩形四个顶点非常接近,所以我们需要修改算法,剔除掉其中一个,算法思路:
把矩形四个顶点一一对应相减得到差值,算出距离,如果距离小于某个值,说明这四个顶点是非常接近的,
可以算出矩形周长,