本文大部分代码转自:https://blog.csdn.net/ltg01/article/details/50492556
看到原文有很多人求完整代码,于是在这里给出完整代码,并且补充了更详细的注释,以便于更好的理解代码。具体的步骤和思路,原文里有详细的说明,这里就不再阐述了。
以下为完整代码:
#include "cv.h" #include "highgui.h" #include "cxcore.h" using namespace std; using namespace cv; int getColSum(Mat src,int col)//统计所有列像素的总和 { int sum = 0; int height = src.rows; int width = src.cols; for (int i = 0; i < height; i++) { sum = sum + src.at <uchar>(i, col); } return sum; } int getRowSum(Mat src, int row)//统计所有行像素的总和 { int sum = 0; int height = src.rows; int width = src.cols; for (int i = 0; i < width; i++) { sum += src.at <uchar>(row, i); } return sum; } void cutTop(Mat& src, Mat& dstImg)//上下切割 { int top, bottom; top = 0; bottom = src.rows; int i; for (i = 0; i < src.rows; i++) { int colValue = getRowSum(src, i);//统计所有行像素的总和 //cout <<i<<" th "<< colValue << endl; if (colValue>0)//扫描直到行像素的总和大于0时,记下当前位置top { top = i; break; } } for (; i < src.rows; i++) { int colValue = getRowSum(src, i);//统计所有行像素的总和 //cout << i << " th " << colValue << endl; if (colValue == 0)//继续扫描直到行像素的总和等于0时,记下当前位置bottom { bottom = i; break; } } int height = bottom - top; Rect rect(0, top, src.cols, height); dstImg = src(rect).clone(); } int cutLeft(Mat& src, Mat& leftImg, Mat& rightImg)//左右切割 { int left, right; left = 0; right = src.cols; int i; for (i = 0; i < src.cols; i++) { int colValue = getColSum(src, i);//统计所有列像素的总和 //cout <<i<<" th "<< colValue << endl; if (colValue>0)//扫描直到列像素的总和大于0时,记下当前位置left { left = i; break; } } if (left == 0) { return 1; } //继续扫描 for (; i < src.cols; i++) { int colValue = getColSum(src, i);//统计所有列像素的总和 //cout << i << " th " << colValue << endl; if (colValue == 0)//继续扫描直到列像素的总和等于0时,记下当前位置right { right = i; break; } } int width = right - left;//分割图片的宽度则为right - left Rect rect(left, 0, width, src.rows);//构造一个矩形,参数分别为矩形左边顶部的X坐标、Y坐标,右边底部的X坐标、Y坐标(左上角坐标为0,0) leftImg = src(rect).clone(); Rect rectRight(right, 0, src.cols - right, src.rows);//分割后剩下的原图 rightImg = src(rectRight).clone(); cutTop(leftImg, leftImg);//上下切割 return 0; } void getPXSum(Mat &src, int &a)//获取所有像素点和 { threshold(src, src, 100, 255, CV_THRESH_BINARY); a = 0; for (int i = 0; i < src.rows;i++) { for (int j = 0; j < src.cols; j++) { a += src.at <uchar>(i, j); } } } int getSubtract(Mat &src, int TemplateNum) //数字识别 { Mat img_result; int min = 1000000; int serieNum = 0; for (int i = 0; i < TemplateNum; i++){ char name[20]; sprintf_s(name, "D:\\1\\%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); /*让需要匹配的图分别和10个模板对应像素点值相减,然后求返回图片的整个图片的像素点值得平方和,和哪个模板匹配时候返回图片的平方和最小则就可以得到结果*/ absdiff(Template, src, img_result);//AbsDiff,OpenCV中计算两个数组差的绝对值的函数。 int diff = 0; getPXSum(img_result, diff);//获取所有像素点和 if (diff < min)//像素点对比 { min = diff; serieNum = i; } } printf("最小距离是%d ", min); printf("匹配到第%d个模板匹配的数字是%d\n", serieNum,serieNum); return serieNum; } int main() { Mat src = imread("ss.jpg", CV_LOAD_IMAGE_GRAYSCALE);//读取图片 threshold(src, src, 100 , 255, 1);//二值化 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 << nameLeft; //imwrite("D:\\1\\" + ss.str() + ".jpg", leftImg);//把分割图片存到D:\\1\\ //ss >> nameLeft; Mat srcTmp = rightImg; getSubtract(leftImg, 10);//进行数字识别 res = cutLeft(srcTmp, leftImg, rightImg); } waitKey(0); return 0; }