今天学习到了邮政编码识别,找到了相关理论与实际的代码,分析了一下,有些地方还不是很懂。 理论是看的杨淑莹的《图像识别与项目实践——VC++、matlab计术实现》 第四章–邮政编码识别。
下面是网上找到的字符识别相关程序
#include
#include
#include
#include
#include
#include
using namespace std;
IplImage* rotateImage2(IplImage* img, double angle)
{
//double angle = degree /180*CV_PI;
int step;
int i,j,k;
uchar*data ;
coutimageData;
for(i=0;iheight;i++)
for(j=0;jwidth;j++)
for(k=0;knChannels;k++)
data[i*step+j*img->nChannels+k]=255-data[i*step+j*img->nChannels+k];//反色
//保证原图可以任意角度旋转的最小尺寸
int tempLength = sqrt((double)width * width + (double)height *height) + 10;
int tempX = (tempLength + 1) / 2 - width / 2;
int tempY = (tempLength + 1) / 2 - height / 2;
IplImage* temp = cvCreateImage(cvSize(tempLength, tempLength), img->depth, img->nChannels);
cvZero(temp);
//将原图复制到临时图像tmp中心
cvSetImageROI(temp, cvRect(tempX, tempY, width, height));
cvCopy(img, temp, NULL);
cvResetImageROI(temp);
//旋转数组map
// [ m0 m1 m2 ] ===> [ A11 A12 b1 ]
// [ m3 m4 m5 ] ===> [ A21 A22 b2 ]
float m[6];
int w = temp->width;
int h = temp->height;
m[0] = b;
m[1] = a;
m[3] = -m[1];
m[4] = m[0];
// 将旋转中心移至图像中间
m[2] = w * 0.5f;
m[5] = h * 0.5f;
CvMat M = cvMat(2, 3, CV_32F, m);
cvGetQuadrangleSubPix(temp, img_rotate, &M);
step=img_rotate->widthStep/sizeof(uchar);
data = (uchar*)img_rotate->imageData;
for(i=0;iheight;i++)
for(j=0;jwidth;j++)
for(k=0;knChannels;k++)
data[i*step+j*img_rotate->nChannels+k]=255-data[i*step+j*img_rotate->nChannels+k];//反色
cvReleaseImage(&temp);
return img_rotate;
}
int otsu(const IplImage *src)
{
double sum=0.0;
double w0=0.0;
double w1=0.0;
double u0_temp=0.0;
double u1_temp=0.0;
double u0=0.0;
double u1=0.0;
double delta_temp=0.0;
double delta_max=0.0;
int pixel_count[256]={0};
float pixel_pro[256]={0};
int threshold=0;
uchar *data=(uchar *)src->imageData;
for(int i=0;iheight;i++)
{
for(int j=0;jwidth;j++)
{
pixel_count[(int)data[i*src->width+j]]++;
sum+=(int)data[i*src->width+j];
}
}
coutxx;
}
if(pt->x>rol_x1)
{
rol_x1=pt->x;
}
if(pt->y>rol_y1)
{
rol_y1=pt->y;
}
}
//cvRectangle(pBinary,cvPoint(rect.x,rect.y),cvPoint(rect.x+rect.width,rect.y+rect.height),CV_RGB(255,0,0),1,8,0);
}
rect.x=rol_x0;
rect.y=rol_y0;
rect.height = (rol_y1 - rol_y0);
rect.width = (rol_x1 - rol_x0);
cvRectangle(pBinary,cvPoint(rect.x,rect.y),cvPoint(rect.x+rect.width,rect.y+rect.height),CV_RGB(255,255,255),1,8,0);
cvReleaseMemStorage(&pStorage);
pStorage=NULL;
}
}
IplImage * rotateimage(IplImage *image)
{
IplImage *img1=cvCreateImage(cvGetSize(image),IPL_DEPTH_8U,1);
cvSmooth(image,img1,CV_GAUSSIAN,3,0,0,0);
int threshold=otsu(img1);
IplImage *img2=cvCreateImage(cvGetSize(img1),IPL_DEPTH_8U,1);
cvThreshold(img1,img2,threshold,255,CV_THRESH_BINARY);
FillInternalContours(img2,200);
return img2;
}
void FillInternalContours1(IplImage *image,double dAreaThre)
{
//cvCvtColor(image,image,CV_RGB2GRAY);
IplImage *image_bin=cvCreateImage(cvGetSize(image),8,1);
int Threshold=otsu(image);
cvThreshold(image, image_bin, Threshold, 255, CV_THRESH_BINARY);
double conarea=0.0;
CvSeq *pContour=NULL;
CvSeq *pConInner=NULL;
CvMemStorage *storage0=NULL;
int id=0;
char fgname[56]={0};
if(image)
{
storage0=cvCreateMemStorage(0);
cvFindContours(image_bin, storage0, &pContour, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
// 填充所有轮廓
cvDrawContours(image_bin, pContour, CV_RGB(255, 255, 255), CV_RGB(255, 255, 255), 2, CV_FILLED, 8, cvPoint(0, 0));
for (; pContour != NULL; pContour = pContour->h_next)
{
// 内轮廓循环
for (pConInner = pContour->v_next; pConInner != NULL; pConInner = pConInner->h_next)
{
conarea = fabs(cvContourArea(pConInner, CV_WHOLE_SEQ));
if(conarea |