ocr.h头文件
ocr.cpp
训练的样子,可以自己做.也可以用这篇文章里面的例子opencv 写的 OCR
#pragma once #include <opencv2/core/core.hpp> #include <opencv2/opencv.hpp> #include <opencv2/ml/ml.hpp> class COcr { public: COcr(void); ~COcr(void); float classify(IplImage* img,int showResult);//将图片进行分类,得到最终结果 void test(); private: char file_path[255]; int train_samples;//单个特征码数量,如0,1各有10个特征码 int classes;//分类器数 数字0~9(10个)字母a~z(26个) CvMat* trainData; CvMat* trainClasses; int contourSize;//轮廓大小,统一放大或缩小样本大小为该值(正方形) static const int K=10; CvKNearest *knn; void getData(); /***************************************************************** * * Find the min box. The min box respect original aspect ratio image * The image is a binary data and background is white. * *******************************************************************/ void findX(IplImage* imgSrc,int* min, int* max){ int i; int minFound=0; CvMat data; CvScalar maxVal=cvRealScalar(imgSrc->width * 255); CvScalar val=cvRealScalar(0); //For each col sum, if sum < width*255 then we find the min //then continue to end to search the max, if sum< width*255 then is new max for (i=0; i< imgSrc->width; i++){ cvGetCol(imgSrc, &data, i); val= cvSum(&data); if(val.val[0] < maxVal.val[0]){ *max= i; if(!minFound){ *min= i; minFound= 1; } } } } void findY(IplImage* imgSrc,int* min, int* max){ int i; int minFound=0; CvMat data; CvScalar maxVal=cvRealScalar(imgSrc->width * 255); CvScalar val=cvRealScalar(0); //For each col sum, if sum < width*255 then we find the min //then continue to end to search the max, if sum< width*255 then is new max for (i=0; i< imgSrc->height; i++){ cvGetRow(imgSrc, &data, i); val= cvSum(&data); if(val.val[0] < maxVal.val[0]){ *max=i; if(!minFound){ *min= i; minFound= 1; } } } } CvRect findBB(IplImage* imgSrc){ CvRect aux; int xmin, xmax, ymin, ymax; xmin=xmax=ymin=ymax=0; findX(imgSrc, &xmin, &xmax); findY(imgSrc, &ymin, &ymax); aux=cvRect(xmin, ymin, xmax-xmin, ymax-ymin); return aux; } IplImage* preprocessing(IplImage* imgSrc,int new_width, int new_height){ IplImage* result; IplImage* scaledResult; CvMat data; CvMat dataA; CvRect bb;//bounding box //CvRect bba;//boundinb box maintain aspect ratio //Find bounding box bb=findBB(imgSrc); //Get bounding box data and no with aspect ratio, the x and y can be corrupted cvGetSubRect(imgSrc, &data, cvRect(bb.x, bb.y, bb.width, bb.height)); //Create image with this data with width and height with aspect ratio 1 //then we get highest size betwen width and height of our bounding box int size=(bb.width>bb.height)?bb.width:bb.height; result=cvCreateImage( cvSize( size, size ), 8, 1 ); cvSet(result,CV_RGB(255,255,255),NULL); //Copy de data in center of image int x=(int)floor((float)(size-bb.width)/2.0f); int y=(int)floor((float)(size-bb.height)/2.0f); cvGetSubRect(result, &dataA, cvRect(x,y,bb.width, bb.height)); cvCopy(&data, &dataA, NULL); //Scale result scaledResult=cvCreateImage( cvSize( new_width, new_height ), 8, 1 ); cvResize(result, scaledResult, CV_INTER_NN); //Release cvReleaseImage(&result); //Return processed data return scaledResult; } };
ocr.cpp
#include "StdAfx.h" #include "Ocr.h" IplImage* imagen; IplImage* screenBuffer; int drawing; int r,last_x, last_y; void draw(int x,int y){ //Draw a circle where is the mouse cvCircle(imagen, cvPoint(x,y), r, CV_RGB(0,0,0), -1, 4, 0); //Get clean copy of image screenBuffer=cvCloneImage(imagen); cvShowImage( "Demo", screenBuffer ); } void drawCursor(int x, int y){ //Get clean copy of image screenBuffer=cvCloneImage(imagen); //Draw a circle where is the mouse cvCircle(screenBuffer, cvPoint(x,y), r, CV_RGB(0,0,0), 1, 4, 0); } /************************* * Mouse CallBack * event: * #define CV_EVENT_MOUSEMOVE 0 * #define CV_EVENT_LBUTTONDOWN 1 * #define CV_EVENT_RBUTTONDOWN 2 * #define CV_EVENT_MBUTTONDOWN 3 * #define CV_EVENT_LBUTTONUP 4 * #define CV_EVENT_RBUTTONUP 5 * #define CV_EVENT_MBUTTONUP 6 * #define CV_EVENT_LBUTTONDBLCLK 7 * #define CV_EVENT_RBUTTONDBLCLK 8 * #define CV_EVENT_MBUTTONDBLCLK 9 * * x, y: mouse position * * flag: * #define CV_EVENT_FLAG_LBUTTON 1 * #define CV_EVENT_FLAG_RBUTTON 2 * #define CV_EVENT_FLAG_MBUTTON 4 * #define CV_EVENT_FLAG_CTRLKEY 8 * #define CV_EVENT_FLAG_SHIFTKEY 16 * #define CV_EVENT_FLAG_ALTKEY 32 * **************************/ void on_mouse( int event, int x, int y, int flags, void* param ) { last_x=x; last_y=y; drawCursor(x,y); //Select mouse Event if(event==CV_EVENT_LBUTTONDOWN) { drawing=1; draw(x,y); } else if(event==CV_EVENT_LBUTTONUP) { //drawing=!drawing; drawing=0; } else if(event == CV_EVENT_MOUSEMOVE && flags & CV_EVENT_FLAG_LBUTTON) { if(drawing) draw(x,y); } } COcr::COcr(void) { //initial sprintf(file_path , "../OCR/"); train_samples = 90;//加载样本越多,速度越慢 classes = 10; contourSize = 20; trainData = cvCreateMat(train_samples*classes, contourSize*contourSize, CV_32FC1); trainClasses = cvCreateMat(train_samples*classes, 1, CV_32FC1); getData(); knn = new CvKNearest(trainData, trainClasses, 0, false, K); } COcr::~COcr(void) { if(knn)delete knn; if(trainData)cvReleaseMat(&trainData); if(trainClasses)cvReleaseMat(&trainClasses); } float COcr::classify(IplImage* img,int showResult) { IplImage* prs_image; CvMat data; CvMat* nearest = cvCreateMat(1,K,CV_32FC1); float result; //process file prs_image = preprocessing(img, contourSize, contourSize); //Set data IplImage* img32 = cvCreateImage(cvSize( contourSize, contourSize ), IPL_DEPTH_32F, 1); cvConvertScale(prs_image, img32, 0.0039215, 0); cvGetSubRect(img32, &data, cvRect(0,0, contourSize,contourSize)); CvMat row_header, *row1; row1 = cvReshape(&data, &row_header, 0, 1); result = knn->find_nearest(row1,K,0,0,nearest,0); int accuracy=0; for(int i=0;i<K;i++){ if( nearest->data.fl[i] == result) accuracy++; } float pre=100*((float)accuracy/(float)K); if(showResult==1){ DebugString("|\t%.0f\t| \t%.2f%% \t| \t%d of %d \t| \n",result,pre,accuracy,K); DebugString(" ---------------------------------------------------------------\n"); } cvReleaseImage(&img32); cvReleaseImage(&prs_image); cvReleaseMat(&nearest); return result; } void COcr::getData() { IplImage* prs_image; CvMat row,data; char file[255]; int i,j; for(i =0; i<classes; i++){ for( j = 0; j< train_samples; j++){ //Load file if(j<10) sprintf(file,"%s%d/%d0%d.pbm",file_path, i, i , j); else sprintf(file,"%s%d/%d%d.pbm",file_path, i, i , j); IplImage* src_image = cvLoadImage(file,0); if(!src_image){ DebugString("Error: Cant load image %s\n", file); //exit(-1); } //process file prs_image = preprocessing(src_image, contourSize, contourSize);//原样本图处理指定大小的轮廓图 //Set class label cvGetRow(trainClasses, &row, i*train_samples + j); cvSet(&row, cvRealScalar(i)); //Set data cvGetRow(trainData, &row, i*train_samples + j); IplImage* img = cvCreateImage(cvSize(contourSize, contourSize), IPL_DEPTH_32F, 1); //convert 8 bits image to 32 float image cvConvertScale(prs_image, img, 0.0039215, 0); cvGetSubRect(img, &data, cvRect(0,0, contourSize,contourSize)); CvMat row_header, *row1; //convert data matrix sizexsize to vecor row1 = cvReshape(&data, &row_header, 0, 1); cvCopy(row1, &row, NULL); cvReleaseImage(&src_image); cvReleaseImage(&prs_image); cvReleaseImage(&img); } } } void COcr::test() { drawing=0; r=10; last_x=last_y=0; //Create image imagen=cvCreateImage(cvSize(128,128),IPL_DEPTH_8U,1); //Set data of image to white cvSet(imagen, CV_RGB(255,255,255),NULL); //Image we show user with cursor and other artefacts we need screenBuffer=cvCloneImage(imagen); //Create window cvNamedWindow( "Demo", 0 ); cvResizeWindow("Demo", 128,128); //Create mouse CallBack cvSetMouseCallback("Demo",&on_mouse, 0 ); //Main Loop int c = 0; while(true) { cvShowImage( "Demo", screenBuffer ); c = cvWaitKey(10); if( (char) c == 'x' ) break; if( (char) c== '+' ){ r++; drawCursor(last_x,last_y); } if( ((char)c== '-') && (r>1) ){ r--; drawCursor(last_x,last_y); } if( (char)c== 'r'){ cvSet(imagen, cvRealScalar(255),NULL); drawCursor(last_x,last_y); } if( (char)c== 's'){ cvSaveImage("out.png", imagen); } if( (char)c=='c'){ classify(imagen,1); } } cvDestroyWindow("Demo"); }
训练的样子,可以自己做.也可以用这篇文章里面的例子opencv 写的 OCR
收藏的用户(0) X
正在加载信息~
推荐阅读
最新回复 (1)
- FrancePvm632973 2017-2-22引用 2楼后来改良了一下图片处理函数,不用到文章提到的
CvRect findBB(IplImage* imgSrc)
这个用起来不精确.而且事先要处理一下二值化.
站点信息
- 文章2300
- 用户1336
- 访客10867881
每日一句
To be a happy man.
做一个幸福的人。
做一个幸福的人。
新会员