最近要做数字识别这块,但是自己又完全不懂这个,网上搜资料搜了好多,但是都没找到完整代码。只有自己慢慢搞,下面写下自己的过程以及代码有不好的地方希望大神可以指出,大家相互交流下。有需要完整代码的可以自行下载源码 (源码里面 是需要自己做一个图片的,没有图片,不能直接运行)
我是在VS2013 和opencv 2.4.9 环境下实现的。关于环境的搭建和配置以及软件的下载可以可以参考,http://blog.csdn.net/ltg01/article/details/50433386
我要做的是把0123456789 印刷体数字识别出来。
一、首先对图片进行预处理
对图片进行灰度化二值化
Mat src = imread("D:\\b.png", CV_LOAD_IMAGE_GRAYSCALE);//读取图片并进行灰度化处理
threshold(src, src, 100 , 255, CV_THRESH_BINARY);//二值化
imshow("origin", src);//显示图片
原图
threshold(src, src, 100 , 255, CV_THRESH_BINARY_INV);
imshow("origin", src);
Mat leftImg,rightImg;
int res = cutLeft(src, leftImg, rightImg);
int i = 0;
while (res == 0)
{
char nameLeft[10];
sprintf(nameLeft, "%dLeft", i);
char nameRight[10];
sprintf(nameRight, "%dRight", i);
i++;
//stringstream ss;
//ss <
//imwrite("D:\\" + ss.str() + ".jpg", leftImg);
//ss >> nameLeft;
Mat srcTmp = rightImg;
//getSubtract(leftImg, 10);
res = cutLeft(srcTmp, leftImg, rightImg);
}
waitKey(0);
return 0;
}
最后截取结果如下图
threshold(src, src, 100 , 255, CV_THRESH_BINARY_INV);
imshow("origin", src);
Mat leftImg,rightImg;
int res = cutLeft(src, leftImg, rightImg);
int i = 0;
while (res == 0)
{
char nameLeft[10];
sprintf(nameLeft, "%dLeft", i);
char nameRight[10];
sprintf(nameRight, "%dRight", i);
i++;
imshow(nameLeft, leftImg);
stringstream ss;
ss < imwrite("D:\\" + ss.str() + ".jpg", leftImg);//保存截取图片做为模板
ss >> nameLeft;
Mat srcTmp = rightImg;
//getSubtract(leftImg, 10);
res = cutLeft(srcTmp, leftImg, rightImg);
}
waitKey(0);
return 0;
}
四、数字识别
把你切割的数字图片大小调整到和模板一样的大小,然后让需要匹配的图和分别和10个模板相减,(让两个图片对应像素点值相减)然后求返回图片的整个图片的像素点值得平方和,和哪个模板匹配时候返回图片的平方和最小则就可以得到结果。只需要改主函数
void getPXSum(Mat &src, int &a)//获取所有像素点和
{
threshold(src, src, 100, 255, CV_THRESH_BINARY);
a = 0;
for (int i = 0; i {
for (int j = 0; j {
a += src.at (i, j);
}
}
}
int getSubtract(Mat &src, int TemplateNum) //两张图片相减
{
Mat img_result;
int min = 1000000;
int serieNum = 0;
for (int i = 0; i char name[20];
sprintf_s(name, "D:\\%dLeft.jpg", i);
Mat Template = imread(name, CV_LOAD_IMAGE_GRAYSCALE);
threshold(Template, Template, 100, 255, CV_THRESH_BINARY);
threshold(src, src, 100, 255, CV_THRESH_BINARY);
resize(src, src, Size(32, 48), 0, 0, CV_INTER_LINEAR);
resize(Template, Template, Size(32, 48), 0, 0, CV_INTER_LINEAR);//调整尺寸
//imshow(name, Template);
absdiff(Template, src, img_result);//
getPXSum(img_result, diff);
if (diff {
min = diff;
serieNum = i;
}
}
printf("最小距离是%d ", min);
printf("匹配到第%d个模板匹配的数字是%d\n", serieNum,serieNum);
return serieNum;
}
int main()
{
Mat src = imread("D:\\s.png", CV_LOAD_IMAGE_GRAYSCALE);
threshold(src, src, 100 , 255, CV_THRESH_BINARY_INV);
imshow("origin", src);
Mat leftImg,rightImg;
int res = cutLeft(src, leftImg, rightImg);
int i = 0;
while (res == 0)
{
// char nameLeft[10];
// sprintf(nameLeft, "%dLeft", i);
// char nameRight[10];
// sprintf(nameRight, "%dRight", i);
// i++;
imshow(nameLeft, leftImg);
// stringstream ss;
// ss < // imwrite("D:\\" + ss.str() + ".jpg", leftImg);
// ss >> nameLeft;
Mat srcTmp = rightImg;
getSubtract(leftImg, 10);//数字识别
res = cutLeft(srcTmp, leftImg, rightImg);
}
waitKey(0);
return 0;
}
运行最终结果如下图