欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2024-03-07 18:26:27
...

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

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

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

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<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 = 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);
        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<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.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;
}

三、模板建立
使用上面代码运行获得数字的模板,如图
使用Opencv+VS2015做数字图像识别
四、识别
将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做数字图像识别
运行程序结果如下:
使用Opencv+VS2015做数字图像识别