使用Opencv+VS2015做数字图像识别

本文大部分代码转载自https://blog.csdn.net/huaweiran1993/article/details/80548290

一、首先建立数字的模板(0-9)图像
使用Opencv+VS2015做数字图像识别_第1张图片
使用Windows自带的画图软件,制作数字图片使用Opencv+VS2015做数字图像识别_第2张图片
依次类推建立数字0-9的图片
使用Opencv+VS2015做数字图像识别_第3张图片
把图片就放在工程目录下,如上图。
二、完整代码如下

#include 
#include 
#include 

using namespace cv;
using namespace std;

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(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 = sum + src.at(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);
        if (colValue > 0)
        {
            top = i;
            break;
        }
    }
    for (; i < src.rows; i++)
    {
        int colValue = getRowSum(src, i);
        if (colValue == 0)
        {
            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);
        if (colValue > 0)
        {
            left = i;
            break;
        }
    }
    if (left == 0)
    {
        return 1;
    }
    for (; i < src.cols; i++)
    {
        int colValue = getColSum(src, i);
        if (colValue == 0)
        {
            right = i;
            break;
        }
    }
    int width = right - left;
    Rect rect(left, 0, width, src.rows);
    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(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.png", 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(50, 50), 0, 0, CV_INTER_LINEAR);
        resize(Template, Template, Size(50, 50), 0, 0, CV_INTER_LINEAR);
        absdiff(Template, src, img_result);
        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()
{
    //用于模板建立
    for (int i = 0; i < 10; i++)
    {
        char fileName[10];
        sprintf_s(fileName, "%d.png", i);
        Mat src = imread(fileName, CV_LOAD_IMAGE_GRAYSCALE);
        threshold(src, src, 100, 255, CV_THRESH_BINARY_INV);
        Mat rImg,dst;
        cutLeft(src, dst, rImg);
        imwrite(fileName, dst);
    }


    //用于识别
    //Mat src = imread("z.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);
    //while (res == 0)
    //{
    //  Mat srcTmp = rightImg;
    //  getSubtract(leftImg, 9);
    //  res = cutLeft(srcTmp, leftImg, rightImg);
    //}

    waitKey(0);
    return 0;
}

三、模板建立
使用上面代码运行获得数字的模板,如图
这里写图片描述
四、识别
将main函数中用于模板建立的代码注释掉,用于识别的代码去掉注释

  int main()
{
    //用于模板建立
    //for (int i = 0; i < 10; i++)
    //{
    //  char fileName[10];
    //  sprintf_s(fileName, "%d.png", i);
    //  Mat src = imread(fileName, CV_LOAD_IMAGE_GRAYSCALE);
    //  threshold(src, src, 100, 255, CV_THRESH_BINARY_INV);
    //  Mat rImg,dst;
    //  cutLeft(src, dst, rImg);
    //  imwrite(fileName, dst);
    //}


    //用于识别
    Mat src = imread("z.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);
    while (res == 0)
    {
        Mat srcTmp = rightImg;
        getSubtract(leftImg, 9);
        res = cutLeft(srcTmp, leftImg, rightImg);
    }

    waitKey(0);
    return 0;
}  

用画图软件制作识别用的图像
使用Opencv+VS2015做数字图像识别_第4张图片
运行程序结果如下:
使用Opencv+VS2015做数字图像识别_第5张图片

你可能感兴趣的:(使用Opencv+VS2015做数字图像识别)