摘要
在机器视觉中,对于图像的处理有时候因为放置的原因导致ROI区域倾斜,这个时候我们会想办法把它纠正为正确的角度视角来,方便下一步的布局分析与文字识别,这个时候通过透视变换就可以取得比较好的裁剪效果。
本次实战,对于图像的矫正使用了两种矫正思路:
- 针对边缘比较明显的图像,使用基于轮廓提取的矫正算法。
- 针对边缘不明显,但是排列整齐的文本图像,使用了基于霍夫直线探测的矫正算法。
基于轮廓提取的矫正算法
整体思路:
- 图片灰度化,二值化
- 检测轮廓,并筛选出目标轮廓(通过横纵比或面积去除干扰轮廓)
- 获取目标轮廓的最小外接矩形
- 获取最小外接矩形的四顶点,并定义矫正图像后的四顶点
- 透视变换(四点变换)
opencv实现(分解步骤):
(一)图片灰度化,二值化(开运算,消除噪点)
Mat src = imread("D:/opencv练习图片/图片矫正.png"); imshow("原图片", src); // 二值图像 Mat gray, binary; cvtColor(src, gray, COLOR_BGR2GRAY); threshold(gray, binary, 0, 255, THRESH_BINARY_INV| THRESH_OTSU); imshow("二值化", binary); // 定义结构元素 Mat se = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1)); morphologyEx(binary, binary, MORPH_OPEN, se); imshow("开运算", binary);
注意:由于原图像背景是白色,因此二值化时候要用THRESH_BINARY_INV
(二)提取轮廓,筛选轮廓
// 寻找最大轮廓 vector<vector<Point>> contours; findContours(binary, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE); int index = -1; int max = 0; for (size_t i = 0; i < contours.size(); i++) { double area = contourArea(contours[i]); if (area > max) { max = area; index = i; } }
(三)求取最小外接矩形以及四顶点坐标,并定义变换后的四顶点坐标
// 寻找最小外接矩形 RotatedRect rect = minAreaRect(contours[index]); Point2f srcpoint[4];//存放变换前四顶点 Point2f dstpoint[4];//存放变换后四顶点 rect.points(srcpoint);//获取最小外接矩形四顶点坐标 //显示顶点 for (size_t i = 0; i < 4; i++) { circle(src, srcpoint[i], 5, Scalar(0, 0, 255),-1);//-1表示填充 } imshow("顶点坐标", src); //获取外接矩形宽高 float width = rect.size.width; float height = rect.size.height; //定义矫正后四顶点 dstpoint[0]= Point2f(0, height); dstpoint[1] = Point2f(0, 0); dstpoint[2] = Point2f(width, 0); dstpoint[3] = Point2f(width, height);