C++ opencv 数字识别
#include "cv.h"
#include "highgui.h"
#include "cxcore.h"
#include <stdlib.h>
#include <stdio.h>
#define N 5//载入数字图片个数 char *testPic[] = {"test1.jpg"};
int thres = ; //二值化阀值 int n_min = ; //识别数字轮廓长度的下限 单位(像素)
int n_max = ; //识别数字轮廓长度的上限 //数字轮廓的长度和宽度 单位(像素)
int n_width_min = , n_width_max = ;
int n_height_min = , n_height_max = ; // 数组成员之间的距离小于一个阀值视为一个数
int n_width_n_min = , n_width_n_max = ; char *picture[] = {"0.jpg", "1.jpg", "2.jpg", "3.jpg", "4.jpg"}; //数字图片集 这里储存白底黑子的数字图片 0 - 4;
CvSeq *pic[N];//储存数字图片轮廓 CvSeq* GetImageContour(IplImage* srcIn,int flag = )
{
IplImage* src = cvCreateImage(cvGetSize(srcIn), , ); //拷贝图像
cvCopy(srcIn, src); //创建空间
CvMemStorage* mem = cvCreateMemStorage(); if(!mem){
printf("mem is NULL!");
} //二值化图像
cvThreshold(src, src, thres, , CV_THRESH_BINARY_INV); //计算图像轮廓 0-只获取最外部轮廓 1-获取全部轮廓
CvSeq* seq;//储存图片轮廓信息
if(flag == ){
cvFindContours(src, mem, &seq, sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE, cvPoint(,));
}
if(flag == ){
cvFindContours(src, mem, &seq, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE, cvPoint(,));
} //释放图像空间
cvReleaseImage(&src); //返回轮廓信息
return seq;
} //数字图片轮廓计算
void Init(void)
{
IplImage *src0, *src;
for(int i = ; picture[i] != ; i++){
src0 = cvLoadImage(picture[i], CV_LOAD_IMAGE_GRAYSCALE);
if(!src0){
printf("Couldn't load %s\n", picture[i]);
exit();
}
src = cvCloneImage(src0);
pic[i] = GetImageContour(src, );//只获取最外部轮廓
}
} int ReadNumber(CvSeq* contoursTemp)
{
double tmp = ,min = ;
int num = -;
for(int i = ; i < N; i++){
tmp = cvMatchShapes(contoursTemp,pic[i],); //匹配
if(tmp < min){
min = tmp;
num = i;
}
}
return num;
} void Paixu(int numList[][], int count) //将数字按横坐标从左往右排列
{
int tem = ;
int newList[] = {}; //数字融合后的新序列
for(int i = ; i < count - ; i++){
for(int j = i + ; j < count; j++){
if(numList[i][] > numList[j][]){
//交换坐标
tem = numList[i][];
numList[i][] = numList[j][];
numList[j][] = tem; //交换数字
tem = numList[i][];
numList[i][] = numList[j][];
numList[j][] = tem;
}
}
}
if(count == ){
printf("no number!");
}
else{
for(int i = ; i < count; i++){
printf("%d\t",numList[i][]);
}
} //数字融合,可以自己改。。。。数字从左往右的顺序都在numList里面,[0]为数,[1]为坐标,自己可以根据数字间的距离判断是否为一个数
if(count == ){
int width = ; //两数字间的距离
width = numList[][] - numList[][];
if((width < n_width_n_max) && (width > n_width_n_min)){
tem = numList[][] * + numList[][];
newList[] = tem;
} printf("the number is %d\t",newList[]);
}
} int main()
{
Init();//初始化,在pic中储存所有图片轮廓
IplImage* img = cvLoadImage(testPic[], CV_LOAD_IMAGE_GRAYSCALE); int travel = ;//如果为0,识别中间数字,如果为1,识别右边数字.其他数字,全部识别
if(travel == ){
CvRect ins;
ins.x = ;
ins.y = ;
ins.width = ;
ins.height = ;
cvSetImageROI(img, ins);
}
if(travel == ){
CvRect ins;
ins.x = ;
ins.y = ;
ins.width = ;
ins.height = ;
cvSetImageROI(img, ins);
} IplImage* imgColor = cvCreateImage(cvGetSize(img), , );
IplImage* contoursImage = cvCreateImage(cvSize(img->width,img->height), , ); CvSeq* contours = , *contoursTemp = ;
cvZero(contoursImage);
contours = GetImageContour(img, );//获取轮廓信息
contoursTemp = contours; //对轮廓进行循环
int count=; //数字轮廓个数
int numList[][]; //一幅图像中的数字序列 一维是数字,二维是数字所在横坐标
for(; contoursTemp != ; contoursTemp = contoursTemp->h_next){
//如果符合数字轮廓长度条件 保留并画出
if(contoursTemp->total > n_min && contoursTemp->total < n_max){
int num = -;//识别一幅图像中的一个数字
CvRect rect = cvBoundingRect(contoursTemp, ); //根据序列,返回轮廓外围矩形 //如果满座数字轮廓长宽
if((rect.width >= n_width_min && rect.width <= n_width_max) && (rect.height >= n_height_min && rect.height <= n_height_max)){
//匹配该轮廓数字
num = ReadNumber(contoursTemp); //计算矩形顶点
CvPoint pt1,pt2;
pt1.x = rect.x;
pt1.y = rect.y;
pt2.x = rect.x + rect.width;
pt2.y = rect.y + rect.height; if(num >= ){
numList[count][] = num; //一维存数字
numList[count][] = rect.x; //二维存数字横坐标
} //在原图上绘制轮廓外矩形
cvRectangle(imgColor, pt1, pt2, CV_RGB(,,), ); //提取外轮廓 上的所以坐标点
for(int i = ; i < contoursTemp->total; i++){
CvPoint * pt = (CvPoint*)cvGetSeqElem(contoursTemp, i); // 读出第i个点。 cvSetReal2D(contoursImage, pt->y , pt->x , 255.0);
cvSet2D(imgColor, pt->y, pt->x,cvScalar(, , , ));
}
count++;//数字轮廓+1
}
}
} Paixu(numList, count);
for(int i = ; i < count; i++){
printf("%d(%d)\t", numList[i][], numList[i][]);
} cvNamedWindow("image", );
cvShowImage("image", imgColor); cvNamedWindow("contours");
cvShowImage("contours", contoursImage); cvWaitKey();//停顿5秒钟
cvResetImageROI(imgColor);
cvResetImageROI(img);
cvReleaseImage(&img);
cvReleaseImage(&contoursImage);
cvReleaseImage(&imgColor);
return ;
}
由于代码是从网上下载下来的,所以整理了一下发布出来。可以运行。
配置环境:VS2013 opencv3.0.0
缺点:识别率不高
源码下载地址:http://download.csdn.net/detail/sz76211822/8986931
C++ opencv 数字识别的更多相关文章
- opencv +数字识别
现在很多场景需要使用的数字识别,比如银行卡识别,以及车牌识别等,在AI领域有很多图像识别算法,大多是居于opencv 或者谷歌开源的tesseract 识别. 由于公司业务需要,需要开发一个客户端程序 ...
- OpenCV数字识别
输入命令: conda install opencv 返回信息:
- OpenCV 玩九宫格数独(二):knn 数字识别
欢迎大家关注腾讯云技术社区-博客园官方主页,我们将持续在博客园为大家推荐技术精品文章哦~ 作者:刘潇龙 前言 首先需要说明,这里所说的数字识别不是手写数字识别! 但凡对机器学习有所了解的人,相信看到数 ...
- Java基于opencv实现图像数字识别(五)—投影法分割字符
Java基于opencv实现图像数字识别(五)-投影法分割字符 水平投影法 1.水平投影法就是先用一个数组统计出图像每行黑色像素点的个数(二值化的图像): 2.选出一个最优的阀值,根据比这个阀值大或小 ...
- Java基于opencv实现图像数字识别(四)—图像降噪
Java基于opencv实现图像数字识别(四)-图像降噪 我们每一步的工作都是基于前一步的,我们先把我们前面的几个函数封装成一个工具类,以后我们所有的函数都基于这个工具类 这个工具类呢,就一个成员变量 ...
- Java基于opencv实现图像数字识别(三)—灰度化和二值化
Java基于opencv实现图像数字识别(三)-灰度化和二值化 一.灰度化 灰度化:在RGB模型中,如果R=G=B时,则彩色表示灰度颜色,其中R=G=B的值叫灰度值:因此,灰度图像每个像素点只需一个字 ...
- Java基于opencv实现图像数字识别(二)—基本流程
Java基于opencv实现图像数字识别(二)-基本流程 做一个项目之前呢,我们应该有一个总体把握,或者是进度条:来一步步的督促着我们来完成这个项目,在我们正式开始前呢,我们先讨论下流程. 我做的主要 ...
- Java基于opencv实现图像数字识别(一)
Java基于opencv实现图像数字识别(一) 最近分到了一个任务,要做数字识别,我分配到的任务是把数字一个个的分开:当时一脸懵逼,直接百度java如何分割图片中的数字,然后就百度到了用Buffere ...
- OpenCV+TensorFlow图片手写数字识别(附源码)
初次接触TensorFlow,而手写数字训练识别是其最基本的入门教程,网上关于训练的教程很多,但是模型的测试大多都是官方提供的一些素材,能不能自己随便写一串数字让机器识别出来呢?纸上得来终觉浅,带着这 ...
随机推荐
- 「USACO08JAN」电话线Telephone Lines
传送门 Luogu 解题思路 考虑二分,每次把大于二分值的边的权设为1,小于等于的设为0,如果最短路<=k则可行,记得判无解 细节注意事项 咕咕咕 参考代码 #include <algor ...
- 「LuoguP3979」遥远的国度
传送门 Luogu 解题思路 带换根操作的树剖. 换根只会影响更新或查询子树信息的操作. 我们始终保持初始的根不变,然后只要分类讨论一下: 假设当前被查询的节点是 \(u\) 如果 \(u\) 就是根 ...
- app开屏广告
最近公司有个需求需要做app开屏广告(跳转到不同的页面)--下面是app开屏广告的处理 1.管理后台效果图 (1)广告链接--商品详情 (2)广告链接--关联模块 (3)广告链接--消息富文本 (4) ...
- PyQt5点击菜单栏弹出新窗口,解决新窗口闪退的实现方法
实现的功能为:当点击菜单中某个菜单时,会弹出一个新窗口,下面就列出部分代码 def mail_setting(self): log.debug("open mail settings&quo ...
- Java读取压缩文件信息
不解压压缩文件,获取其中包含的文件,通过文件名检查是否包含非法文件.(后续再根据文件头或内容吧) zip: import java.util.zip.ZipEntry;import java.util ...
- C++ Primer Plus 6 笔记(3)
第5章 1.cout在显示bool值之前将它们转换为int,但cout.setf(ios:: boolalpha)函数调用设置了一个标记,该标记命令cout显示true和false,而不是1和0 2. ...
- numpy高级函数:where与extract
numpy高级函数:where与extract 1.numpy.where()函数,此函数返回数组中满足某个条件的元素的索引: import numpy as np x = np.array([[1, ...
- sklearn调用分类算法的评价指标
sklearn分类算法的评价指标调用#二分类问题的算法评价指标import numpy as npimport matplotlib.pyplot as pltimport pandas as pdf ...
- 使用vim编译.cpp文件
一.编写代码 1.打开命令行终端,输入vim test.cpp,新建了一个文件叫做“test.cpp”:如果以前已经建立过这个文件,则是打开这个名字的文件. 2.按回车进入编辑界面,输入i进入编辑模式 ...
- java 垒骰子
垒骰子 赌圣atm晚年迷恋上了垒骰子,就是把骰子一个垒在另一个上边,不能歪歪扭扭,要垒成方柱体. 经过长期观察,atm 发现了稳定骰子的奥秘:有些数字的面贴着会互相排斥! 我们先来规范一下骰子:1 的 ...