基于模糊特征的文字识别实习原理如下:
代码如下:(在OPENCV环境下编写)
#pragma comment(lib, "opencv_imgproc220d.lib")
#pragma comment(lib, "opencv_highgui231d.lib")
#pragma comment(lib, "opencv_core231d.lib")
#include "highgui.h"
#include <math.h>
#include <cv.h>
#include "stdio.h"
#include "stdlib.h"
#include "math.h"
#define N 26 //字母数量
#define dimNum 8 //向量维数
#define min(a, b) (a<b?a:b)
#define max(a, b) (a>b?a:b)
CvSize letterSize;
double letterVector[N][dimNum];
void getFuzzyVector(IplImage *srcPic); //获取26个字母的迷糊向量
void letterMatch(IplImage *testPic); //字母匹配
void fuzzyNearness(double *src); //贴进度计算
void main()
{
IplImage *srcPic;
srcPic = cvLoadImage("1.bmp", 0);
if(srcPic==NULL)
{
printf("打开训练图片错误\n");
exit(0);
}
IplImage *testPic;
testPic = cvLoadImage("test.bmp", 0);
if(testPic==NULL)
{
printf("打开测试图片错误\n");
exit(0);
}
getFuzzyVector(srcPic); //获取26个字母的模糊向量
letterMatch(testPic); //字母匹配
cvShowImage("训练图片", srcPic);
cvShowImage("测试图片", testPic);
cvWaitKey(0);
cvDestroyAllWindows();
cvReleaseImage(&testPic);
cvReleaseImage(&srcPic);
}
//贴进度计算
void fuzzyNearness(double *src)
{
int i, j, laber;
double sum, maxNum;
double Y[N];
double temp[dimNum];
double minNum;
bool flag = false;
double innerMul[N];
double outerMul[N];
//欧几里得贴进度
for(i=0; i<N; i++)
{
sum = 0;
for(j=0; j<dimNum; j++)
sum += (src[j]-letterVector[i][j])*(src[j]-letterVector[i][j]);
Y[i] = 1-sqrtf(sum)/sqrtf(dimNum);
}
//输出结果
maxNum = Y[0];
laber = 0;
for(i=1; i<N; i++)
if(maxNum<Y[i])
{
maxNum = Y[i];
laber = i;
}
printf("%c ", laber+65);
}
//字母匹配
void letterMatch(IplImage *testPic)
{
int i, j;
int flag = 0;
CvScalar scalar;
int xPixelNum, yPixelNum;
int yTop, yDown, xLeft, xRight;
int letterHeight, letterWidth;
CvPoint centre;
IplImage *cannyPic = cvCreateImage(cvGetSize(testPic), testPic->depth, 1);
cvCanny(testPic, cannyPic, 50, 150, 3);
//寻找Y坐标
yTop = yDown = 0;
for(i=0; i<cannyPic->height; i++)
{
yPixelNum = 0;
for(j=0; j<cannyPic->width; j++)
{
scalar = cvGet2D(cannyPic, i, j);
if(scalar.val[0] == 255)
yPixelNum++;
}
if(yPixelNum>=2 && flag == 0)
{
yTop = i;
flag = 1;
}
if(flag == 1 && yPixelNum<2)
{
yDown = i;
flag = 0;
if((yDown-yTop)<5)
yDown = yTop = 1;
else
letterHeight = yDown-yTop;
}
}
int k, x, y, m, n;
CvScalar ROIScalar;
//寻找x坐标
k=0;
flag = 0;
xLeft = xRight = 0;
for(i=0; i<cannyPic->width; i++)
{
xPixelNum = 0;
for(j=yTop; j<=yDown; j++)
{
scalar = cvGet2D(cannyPic, j, i);
if(scalar.val[0]==255)
xPixelNum++;
}
if(flag==0 && xPixelNum>=2)
{
xLeft = i;
flag = 1;
}
if(flag==1 && xPixelNum<2)
{
xRight = i;
flag = 0;
if((xRight-xLeft)<3)
xLeft = xRight = 1;
else
{
double testVector[dimNum] = {0};
double tempWidth;
tempWidth = xRight-xLeft;
centre.x = xLeft+tempWidth/2;
centre.y = yTop+letterHeight/2;
letterWidth = letterHeight;
IplImage *ROIPic = cvCreateImage(cvSize(letterHeight, letterWidth), cannyPic->depth, cannyPic->nChannels);
cvSetImageROI(cannyPic, cvRect(centre.x-letterWidth/2, yTop, letterHeight, letterWidth));
cvCopyImage(cannyPic, ROIPic);
cvResetImageROI(cannyPic);
//八个方向向量
//左边
for(x=0; x<ROIPic->width; x++)
{
ROIScalar = cvGet2D(ROIPic, ROIPic->height/2, x);
if(ROIScalar.val[0]==255)
{
testVector[0] = x;
break;
}
}
//右边
for(x=ROIPic->width-1; x>=0; x--)
{
ROIScalar = cvGet2D(ROIPic, ROIPic->height/2, x);
if(ROIScalar.val[0]==255)
{
testVector[1] = ROIPic->width-x;
break;
}
}
//上边
for(y=0; y<ROIPic->height; y++)
{
ROIScalar = cvGet2D(ROIPic, y, ROIPic->width/2);
if(ROIScalar.val[0]==255)
{
testVector[2] = x;
break;
}
}
//下边
for(y=ROIPic->height-1; y>=0; y--)
{
ROIScalar = cvGet2D(ROIPic, y, ROIPic->width/2);
if(ROIScalar.val[0]==255)
{
testVector[3] = ROIPic->height-x;
break;
}
}
//左上
for(x=0; x<ROIPic->width; x++)
{
ROIScalar = cvGet2D(ROIPic, x, x);
if(ROIScalar.val[0]==255)
{
testVector[4] = sqrtf(2*x*x);
break;
}
}
//右下
for(x=ROIPic->width-1, y=ROIPic->height-1; x>=0 && y>=0; y--,x--)
{
ROIScalar = cvGet2D(ROIPic, y, x);
if(ROIScalar.val[0]==255)
{
testVector[5] = sqrtf((ROIPic->height-y)*(ROIPic->height-y)+(ROIPic->width-x)*(ROIPic->width-x));
break;
}
}
//右上
for(x=ROIPic->width-1, y=0; x>=0 && y<ROIPic->height; y++,x--)
{
ROIScalar = cvGet2D(ROIPic, y, x);
if(ROIScalar.val[0]==255)
{
testVector[6] = sqrtf(2*y*y);
break;
}
}
//左下
for(x=0, y=ROIPic->height-1; x<ROIPic->width; y--,x++)
{
ROIScalar = cvGet2D(ROIPic, y, x);
if(ROIScalar.val[0]==255)
{
testVector[7] = sqrtf(2*x*x);
break;
}
}
//生成模糊向量
double maxDis;
maxDis = testVector[0];
//寻找最大距离
for (m=1; m<dimNum; m++)
if(maxDis<testVector[m])
maxDis = testVector[m];
//模糊化
for(m=0; m<dimNum; m++)
testVector[m] = testVector[m]/maxDis;
//计算贴进度
fuzzyNearness(testVector);
}
}
}
}
//获取26个字母的迷糊向量
void getFuzzyVector(IplImage *srcPic)
{
int i, j;
int flag = 0;
CvScalar scalar;
int xPixelNum, yPixelNum;
int yTop, yDown, xLeft, xRight;
int letterHeight, letterWidth;
CvPoint centre;
IplImage *cannyPic = cvCreateImage(cvGetSize(srcPic), srcPic->depth, 1);
cvCanny(srcPic, cannyPic, 50, 150, 3);
//寻找Y坐标
yTop = yDown = 0;
for(i=0; i<cannyPic->height; i++)
{
yPixelNum = 0;
for(j=0; j<cannyPic->width; j++)
{
scalar = cvGet2D(cannyPic, i, j);
if(scalar.val[0] == 255)
yPixelNum++;
}
if(yPixelNum>=20 && flag == 0)
{
yTop = i;
flag = 1;
}
if(flag == 1 && yPixelNum<20)
{
yDown = i;
flag = 0;
if((yDown-yTop)<8)
yDown = yTop = 1;
else
letterHeight = yDown-yTop;
}
}
int k, x, y, m, n;
CvScalar ROIScalar;
//寻找x坐标
k=0;
flag = 0;
xLeft = xRight = 0;
for(i=0; i<cannyPic->width; i++)
{
xPixelNum = 0;
for(j=yTop; j<=yDown; j++)
{
scalar = cvGet2D(cannyPic, j, i);
if(scalar.val[0]==255)
xPixelNum++;
}
if(flag==0 && xPixelNum>=2)
{
xLeft = i;
flag = 1;
}
if(flag==1 && xPixelNum<2)
{
xRight = i;
flag = 0;
if((xRight-xLeft)<3)
xLeft = xRight = 1;
else
{
double tempWidth;
tempWidth = xRight-xLeft;
centre.x = xLeft+tempWidth/2;
centre.y = yTop+letterHeight/2;
letterWidth = letterHeight;
IplImage *ROIPic = cvCreateImage(cvSize(letterHeight, letterWidth), cannyPic->depth, cannyPic->nChannels);
cvSetImageROI(cannyPic, cvRect(centre.x-letterWidth/2, yTop, letterHeight, letterWidth));
cvCopyImage(cannyPic, ROIPic);
cvResetImageROI(cannyPic);
//八个方向向量
//左边
for(x=0; x<ROIPic->width; x++)
{
ROIScalar = cvGet2D(ROIPic, ROIPic->height/2, x);
if(ROIScalar.val[0]==255)
{
letterVector[k][0] = x;
break;
}
}
//右边
for(x=ROIPic->width-1; x>=0; x--)
{
ROIScalar = cvGet2D(ROIPic, ROIPic->height/2, x);
if(ROIScalar.val[0]==255)
{
letterVector[k][1] = ROIPic->width-x;
break;
}
}
//上边
for(y=0; y<ROIPic->height; y++)
{
ROIScalar = cvGet2D(ROIPic, y, ROIPic->width/2);
if(ROIScalar.val[0]==255)
{
letterVector[k][2] = x;
break;
}
}
//下边
for(y=ROIPic->height-1; y>=0; y--)
{
ROIScalar = cvGet2D(ROIPic, y, ROIPic->width/2);
if(ROIScalar.val[0]==255)
{
letterVector[k][3] = ROIPic->height-x;
break;
}
}
//左上
for(x=0; x<ROIPic->width; x++)
{
ROIScalar = cvGet2D(ROIPic, x, x);
if(ROIScalar.val[0]==255)
{
letterVector[k][4] = sqrtf(2*x*x);
break;
}
}
//右下
for(x=ROIPic->width-1, y=ROIPic->height-1; x>=0 && y>=0; y--,x--)
{
ROIScalar = cvGet2D(ROIPic, y, x);
if(ROIScalar.val[0]==255)
{
letterVector[k][5] = sqrtf((ROIPic->height-y)*(ROIPic->height-y)+(ROIPic->width-x)*(ROIPic->width-x));
break;
}
}
//右上
for(x=ROIPic->width-1, y=0; x>=0 && y<ROIPic->height; y++,x--)
{
ROIScalar = cvGet2D(ROIPic, y, x);
if(ROIScalar.val[0]==255)
{
letterVector[k][6] = sqrtf(2*y*y);
break;
}
}
//左下
for(x=0, y=ROIPic->height-1; x<ROIPic->width; y--,x++)
{
ROIScalar = cvGet2D(ROIPic, y, x);
if(ROIScalar.val[0]==255)
{
letterVector[k][7] = sqrtf(2*x*x);
break;
}
}
k++;
}
}
}
letterSize.height = letterHeight;
letterSize.width = letterWidth;
//生成模糊向量
double maxDis;
for(i=0; i<N; i++)
{
maxDis = letterVector[i][0];
//寻找最大距离
for (j=1; j<dimNum; j++)
if(maxDis<letterVector[i][j])
maxDis = letterVector[i][j];
//模糊化
for(j=0; j<dimNum; j++)
letterVector[i][j] = letterVector[i][j]/maxDis;
}
}
运行结果: