#include "cv.h" #include "highgui.h" #include "cxcore.h" #include <stdlib.h> #include <stdio.h> #define N 5//载入数字图片个数 char *testPic[] = {"test1.jpg"}; int thres = 115; //二值化阀值 int n_min = 80; //识别数字轮廓长度的下限 单位(像素) int n_max = 400; //识别数字轮廓长度的上限 //数字轮廓的长度和宽度 单位(像素) int n_width_min = 5, n_width_max = 40; int n_height_min = 30, n_height_max = 50; // 数组成员之间的距离小于一个阀值视为一个数 int n_width_n_min = 15, n_width_n_max = 40; char *picture[] = {"0.jpg", "1.jpg", "2.jpg", "3.jpg", "4.jpg"}; //数字图片集 这里储存白底黑子的数字图片 0 - 4; CvSeq *pic[N];//储存数字图片轮廓 CvSeq* GetImageContour(IplImage* srcIn,int flag = 0) { IplImage* src = cvCreateImage(cvGetSize(srcIn), 8, 1); //拷贝图像 cvCopy(srcIn, src); //创建空间 CvMemStorage* mem = cvCreateMemStorage(0); if(!mem){ printf("mem is NULL!"); } //二值化图像 cvThreshold(src, src, thres, 255, CV_THRESH_BINARY_INV); //计算图像轮廓 0-只获取最外部轮廓 1-获取全部轮廓 CvSeq* seq;//储存图片轮廓信息 if(flag == 0){ cvFindContours(src, mem, &seq, sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE, cvPoint(0,0)); } if(flag == 1){ cvFindContours(src, mem, &seq, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE, cvPoint(0,0)); } //释放图像空间 cvReleaseImage(&src); //返回轮廓信息 return seq; } //数字图片轮廓计算 void Init(void) { IplImage *src0, *src; for(int i = 0; picture[i] != 0; i++){ src0 = cvLoadImage(picture[i], CV_LOAD_IMAGE_GRAYSCALE); if(!src0){ printf("Couldn‘t load %s\n", picture[i]); exit(1); } src = cvCloneImage(src0); pic[i] = GetImageContour(src, 0);//只获取最外部轮廓 } } int ReadNumber(CvSeq* contoursTemp) { double tmp = 5,min = 5; int num = -1; for(int i = 0; i < N; i++){ tmp = cvMatchShapes(contoursTemp,pic[i],1); //匹配 if(tmp < min){ min = tmp; num = i; } } return num; } void Paixu(int numList[100][2], int count) //将数字按横坐标从左往右排列 { int tem = 0; int newList[100] = {0}; //数字融合后的新序列 for(int i = 0; i < count - 1; i++){ for(int j = i + 1; j < count; j++){ if(numList[i][1] > numList[j][1]){ //交换坐标 tem = numList[i][1]; numList[i][1] = numList[j][1]; numList[j][1] = tem; //交换数字 tem = numList[i][0]; numList[i][0] = numList[j][0]; numList[j][0] = tem; } } } if(count == 0){ printf("no number!"); } else{ for(int i = 0; i < count; i++){ printf("%d\t",numList[i][0]); } } //数字融合,可以自己改。。。。数字从左往右的顺序都在numList里面,[0]为数,[1]为坐标,自己可以根据数字间的距离判断是否为一个数 if(count == 2){ int width = 0; //两数字间的距离 width = numList[1][1] - numList[0][1]; if((width < n_width_n_max) && (width > n_width_n_min)){ tem = numList[0][0] * 10 + numList[1][0]; newList[0] = tem; } printf("the number is %d\t",newList[0]); } } int main() { Init();//初始化,在pic中储存所有图片轮廓 IplImage* img = cvLoadImage(testPic[0], CV_LOAD_IMAGE_GRAYSCALE); int travel = 1;//如果为0,识别中间数字,如果为1,识别右边数字.其他数字,全部识别 if(travel == 0){ CvRect ins; ins.x = 170; ins.y = 140; ins.width = 300; ins.height = 200; cvSetImageROI(img, ins); } if(travel == 1){ CvRect ins; ins.x = 470; ins.y = 140; ins.width = 165; ins.height = 200; cvSetImageROI(img, ins); } IplImage* imgColor = cvCreateImage(cvGetSize(img), 8, 3); IplImage* contoursImage = cvCreateImage(cvSize(img->width,img->height), 8, 1); CvSeq* contours = 0, *contoursTemp = 0; cvZero(contoursImage); contours = GetImageContour(img, 1);//获取轮廓信息 contoursTemp = contours; //对轮廓进行循环 int count=0; //数字轮廓个数 int numList[100][2]; //一幅图像中的数字序列 一维是数字,二维是数字所在横坐标 for(; contoursTemp != 0; contoursTemp = contoursTemp->h_next){ //如果符合数字轮廓长度条件 保留并画出 if(contoursTemp->total > n_min && contoursTemp->total < n_max){ int num = -1;//识别一幅图像中的一个数字 CvRect rect = cvBoundingRect(contoursTemp, 1); //根据序列,返回轮廓外围矩形 //如果满座数字轮廓长宽 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 >= 0){ numList[count][0] = num; //一维存数字 numList[count][1] = rect.x; //二维存数字横坐标 } //在原图上绘制轮廓外矩形 cvRectangle(imgColor, pt1, pt2, CV_RGB(0,255,0), 2); //提取外轮廓 上的所以坐标点 for(int i = 0; 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(0, 0, 255, 0)); } count++;//数字轮廓+1 } } } Paixu(numList, count); for(int i = 0; i < count; i++){ printf("%d(%d)\t", numList[i][0], numList[i][1]); } cvNamedWindow("image", 1); cvShowImage("image", imgColor); cvNamedWindow("contours"); cvShowImage("contours", contoursImage); cvWaitKey(5000);//停顿5秒钟 cvResetImageROI(imgColor); cvResetImageROI(img); cvReleaseImage(&img); cvReleaseImage(&contoursImage); cvReleaseImage(&imgColor); return 0; }
由于代码是从网上下载下来的,所以整理了一下发布出来。可以运行。
配置环境:VS2013 opencv3.0.0
缺点:识别率不高
源码下载地址:http://download.csdn.net/detail/sz76211822/8986931
时间: 2024-10-10 22:06:25