环境
- OpenCV 2.4.13
- VS 2015
- 本文完整代码开源在Github
刚开始让我做这个,我也没有什么好的思路,但是随着对OpenCV的文档逐渐熟悉,也查阅了很多资料,对于这个问题,终于有了一个相当不错的解决方法。
常规方法
最初的搜索,会找到一种非常常规的方法:先对图像进行二值化,然后使用霍夫变换,检测出其中的直线,并在直线中,找到围成一个矩形的区域,将这块区域提取出来就好了。
按照这个方法,我最初使用的是Canny + HoughLinesP,检测出的直线效果也看得过去。但是由于我的输入图像是照片,每个照片的明亮不统一,Canny效果并不出众。于是乎我又加了腐蚀和高斯模糊,Canny我也参考Matlab等加了自适应阈值,直线稍微多了些,但也并不好看。
最初的代码是这样的,很小白。
void extractTable(string &argv) {
Mat src = imread(argv), dst;
if (!src.data) {
cout << "not picture" << endl;
}
Mat canny,gray,sobel, edge,erod, blur, color_dst;
double src_height=src.cols, src_width=src.rows;
imshow("source", src);
//先转为灰度
cvtColor(src, gray, COLOR_BGR2GRAY);
//腐蚀(黑色区域变大)
int erodeSize = src_height / 200;
if (erodeSize % 2 == 0)
erodeSize++;
Mat element = getStructuringElement(MORPH_RECT, Size(erodeSize, erodeSize));
erode(gray, erod, element);
//高斯模糊化
int blurSize = src_height / 200;
if (blurSize % 2 == 0)
blurSize++;
GaussianBlur(erod, blur, Size(blurSize, blurSize), 0, 0);
namedWindow("GaussianBlur", WINDOW_NORMAL);
imshow("GaussianBlur", blur);
//自适应阈值Cannyz算法
double low = 0.0, high = 0.0;
AdaptiveFindThreshold(src, &low, &high);
Canny(blur, canny, low, high);
imshow(