工程文件详见 :z199912230/-VS-: 数字图像处理;图像识别 (github.com)

要求 

  1. 根据题目要求,利用图像处理相关知识,完成印刷数字图像的采集及识别,确定具体数字。
  2. 采集印刷体数字图像。识别0-9两种以上字体的数字图像识别。
  3. 熟悉Visaul Studio2019软件开发平台,Opencv及相关功能的配置。
  4. 利用Opencv库函数,驱动笔记本电脑自带的摄像头进行图像采集及显示。
  5. 整个系统的设计过程包括:模板制作,图像采集及预处理,图像识别。
  6. 通过调试、运行,查看数字识别的结果,进行识别率的分析。

系统总体设计

基于Visaul Studio2019软件开发平台,搭载OpenCv库的印刷数字识别系统的设计,需要识别不同字体的印刷数字,其中涉及到了Opencv库以及相关的操作。

OpenCV图像处理库,它轻量级而且高效,由一系列C函数和少量C++类构成,实现了图像处理和计算机视觉方面的很多通用算法。因此本次课题将使用OpenCv库函数实现以下功能:模板制作、灰度转换、二值化、图像采集、鼠标回调函数操作、图像分割、模板匹配等。最终实现不同印刷数字的识别。系统总体框图如图1所示。

配置环境

  1. 添加环境变量,将OpenCv动态库的路径添加到Path环境变量中。
  2. 在VS2015中新建空项目,配置包含目录:添加OpenCv头文件的路径。
  3. 配置库目录:添加OpenCv动态库的路径。
  4. 配置链接器的输入:添加OpenCv的动态库。

模板制作模块程序设计

首先准备一张有0~9数字的图片,然后将图片进行灰度处理。

之后将灰度图进行二值化,阈值设为100,这样可以将图片变成黑纸白字。利用边缘检测的原理将每个数字分割开制成模板。

void makeModel()
{//Mat src = imread("model.png", CV_LOAD_IMAGE_GRAYSCALE);//threshold(src, src, 100, 255, CV_THRESH_BINARY_INV); // 二值化Mat src = imread("model.png");//读取模板paintGrey(src, src);//对模板进行灰度化处理//imshow("grey", src);towNum(src, src, 150, 255, 0);//二值化//imshow("tow", src);//显示图像imwrite("tow.jpg", src);for (int i = 0; i <20; i++){char fileName[21];Mat rImg, dst;cutLeft(src, dst, rImg);sprintf_s(fileName, "%d.png", i);//生成0~19.pngimwrite(fileName, dst);//src = rImg;}
}// 二值化
void towNum(Mat &src, Mat &dst, int thresh, int maxVul, bool flag)
{Mat tmp = Mat(src.size(), CV_8U);//获取大小for (int i = 0; i < src.rows; i++)//行{for (int j = 0; j < src.cols; j++)//列{uchar num = src.at<uchar>(i, j);if (flag == 0){if (num <= thresh)tmp.at<uchar>(i, j) = 255;elsetmp.at<uchar>(i, j) = 0;}else{if (num <= thresh)tmp.at<uchar>(i, j) = 0;elsetmp.at<uchar>(i, j) = 255;}}}dst = tmp;
}// 灰度转换
void paintGrey(Mat &src, Mat &dst)
{Mat temp = Mat(src.size(), CV_8U);int row = src.rows;int col = src.cols;for (int i = 0; i < row; i++){for (int j = 0; j < col; j++){uchar b = src.at<Vec3b>(i, j)[0] * 0.144;uchar g = src.at<Vec3b>(i, j)[1] * 0.587;uchar r = src.at<Vec3b>(i, j)[2] * 0.299;temp.at<uchar>(i, j) = saturate_cast<uchar>(b + g + r);//防止溢出if ((b + g + r) > 255)temp.at<uchar>(i, j) = 255;elsetemp.at<uchar>(i, j) = b + g + r;}}dst = temp;
}//切掉左右边空白和数字切割//行
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);//下x,y坐标长宽rightImg = src(rectRight).clone();cutTop(leftImg, leftImg);return 0;
}//统计所有列的二值总和
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;
}//切掉图片的上下空白
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 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;
}

图像采集模块程序设计

首先使用OpenCv库函数启动IP摄像头,采集图像,然后用鼠标选择要识别的具体区域,此处使用到了OpenCv库的鼠标操作回调函数,之后将识别区域的图片进行灰度转换与二值化处理。

Mat getPicture()
{int c;VideoCapture capture("“http://账号:密码@广域网IP:端口号”");//调用摄像头while (true){capture.read(src);imshow("origion", src);c = waitKey(30);//延时if (c == 13){capture.release();break;}}/*VideoCapture v(0);//调用电脑摄像头int c;while (v.read(src)){imshow("origin", src);c = waitKey(30);//延时if (c == 13){v.release();break;}}*///imshow("test", src);//src = imread("test.png");imshow("t", src);// 设置鼠标事件回调函数setMouseCallback("t", mouse_callback);   while (char(waitKey(1)) != 13){}paintGrey(crop, crop);towNum(crop, crop, 150, 255, 0);return crop;
}// 鼠标事件回调函数
void mouse_callback(int event, int x, int y, int, void*)
{// 当鼠标左键按下时,记录其状态和坐标if (event == EVENT_LBUTTONDOWN){ldown = true;corner1.x = x;corner1.y = y;cout << "Corner 1 recorded at" << corner1 << endl;}// 当鼠标左键放开时,记录其状态和坐标if (event == EVENT_LBUTTONUP){// 判断选取的区域是否大于20个像素if (abs(x - corner1.x) > 20 && abs(y - corner1.y) >20){lup = true;corner2.x = x;corner2.y = y;cout << "Corner 2 recorded at" << corner2 << endl << endl;}else{cout << "Please select a bigger region" << endl;ldown = false;}}//当移动鼠标时, 更新选择区域, 并绘制矩形选择区域图形if (ldown == true && lup == false){Point pt;pt.x = x;pt.y = y;Mat local_img = src.clone();rectangle(local_img, corner1, pt, Scalar(0, 0, 255));imshow("t", local_img);}// 定义感兴趣区域,并对原图进行剪裁if (ldown == true && lup == true){box.width = abs(corner1.x - corner2.x);box.height = abs(corner1.y - corner2.y);box.x = min(corner1.x, corner2.x);box.y = min(corner1.y, corner2.y);// 对原图进行剪裁, 生成新图crop = 0;crop = src(box);namedWindow("Crop", CV_WINDOW_AUTOSIZE);imshow("Crop", crop);ldown = false;lup = false;imshow("t", src);}
}

具体启动IP摄像头的教程参考

通过局域网访问手机摄像头数据流 (baidu.com)

利用OpenCV4调用安卓手机摄像头、电脑摄像头的实现 (baidu.com)

图像识别模块程序设计

图像匹配有很多方法:比如模板匹配、直方图匹配等,本次课题中采用的方法是模板匹配。

在匹配图像之前需要将模板与待识别图像设定为同样大小得像素值,用到了图像缩放,实习中用的双线性插值法。双线性插值法的原理:当求出的分数地址与像素点不一致时,求出其与周围4个像素点的距离比,根据该比例,由4个邻域的像素灰度值进行双线性插值。

图像匹配的原理:将待识别的二值图像的像数值与20个模板的二值图像的像数值一一对应,求其差的绝对值。

void getPXSum(Mat &src, int &a) //计算图像最小距离
{towNum(src, src, 150, 255, 1);a = 0;for (int i = 0; i < src.rows; i++)//行像素{for (int j = 0; j < src.cols; j++)//列像素{a += src.at<uchar>(i, j);//第i行第j列的的值.at()是一个返回值}}
}// 求绝对值
void my_abs(Mat &src, Mat &dst, Mat &result)
{Mat tmp = Mat(src.size(), CV_8U);//无符号整数for (int i = 0; i < src.rows; i++){for (int j = 0; j < src.cols; j++){uchar a = src.at<uchar>(i, j);uchar b = dst.at<uchar>(i, j);tmp.at<uchar>(i, j) = a > b ? a - b : b - a;//如果a>b成立则a-b,否则b-a}}result = tmp;
}int getSubtract(Mat &src, int TemplateNum) //用于识别数字
{Mat img_result = Mat(src.size(), CV_8U);;int min = 1000000;int serieNum = 0;int serienum = 0;int num[20];for (int p = 0; p < 20; p++)num[p] = 0;for (int i = 0; i <= TemplateNum; i++){char name[20];sprintf_s(name, "%d.png", i);Mat Template = imread(name);//读取图片文件paintGrey(Template, Template);//灰度转换//threshold(src, src, 100, 255, CV_THRESH_BINARY);towNum(Template, Template, 150, 255, 1);//二值化test模板towNum(src, src, 150, 255, 1);resize(src, src, Size(50, 50), 0, 0, CV_INTER_LINEAR);//缩放的大小为50*50,0,height/row,0,,双线性插值resize(Template, Template, Size(50, 50), 0, 0, CV_INTER_LINEAR);my_abs(Template, src, img_result);//结果保存到img_resultint diff = 0;getPXSum(img_result, diff);//距离num[i] = diff;/*if (diff < min){min = diff;serieNum = i;serienum = i;if (serienum >= 10)serienum =serienum -10;}*/}for (int i = 0; i < 20; i++){int cin;cin >> num[i];if (num[i] < num[serieNum]){serieNum = i;serienum = i;if (serienum >= 10)serienum = serienum - 10;}}//cout << "最小距离是" << min << ",";cout << "最小距离是" << num [serienum] << ",";cout << "匹配的是第" << serieNum << "个模板,匹配的数字是" << serienum << endl;return serieNum;
}int main()
{// 建模板makeModel();//用于识别Mat src = imread("test.png", CV_LOAD_IMAGE_GRAYSCALE);Mat test = getPicture();while (char(waitKey(0))!='q')//无返回值,必须有按键{imshow("test", test);//Mat leftImg, rightImg;int res = cutLeft(test, leftImg, rightImg);//切割while (res == 0)//切割完成后{Mat srcTmp = rightImg;getSubtract(leftImg, 19 );res = cutLeft(srcTmp, leftImg, rightImg);}while (char(waitKey(1)) != 13){}paintGrey(crop, crop);imshow("crop", crop);towNum(crop, crop, 150, 255, 0);test = crop;}waitKey(0);return 0;
}

结果

采集到的图像

选取测试图片

识别结果

基于VS的印刷数字识别系统相关推荐

  1. 基于matlab的手写体数字识别系统

    摘要:随着科学技术的发展,机器学习成为一大学科热门领域,是一门专门研究计算机怎样模拟或实现人类的学习行为的交叉学科.文章在matlab软件的基础上,利用BP神经网络算法完成手写体数字的识别. 机器学习 ...

  2. 基于matlab的手写体数字识别系统,基于matlab的手写体数字识别系统研究

    基于matlab的手写体数字识别系统研究 丁禹鑫1,丁会2,张红娟2,杨彤彤1 [摘要]随着科学技术的发展,机器学习成为一大学科热门领域,是一门专门研究计算机怎样模拟或实现人类的学习行为的交叉学科.文 ...

  3. MATLAB实现数字识别系统,基于人工神经网络的MATLAB手写数字识别系统

    <基于人工神经网络的MATLAB手写数字识别系统>由会员分享,可在线阅读,更多相关<基于人工神经网络的MATLAB手写数字识别系统(8页珍藏版)>请在人人文库网上搜索. 1.基 ...

  4. 课程设计(毕业设计)—基于机器学习KNN算法手写数字识别系统—计算机专业课程设计(毕业设计)

    机器学习KNN算法手写数字识别系统 下载本文手写数字识别系统完整的代码和课设报告的链接(或者可以联系博主koukou(壹壹23七2五六98),获取源码和报告):https://download.csd ...

  5. 手写数字识别系统 基于python

    环境基于Python3.6和Tensorflow框架 实现手写数字识别系统 本文使用python基于TensorFlow设计手写数字识别算法,并编程实现GUI界面,构建手写数字识别系统.文中首先对如何 ...

  6. 基于TensorFlow和mnist数据集的手写数字识别系统 ,可识别电话号码,识别准确率高,有对比实验,两组模型,可讲解代码

    基于TensorFlow和mnist数据集的手写数字识别系统 ,可识别电话号码,识别准确率高,有对比实验,两组模型,可讲解代码

  7. 【手写数字识别】基于matlab GUI BP神经网络单个或连续手写数字识别系统【含Matlab源码 2296期】

    ⛄一.手写数字识别技术简介 1 案例背景 手写体数字识别是图像识别学科下的一个分支,是图像处理和模式识别研究领域的重要应用之一,并且具有很强的通用性.由于手写体数字的随意性很大,如笔画粗细.字体大小. ...

  8. python基于轻量级CNN模型开发构建手写藏文数字识别系统

    最近做的很多工作都是跟手写性质的数据集有关的,比如:手写汉字.手写甲骨文.手写数字.手写字母等等,今天主要做的实践是对藏文中的手写数字进行识别分析,在我之前的博文中有很多相关的实践分析,感兴趣的话可以 ...

  9. 【毕业设计_课程设计】手写数字识别系统的设计实现(源码+论文)

    文章目录 0 项目说明 1 系统概述 1.1 系统实现环境 2 研究方法 2.1 图像预处理阶段 2.2 特征提取阶段 2.3 数字识别阶段 3 研究结论 4 论文概览 5 项目工程 0 项目说明 手 ...

最新文章

  1. javascript的特点
  2. 在Linux下安装配置phpMyAdmin步骤
  3. SqlServer中除了sql和bak你还可以使用mdf文件来进行数据库的添加和分离
  4. vscode怎么写qt项目_使用VSCode 编译调试QT程序
  5. php 打印错误 display,php错误display及error_reporting的使用
  6. grasshopper_如何使用Google的Grasshopper编码应用程序来学习手机上的编码基础知识...
  7. Altium Designer20原理图库放置引脚报错解决方案
  8. python、java大作战,python测试dubbo接口
  9. linux系统汇总的qt,QT 编程总结_Linux编程_Linux公社-Linux系统门户网站
  10. iOS 上的相机捕捉 swift
  11. Kubernetes详解(三)——Kubernetes集群组件
  12. windows 安装python2.7
  13. HashSet底层存储元素的源码分析
  14. 苹果 Mac 上不显示外置硬盘?9 个必须尝试的修复方法
  15. Scala的那些匿名函数
  16. 基于windows fiber的协程(coroutine)实现
  17. 存货的三个加权平均单价
  18. Hyper-V虚拟机设置固定IP
  19. 项目管理九大知识领域五大过程组
  20. 用Python Matplotlib实现可视化混沌系统

热门文章

  1. 扫雷游戏软件测试,暑期社会实践 | 扫雷游戏的测试完善及总结
  2. 老笔记整理二:网页小问题汇总
  3. 为什么说深度学习和机器学习截然不同?
  4. Linux部署人大金仓(Kingbase8)
  5. java_进阶:Map、自动装箱拆箱
  6. 齐治堡垒机前台远程命令执行漏洞(CNVD-2019-20835)分析
  7. 一个好领导,懂得为下属“打伞”
  8. 总结yolov5不同模型的网络结构图
  9. 认真的雪歌词的c语言编码,认真的雪歌词
  10. 前端vue/js刷新浏览器页面方法-案例