上一篇文章中给出了一种对表格进行矫正的方法,但是只能用于只有一个表格的情况,对于有多个表格的情况的矫正的方法,将在这篇文章中给出。
单个表格矫正:链接
(1)Homography(.....)函数返回映射关系H(3*3的矩阵)
CV_EXPORTS_W Mat findHomography(
InputArray srcPoints,
InputArray dstPoints,
int method=0,
double ransacReprojThreshold=3,
OutputArray mask=noArray());
srcPoints,dstPoints是两视图中匹配的点
method 是计算单应矩阵所使用的方法,是一个枚举值。
ransacReprojThreshold 是允许的最大反投影错误,只在使用RANSAC方法时有效。
mask指出匹配的点是不是离群值,用来优化匹配结果。
在这里,我们只用前两个 参数,也就是待矫正的图像的四个点,与模板图像的四个点(这四个点我们取图像中最大的表格的四个角,因为最大的表格比较好找),找出这两个点的映射关系,再通过warpPerspective(....)函数对待矫正的图像进行H映射。
(2)warpPerspective(....)对图像进行变换
void warpPerspective(InputArray src, //输入图像
OutputArray dst, //输出图像
lnputArray M, //透视变换矩阵
Size dsize, //输出图像的大小
int flags=INTER_LINEAR, //输出图像的插值方法
int borderMode=BORDER_CONSTANT, //边界的处理方法
const Scalar& borderValue=Scalar()) //边界的颜色
透视变换矩阵就是H。
第一张是模板图像,第二张是待矫正的图像,我们要找出模板图像的最大的表格,和待矫正的第图像的最大的表格,然后通过两个最大表格的四个顶点得到映射矩阵。
图一
图二
//提取轮廓
vector hierarchy;
std::vector > contours;
cv::findContours(bw, contours, hierarchy, CV_RETR_LIST, CHAIN_APPROX_SIMPLE);
//逼近多边形
vector > contours_poly(contours.size());
//最大的表格的下标和面积
int indexMax = 0;
double areaMax = 0;
for (size_t i = 0; i < contours.size(); i++)
{
//面积
double area = contourArea(contours[i]);
//筛选可能存在且不代表表的单独的行的行。
if (area < 20) // value is randomly chosen
continue;
//逼近区域成为一个形状
approxPolyDP(Mat(contours[i]), contours_poly[i], 10, true);
//找出面积最大的四边形
if (area > areaMax)
{
areaMax = area;
indexMax = i;
}
}
//画出最大的表格的形状
Scalar color(0, 0, 255);
drawContours(srcClone, contours, indexMax, color, 1, 8);
imshow("contou1", srcClone);
waitKey();
std::vector pts_dst;
//将待矫正的表格的四个顶点按顺时针排序
sortPoint(contours_poly[indexMax], pts_dst);
//将模板比表格的四个顶点按照顺时针排序
sortPoint(pts_src, pts_src);
//得到映射函数
Mat h = findHomography(pts_dst, pts_src);
//根据映射函数进行矫正
warpPerspective(src, dst, h, srcImageSize);
矫正后的表格:
相比于第一个方法,这个整体矫正的方法,显然更符合我们项目需要的结果。