本文由@星沉阁冰不语出品,转载请注明作者和出处。

文章链接:http://blog.csdn.net/xingchenbingbuyu/article/details/50783585

微博:http://weibo.com/xingchenbing 

本文部分参考自如下链接:Sudoku-recognizer。前几天发现了这个网页,觉得挺好玩的,就想自己实现一下。本以为只是把代码从Python转换到C++是一件很简单的事情,经过这几天的努力发现是自己想的太简单了。到现在也没有完全实现。前面的一小半可以说是参考了上述文章,所做的只是把opencv的代码转换下语言风格,但是到了后面随着Python语言用的越来越多,很多地方已经完全看不懂了,只能自己实现。而且随着深入,自己的想法也越来越多。所以现在几乎已经跳出上文的框架,开始自己去查资料查文档按照自己的思路实现了。但是考虑到完全实现耗时过长而且不确定什么时候能调试完成,加之如果等一切搞定再来记录将会是一篇十分冗长的博文,于是就这样一边实现一边记录吧。先从最基础的开始。

还是先说要实现什么样的效果吧。给一张带有九宫格数独的照片,检测出其中的九宫格,然后取出来做透视变换。看图的画会更加一目了然。

主要思路:

一、高斯滤波去掉部分噪音,拉普拉斯锐化增强轮廓以便于检测提取;自适应阈值化得到二值图像;

二、轮廓检测,多边形逼近,多边形筛选;

三、根据筛选出的四边形的四个顶点进行透视变换(顶点顺序很重要);

这里面需要注意的细节有以下几点:

一、自适应阈值化的时候最后两个参数的调整特别重要,这两个参数决定着能不能快速检测到需要的轮廓。如果找不到,就继续调整这俩值。

二、findContours()查找轮廓时,方法选取CV_CHAIN_APPROX_SIMPLE,这种方法只是存储轮廓的顶点,后面透视变换时用到的顶点就是从这里面提出来的。

三、轮廓筛选的时候可以用上述顶点数来选出四边形,然后根据面积筛选出目标四边形。

四、透视变换的时候顶点的对应顺序要正确,最好按照左上,右上,左下,右下的顺序。变换前后都是这个顺序。

五、获取透视变换矩阵的时候用到的点的格式应为Point2f,变换矩阵是一个3*3的矩阵,我得到的变换矩阵如下:

这一部分主要代码如下:

#include<opencv.hpp>
#include<iostream>using namespace std;
using namespace cv;int main()
{Mat src = imread("shudu.jpg");GaussianBlur(src, src, Size(3, 3), 0, 0);//拉普拉斯锐化Mat kernel(3, 3, CV_32F, Scalar(-1));kernel.at<float>(1, 1) = 8.9;filter2D(src, src, src.depth(), kernel);Mat gray, thresh;cvtColor(src, gray, CV_BGR2GRAY);//namedWindow("thresh",0);//轮廓提取adaptiveThreshold(gray, thresh, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY_INV,77,15);Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));erode(thresh, thresh, element);dilate(thresh, thresh, element);vector<vector<Point> > contours0;vector<Vec4i> hierarchy;findContours(thresh, contours0, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point());//多边形逼近vector<vector<Point> > contours;contours.resize(contours0.size());for (int i = 0; i < contours0.size(); i++){approxPolyDP(contours0[i], contours[i], 55, true);//15是为了得到一个矩形,小于15的数回得到更多的点}//选出最大面积的多边形double area = 0;int index=0;for (int i = 0; i < contours.size(); i++){if (contourArea(contours[i])>area){area = contourArea(contours[i]);index = i;}}//最外围轮廓的显示if (contourArea(contours[index])>50000){Scalar color(0, 0, 255);drawContours(src, contours, index, color, 4, 8);}//cout << "contours[index]: " << endl << contours[index] << endl;//最外围轮廓顶点的显示//for (int i = 0; i < contours[index].size(); i++)//{//  circle(src, contours[index][i], 15, (0,0,255), 2, 8, 0);//}//透视变换,顶点的顺序很重要!vector<Point2f> corner;//上面提取轮廓的顶点corner.push_back(Point(83, 80));corner.push_back(Point(652, 61));corner.push_back(Point(13, 548)); corner.push_back(Point(798, 495));vector<Point2f> PerspectiveTransform;//透视变换后的顶点RotatedRect box = minAreaRect(cv::Mat(contours[index]));PerspectiveTransform.push_back(Point(0, 0));PerspectiveTransform.push_back(Point(box.boundingRect().width - 1, 0));PerspectiveTransform.push_back(Point(0, box.boundingRect().height - 1));PerspectiveTransform.push_back(Point(box.boundingRect().width - 1, box.boundingRect().height - 1));//cout << "corner: " << endl << corner << endl;//获取变换矩阵Mat M = getPerspectiveTransform(corner, PerspectiveTransform);//Order of points matters!//cout << "PerspectiveTransform: " << endl << PerspectiveTransform << endl;Mat out;//提取出的数独方框cv::Size size(box.boundingRect().width, box.boundingRect().height);warpPerspective(src, out, M,size, 1, 0, 0);<span style="white-space:pre">    </span>imshow("src",src);
<span style="white-space:pre">  </span>imshow("out",out);while (uchar(waitKey()) == 'q') { }return 0;
}

未完待续......

最近开通了微信公众号,感兴趣的同学可以扫码在微信上交流。

OpenCV实践之路——opencv玩数独之一九宫格轮廓提取与透视变换相关推荐

  1. OpenCV实践之路——人脸识别之一数据收集和预处理

    本文由@星沉阁冰不语出品,转载请注明作者和出处. 文章链接:http://blog.csdn.net/xingchenbingbuyu/article/details/51386949 微博:http ...

  2. OpenCV实践之路——雅虎色情图片检测神经网络试用报告

    本文由@星沉阁冰不语出品,转载请注明作者和出处. 文章链接:http://blog.csdn.net/xingchenbingbuyu/article/details/52821497 微博:http ...

  3. OpenCV实践之路——人脸识别之三识别自己的脸

    本文由@星沉阁冰不语出品,转载请注明作者和出处. 文章链接:http://blog.csdn.net/xingchenbingbuyu/article/details/51472330 微博:http ...

  4. 【Opencv】【OpenCV实践】【OpenCV的使用学习记录】【fmt学习记录】

    [Opencv][OpenCV实践][OpenCV的使用学习记录][fmt学习记录] 0 前言 1 opencv使用说明 1.1 头文件的使用 1.2 CMakeLists.txt的使用 1.3 代码 ...

  5. OpenCV实践之路——人脸检测(C++/Python) 【转】

    转自:http://blog.csdn.net/xingchenbingbuyu/article/details/51105159 版权声明:本文为博主原创文章,转载请联系作者取得授权. 本文由@星沉 ...

  6. OpenCV实践之路——方形图片对角线切割

    本文由@星沉阁冰不语出品,转载请注明作者和出处. 文章链接:http://blog.csdn.net/xingchenbingbuyu/article/details/50547897 微博:http ...

  7. OpenCV实践之路——使用imread()函数读取图片的六种正确姿势

    本文由@星沉阁冰不语出品,转载请注明作者和出处. 文章链接:http://blog.csdn.net/xingchenbingbuyu/article/details/51375078 微博:http ...

  8. 小密圈:OpenCV实践之路

    最近发现一个很多意思的东西,小密圈.号称连接一千位铁杆粉丝,知识变现.据说小密圈可能是最好的微信公众号读者论坛.也做一个尝试,看有多少人愿意加入. 仍然是分享OpenCV实战的内容和资料,除了平时写的 ...

  9. OpenCV实践之路——像素初探

    本文由@星沉阁冰不语出品,转载请注明作者和出处. 文章链接:http://blog.csdn.net/xingchenbingbuyu/article/details/50708765 微博:http ...

最新文章

  1. 面试官:为什么HTTPS是安全的
  2. [云炬学英语]每日一句2020.9.3
  3. 1.uniq去重命令讲解
  4. linux 查看系统版本 32位 or 64位
  5. Java程序员:不要因未知而让云成本大涨
  6. UVA11212Editing aBook 编辑书稿
  7. c语言回调函数构架程序,C语言回调函数熟练---使用方法(构建程序框架方便好用)...
  8. 准入控制(NAC)技术调研
  9. elasticsearch工作笔记002---Centos7.3安装最新版elasticsearch-7.0.0-beta1-x86_64.rpm单机版安装
  10. Eclipse-project 重命名问题(如何彻底修改Eclipse工程名),4种解法
  11. 并发-2-Thread和Runnable的API
  12. Android仿京东、天猫app的商品详情页的布局架构, 以及功能实现
  13. 校园网络项目PT模拟
  14. cimiss数据_中国气象数据网
  15. 华为手机怎样恢复Android,华为手机恢复出厂设置的教程和方法
  16. MMC-HVDC仿真模型,pscad柔性直流输电仿真mmc仿真模型
  17. matlab 傅里叶变换 频谱图,傅里叶变换与信号频谱图.PDF
  18. 【微信】微信授权获取openid
  19. flutter ListView.separated使用
  20. 系统架构师进阶(Believe Youself)

热门文章

  1. 可行解、最优解、基解、基可行解、基最优解
  2. 计算机逻辑部件按其结构可分为,《数字逻辑电路》期末大作业实验报告
  3. TokenGazer:DeFi领域发展良好,量化模型显示MKR处于市值偏低区间
  4. 统计学简介之十六——单因素方差分析
  5. 达梦dsc搭建+dw
  6. 十月的秋风还没有来到...
  7. 苹果Mac系统虚拟打印机CAD输出PDF文档软件—pdfwriter
  8. 反函数的导数——arcsinx的导数求导证明
  9. 【Hive+MySQL+Python】淘宝用户购物行为数据分析项目
  10. Oracle和MySql的布尔类型