opencv图像识别数字,opencv 识别

opencv图像识别数字,opencv 识别,如何基于opencv实现简单的数字识别

现在很多场景需要使用的数字识别,比如银行卡识别,以及车牌识别等,在人工智能领域有很多图像识别算法,大多是居于opencv或者谷歌开源的超正方体识别,下面这篇文章主要给大家介绍了关于如何基于opencv实现简单的数字识别,需要的朋友可以参考下

目录

前言要解决的问题解决问题的思路总结

前言

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

要解决的问题

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

这是投资收益率图片,我们要做的就是识别出该照片中的数字,

解决问题的思路

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

#包含opencv2/core/core.hpp

#包含opencv.hpp

#包含opencv2/highgui/highgui.hpp

#包含opencv 2/特性2d/特性2d。HPP

#包含opencv2/imgproc/imgproc.hpp

#包括输入输出流

#包括ctime

使用命名空间标准

使用名称空间cv;

#包含地图

Mat src _阈值;

Mat src _ dil

int太阳图像(Mat图像);

vectorMatROI _ image//待测图片

int main()

{

时钟_t开始,结束;

开始=时钟();

Mat src

src=im read( D: vs pic picture number 6。jpg’);

resize(src,src,Size(src.cols/7,src。行数/7));

imshow(src ,src);

Mat src _ gray

cvtColor(src,src_gray,COLOR _ bgr 2 gray);

//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(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);

vectorvectorPointcontours _ src

vec 4 I hierarchy _ src(contours _ src。size());

findContours(src_canny,contours_src,hierarchy_src,RETR)外部,CHAIN _ approximate _ NONE);

rect rect _ s;

Rect选择_ rect

for(size _ t I=0;图标旅游_ src。size();我)

{

rect _ s=边界矩形(contours _ src[I]);

双倍宽度=矩形宽度

双倍高度=rect _ s.height

double bizhi=宽度/高度;

如果(比直1.5高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 _ bgr 2 gray);

//高斯模糊

Mat img _ gau

GaussianBlur(gray_img,img_gau,Size(3,3),0,0);

//阈值分割

材料img _ seg

threshold(img_gau,img_seg,0,255,THRESH _ BINARY THRESH _ OTSU);

垫元素;

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);

向量向量点轮廓;

vectorVec4i层次结构(轮廓。size());

查找轮廓(img_canny,轮廓,层次,CV _ RETR _外部,CV_CHAIN_APPROX_NONE,Point());//寻找轮廓

int size=(int)(等高线。size());//轮廓的数量

//coutsizeendl;6个

//保存符号边框的序号

矢量数量顺序;//定义一个整型(同国际组织)国际组织容器

mapint,int num _ map//容器,需要关键字和模板对象两个模板参数,此处定义一个(同国际组织)国际组织作为索引,并拥有相关连的指向(同国际组织)国际组织的指针

for(int I=0;我尺寸;我)

{

//获取边框数据

rect number _ rect=bounding rect(contours[I]);

int width=number _ rect.width//获取矩形的宽

int height=number _ rect.height//获取矩形的高度

//去掉较小的干扰边框,筛选出合适的区域。

如果(宽度为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值一起放入地图容器,形成一对一的键值对。

*/

}

}

//按符号顺序提取

sort(num_order.begin()、num _ order . end());/*按从小到大的顺序排列number_order容器的内容,其中是x的坐标*/

for(int I=0;I num _ order . size();i ) {

rect number _ rect=bounding rect(contours[num _ map . find(num _ order[I])-second]);//num_order包含坐标。

cout num _ map的值为: num _ map . find(num _ order[I])-secondendl;

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:vs2012model%d.jpg ,I);//保存模板

imwrite(姓名,号码_ img);

}

Cout“图片分割完成”endl

//加载模板

vectorMattemptImage//存储模板

for(int I=0;i4;我)

{

char name[50];

sprintf_s(name, D:vs2012model%d.jpg ,I);

Mat温度;

temp=im read(name);

//cout 加载模板图像的通道数: temp . channels()endl;

temptimage . push _ back(temp);

}

vectorintseq//存储序列结果

for(int I=0;iROI _ image . size();我)

{

Mat子图像;

int sum=0;

int min=50000

int seq _ min=0;//记录最小和对应的数字

for(int j=0;j4;j)

{

absdiff(ROI_image[i],temptImage[j],subImage);//从待测图片的像素中减去模板图片的像素

sum=sunImage(子图像);//计算像素的总和

如果(总和)

{

min=sum

seq _ min=j;

}

sum=0;

}

seq . push _ back(seq _ min);

}

Cout 输出数字匹配结果:;//endl表示换行。

for(int I=0;iseq . size();I )//输出结果,小数点固定在第三位。

{

cout seq[I];

如果(i==1)

{

cout . ;

}

}

finish=clock();

double all_time=double(完成-开始)/CLOCKS _ PER _ SEC;

/*cout 总运行时间为: all _ timeendl*/

wait key(0);

返回0;

}

//计算像素的总和

中间太阳图像(Mat图像)

{

int sum=0;

for(int I=0;iimage.cols我)

{

for(int j=0;jimage.rowsj)

{

sum=image.atuchar(j,I);

}

}

返回总和;

}

整体思路是这样的:0-9这10个数字被分割保存,也就是模板。然后我们对待测图像进行分割,从0-9模板文件夹中读取模板图像,从10个模板中逐一减去分割后的图像,然后统计相减后的像素和。如果这是10个中最低的,那么它们是相同的数。然后

以上是第一种方法,然后还有第二种方法,就是穿线法,根据晶体管的数字特性来识别。

这就是晶体管数的特点。从0到9的每个数字都不一样。我们将在下一篇文章中详细介绍。

总结

关于如何基于opencv实现简单的数字识别的文章到此结束。有关opencv数字识别的更多信息,请搜索我们以前的文章或继续浏览下面的相关文章。希望你以后能支持我们!

opencv图像识别数字,opencv 识别