自己封装的OCR类,测试OK!

Home / C++ MrLee 2017-2-7 3977

ocr.h头文件
#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

本文链接:https://www.it72.com/11764.htm

推荐阅读
最新回复 (1)
  • FrancePvm632973 2017-2-22
    引用 2
    后来改良了一下图片处理函数,不用到文章提到的
     CvRect findBB(IplImage* imgSrc)
    
    这个用起来不精确.而且事先要处理一下二值化.
返回