由于自己学识尚浅,不能用python深度学习来识别这里的数字,所以就完全采用opencv来识别数字,然后在这里分享、记录一下自己在学习过程中的一些所见所得和所想

要解决的问题
这是一个要识别的数字,我这里首先是对图像进行一个ROI的提取,提取结果就仅仅剩下数字,把其他的一些无关紧要的要素排除在外,

这是ROI图片,我们要做的就是识别出该照片中的数字,
解决问题的思路
1、先把这个图片中的数字分割,分割成为5张小图片,每张图片包含一个数字,为啥要分割呢?因为我们没办法让计算机知道这个数字是多少,所以只能根据特征,让计算机去识别特征,然后每一个特征对应一个值,首先贴出分割图片的程序,然后在程序下方会有一段思路解释

#include <opencv2/core/core.hpp>
#include <opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <ctime>
using namespace std ;
using namespace cv;
#include <map>
Mat src_threshold;
Mat src_dil;
int sunImage(Mat &image);
vector<Mat>ROI_image;//待测图片
int main()
{clock_t start ,finish;start=clock();Mat src;src=imread("D:\\vspic\\picture\\number6.jpg");resize(src,src,Size(src.cols/7,src.rows/7));imshow("src",src);Mat src_gray;cvtColor(src,src_gray,COLOR_BGR2GRAY);//imshow("gsrc_ray",src_gray);Mat src_blur;blur(src_gray,src_blur,Size(9,9));//GaussianBlur(src_gray,src_blur,Size(11,11),1,1);Mat src_threshold;threshold(src_blur,src_threshold,150,255,THRESH_OTSU);//imshow("src_threshold",src_threshold);Mat src_canny;Canny(src_threshold,src_canny,125,255,3);//imshow("src_canny",src_canny);vector<vector<Point>>contours_src;vector<Vec4i>hierarchy_src(contours_src.size());findContours(src_canny,contours_src,hierarchy_src,RETR_EXTERNAL,CHAIN_APPROX_NONE);Rect rect_s;Rect choose_rect;for (size_t i=0;i<contours_src.size();i++){rect_s=boundingRect(contours_src[i]);double width=rect_s.width;double height= rect_s.height;double bizhi=width/height;if (bizhi>1.5&&height>50){/*rectangle(src,rect_s.tl(),rect_s.br(),Scalar(255,255,255),1,1,0);*/choose_rect=Rect(rect_s.x+20,rect_s.y+30,rect_s.x-30,rect_s.y-108);}}Mat roi;roi=src(choose_rect);//imshow("src_",roi);Mat img =roi;Mat gray_img;// 生成灰度图像cvtColor(img, gray_img, CV_BGR2GRAY);// 高斯模糊Mat img_gau;GaussianBlur(gray_img, img_gau, Size(3, 3), 0, 0);// 阈值分割Mat img_seg;threshold(img_gau, img_seg, 0, 255, THRESH_BINARY + THRESH_OTSU);Mat element;element=getStructuringElement(MORPH_RECT,Size(8,8));erode(img_seg,src_dil,element);//imshow("src_dil",src_dil);// 边缘检测,提取轮廓Mat img_canny;Canny(src_dil, img_canny, 200, 100);//imshow("canny",img_canny);vector<vector<Point>> contours;vector<Vec4i> hierarchy(contours.size());findContours(img_canny, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE, Point());//寻找轮廓int size = (int)(contours.size());//轮廓的数量//cout<<size<<endl;6个// 保存符号边框的序号vector<int> num_order;//定义一个整型int容器map<int, int> num_map;//容器,需要关键字和模板对象两个模板参数,此处定义一个int作为索引,并拥有相关连的指向int的指针for (int i = 0; i < size; i++){// 获取边框数据Rect number_rect = boundingRect(contours[i]);int width = number_rect.width;//获取矩形的宽int height = number_rect.height;//获取矩形的高// 去除较小的干扰边框,筛选出合适的区域if (width > img.cols/20 ){rectangle(img,number_rect.tl(),number_rect.br(),Scalar(255,255,255),1,1,0);//绘制矩形imshow("img",img);//显示矩形框num_order.push_back(number_rect.x);//把矩形的x坐标放入number_order容器中,将一个新的元素添加到vector的最后面,//位置为当前元素的下一个元素num_map[number_rect.x] = i;//向map中存入键值对,number_rect.x是关键字,i是值/*把矩形框的x坐标与对应的i值一起放入map容器中,形成一一对应的键值对*/}}// 按符号顺序提取sort(num_order.begin(), num_order.end());/*把number_order容器中的内容按照从小到大的顺序排列,这里面是X的坐标*/for (int i = 0; i < num_order.size(); i++) {Rect number_rect = boundingRect(contours[num_map.find(num_order[i])->second]);//num_order里面放的是坐标//cout<<"num_map的值是:"<<num_map.find(num_order[i])->second<<endl;Rect choose_rect(number_rect.x, 0, number_rect.width, img.rows);//矩形左上角x,y的坐标以及矩形的宽和高Mat number_img = img(choose_rect);resize(number_img,number_img,Size(30,100));//归一化尺寸ROI_image.push_back(number_img);//保存为待测图片//imshow("number" + to_string(i), number_img);char name[50];sprintf_s(name,"D:\\vs2012\\model\\%d.jpg",i);//保存模板imwrite(name, number_img);  }cout<<"图片分割完毕"<<endl;//加载模板vector<Mat>temptImage;//存放模板for (int i=0;i<4;i++){char name[50];sprintf_s(name,"D:\\vs2012\\model\\%d.jpg",i);Mat temp;temp=imread(name);//cout<<"加载模板图片通道数:"<<temp.channels()<<endl;temptImage.push_back(temp);}vector<int>seq;//存放顺序结果for (int i=0;i<ROI_image.size();i++){Mat subImage;int sum=0;int min=50000;int seq_min=0;//记录最小的和对应的数字for (int j=0;j<4;j++){absdiff(ROI_image[i],temptImage[j],subImage);//待测图片像素减去模板图片像素sum=sunImage(subImage);//统计像素和if (sum<min){min=sum;seq_min=j;}sum=0;}seq.push_back(seq_min);}cout<<"输出数字匹配结果:";//endl是换行的意思for (int i=0;i<seq.size();i++)//输出结果,小数点固定在第3位{cout<<seq[i];if (i==1){cout<<".";}}finish=clock();double all_time=double(finish-start)/CLOCKS_PER_SEC;/*cout<<"运行总时间是:"<<all_time<<endl;*/waitKey(0);return 0;
}
//计算像素和
int sunImage(Mat &image)
{int sum=0;for (int i=0;i<image.cols;i++){for (int j=0;j<image.rows;j++){sum+=image.at<uchar>(j,i);}}return sum;
}

整体思路是这样子的:0-9这10个数字也都是已经被分割好的,并且保存好了,也就是模板,然后我们把待测的图片也分割掉,然后从0-9模板文件夹中去读取模板图片,让待测的分割完毕的图片去和10个模板逐个相减,然后去统计他们相减后的像素和,如果这个在这10个中最低,那么他们就是同一个数字,然后输出值就可以了,分割后的大概是这样

上边是第一种方法,然后还有第二种,是穿针引线的方法,是根据晶体管数字特征来识别的

这是晶体管数字的特征,每个0-9每个数字都是不一样的,我们下一篇文章再做详细的介绍

基于opencv的简单数字识别相关推荐

  1. 数字识别java开源_Java基于opencv实现图像数字识别(三)—灰度化和二值化

    Java基于opencv实现图像数字识别(三)-灰度化和二值化 一.灰度化 灰度化:在RGB模型中,如果R=G=B时,则彩色表示灰度颜色,其中R=G=B的值叫灰度值:因此,灰度图像每个像素点只需一个字 ...

  2. Java基于opencv实现图像数字识别(一),java开发面试笔试题

    我总结出了很多互联网公司的面试题及答案,并整理成了文档,以及各种学习的进阶学习资料,免费分享给大家. 扫描二维码或搜索下图红色VX号,加VX好友,拉你进[程序员面试学习交流群]免费领取.也欢迎各位一起 ...

  3. java图片降噪_Java基于opencv实现图像数字识别(四)—图像降噪

    Java基于opencv实现图像数字识别(四)-图像降噪 我们每一步的工作都是基于前一步的,我们先把我们前面的几个函数封装成一个工具类,以后我们所有的函数都基于这个工具类 这个工具类呢,就一个成员变量 ...

  4. Java基于opencv实现图像数字识别(一)

    Java基于opencv实现图像数字识别(一) 最近分到了一个任务,要做数字识别,我分配到的任务是把数字一个个的分开:当时一脸懵逼,直接百度java如何分割图片中的数字,然后就百度到了用Buffere ...

  5. 基于OpenCV 实现银行卡数字识别

    银行卡数字识别 下面展示一张银行卡的结果,左图为灰度图,右图为结果. 开始之前,我们先导入需要的库,再定义一个画图函数,方便后续展示.为了方便大家理解,全文只有这一个自定义函数,我尽量多分成几个步骤来 ...

  6. 基于OpenCV的简单人脸识别系统

    目录 1. 调用库函数 2. 调用摄像头并设置窗口 3. 设置图片正负样本数据集的路径 4. 调用人脸检测器 5. 正负样本载入 6.提取人脸区域 7. 建立LBPH人脸识别模型 8. 实时检测 9. ...

  7. Python基于OpenCV的人脸表情识别系统[源码&部署教程]

    1.项目背景 人脸表情识别是模式识别中一个非常重要却十分复杂的课题.首先对计算机人脸表情识别技术的研究背景及发展历程作了简单回顾.然后对近期人脸表情识别的方法进行了分类综述.通过对各种识别方法的分析与 ...

  8. OpenCV-Python中的简单数字识别OCR

    本文翻译自:Simple Digit Recognition OCR in OpenCV-Python I am trying to implement a "Digit Recogniti ...

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

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

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

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

最新文章

  1. spring boot系列03--spring security (基于数据库)登录和权限控制(下)
  2. Android抽屉(SlidingDrawer --类似android通知栏下拉效果)
  3. 18、Java并发性和多线程-饥饿与公平
  4. python中列表生成式strip_python之列表生成式
  5. 谭晓生大闹中国计算机中心,360高管谭晓生不满中国计算机大会拖堂和临时加议程,现场摔话筒发飙...
  6. 人工神经网络概念及组成,人工神经网络基本概念
  7. vue引入图片的方式
  8. 期货交易中期货公司和柜台的基础知识
  9. 小布老师oralce讲座笔记(六)
  10. 考研复习之数据结构笔记(九)树(上)(树和二叉树的概念、特征、性质及相关实例)
  11. mysql中utf8和utf8mb4的详解用法与区别
  12. 2013互联网公司找工作--大牛总结(ZJU)
  13. 腾讯安全“护航舰”亮相网安周,数实融合共筑产业安全防线
  14. WPF 在编译时 显示 CS0426 类型“xxx”中不存在类型名“xxx”
  15. Linux下IO监控与分析 --转载
  16. Linux 网络编程——TCP/IP 数据包格式解析
  17. Gps车辆监控软件平台开发技术精华
  18. SAP中使用MM01创建物料如何选定行业领域和物料类型
  19. anaconda创建环境为空、修改默认环境位置
  20. 修复计算机英语翻译,修复用英语怎么说_修复英文怎么说_修复英文翻译_趣词词典...

热门文章

  1. “时间复杂度”的另类解释
  2. LED字体下载,可视化大屏,数据可视化必备
  3. ui设计app设计风格有哪些?ui设计app界面设计流程是什么?
  4. 基于深度学习的单目2D/3D姿态估计综述(2021)
  5. 蜂巢输入法android,讯飞输入法“蜂巢II”输入模型 内核提速便捷实用
  6. jetson nano opencv 打开 CSI摄像头_opencv-python图形图像处理入门基础知识
  7. 腾讯前辈熬夜肝了一个月整理的《Linux内核学习笔记》,啃完受益匪浅不走弯路
  8. cropper使用说明
  9. IPv4与IPv6地址转换
  10. ipv6overipv4+linux,IPv4 over IPv6 的配置