写在前面:
关于本次的数独识别项目,我先说明下情况:
这是本人18年6月份做的,现在把当时的笔记整理出来(口吻的描述是以当时的时间来描述)。
这个数独的项目分别做了两次,
第一次做的还没做完,第二次可以识别数字(虽然不完美)
第一次就是以下准备写的,第二次迟点也会给出来。
区别:第一第二次有什么区别呢?
区别就是第一次用的图片是现实中的图片,第二次用的是数字图片。
那么第一第二次做到哪个地步呢?
现在想来第二次识别的不够精确有可能是训练样本不够多的问题!
那么为什么我还要把没做完的,做的有瑕疵的东西发出来呢?不能完善好才发出来吗?
主要是最近事情多,等往后自己的经验积累多了,技术提高了,再搞个终极版。
然后也迫不及待想和大家分享下我的思路,提供下大家可能遇到了我遇到的问题的解决方法。
当然如果有刚入门的小白(虽然我也是,哈哈),看到两次做到的程度对比之后想学第二次的,我认为是不可取的,因为这个过程是循序渐进的,第一次做的时候我就学到了很多东西,加深了对OpenCV的印象,同时遇到问题并且自己解决了,还写下来自己的理解,对自己的学习是非常大的帮助的。
这是在 @冰不语 的博客看到的一个小项目
OpenCV 实践之路 ——opencv 玩数独之二九宫格小方格的提取和数字的提取
觉得学这个会了可以学到很多东西,于是就马上尝试.
今天先实现作者提供的思路的第一步
一、 高斯滤波去掉部分噪音 GaussianBlur();
1. 先看效果图:
Talk is cheap,show you the code.
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
//using namespace std;
using namespace cv;
int main()
{
Mat src = imread("01.jpg");
Mat out(src.size(),src.type(),Scalar::all(0));
GaussianBlur(src, out, Size(5, 5), 0, 0);
imshow("src", src);
imshow("out", out);
waitKey(0);
}
应用高斯滤波其实很简单。只要设好 高斯内核大小 就可以了。
二、 拉普拉斯锐化增强轮廓以便于检测提取
1. 先看效果图(1):这是对原图直接进行拉普拉斯锐化的图像
Talk is cheap,show you the code.
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace std;
using namespace cv;
int main()
{
Mat src = imread("01.jpg");
Mat out(src.size(),src.type(),Scalar::all(0));
imshow("src", src);
//拉普拉斯锐化
Mat kernel(3, 3, CV_32F, Scalar(-1));
kernel.at<float>(1, 1) = 8.9;
filter2D(src, src, src.depth(), kernel);
imshow("拉普拉斯锐化", src);
waitKey(0);
}
看到拉普拉斯锐化后面那段代码会觉得好像很难,其实仔细看可以看出,只是先定义一个Mat对象,并且先全部初始化为-1,再对矩阵的中心赋值,再调用filter2D调用函数进行卷积。
关于更多拉普拉斯锐化可以看 拉普拉斯锐化图像
关于更多图像卷积运算函数filter2D()可以看 opencv学习(七)之图像卷积运算函数filter2D()
2. 再看效果图(2):先进行高斯滤波后拉普拉斯锐化
Talk is cheap,show you the code.
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace std;
using namespace cv;
int main()
{
Mat src = imread("01.jpg");
Mat out(src.size(),src.type(),Scalar::all(0));
imshow("src", src);
GaussianBlur(src, src, Size(5, 5), 0, 0);
imshow("高斯滤波", src);
//拉普拉斯锐化
Mat kernel(3, 3, CV_32F, Scalar(-1));
kernel.at<float>(1, 1) = 8.9;
filter2D(src, src, src.depth(), kernel);
imshow("高斯滤波后拉普拉斯锐化", src);
waitKey(0);
}
三、自适应阈值化得到二值图像 adaptiveThreshold();
要注意的是 输入图像是单通道的
超清晰理解:【OpenCV3】阈值化操作——cv::threshold()与cv::adaptiveThreshold()详解