想要一个简单的文字识别vc源代码,从黑白图像中识别出文字,就是背景是白色,文字是黑色。只需简单识别英文26个大小写字母就够了。
--------------------------------------------------------------------------------
本回复被接受作为正确答案
做过类似的程序,用摄像头采集类似于电话充值卡的图象,对其的卡号,密码区域进行识别,只识别数字。(0-9)但原理相同,你只需改一下字库即可使用。
我先说下步骤:
1. 字符和字符之间都有间隔,首先要根据间隔确定每个字符的区域(Rect).
2. 然后一个一个象素地和标准字符比较。也就是比较 26 * 2 = 52 次,误差最小的,就认为是该字符。
(注:这种算法比较简单,易于理解,缺点就是效率不高,我用摄像头采集图象识别数字成功率为 98%以上。我曾请教过一位做这方面的专家,他称无论什么识别,影响识别的最重要因数就是源图象的质量。如果识别率不到 90% 请你仔细考虑源图象的采集质量,并重新考虑该方法的可行性。)
附代码如下:
/** 取得每个字符的边界***/
void CPOCRNuberDlg::GetCharRect(HBITMAP bit, RECT rect,int type, CDC* pDC )
{
CString strTemp2;
CBitmap bitmap;
bitmap.m_hObject = CopyImage(bit,IMAGE_BITMAP,0,0,LR_MONOCHROME);
//CDC *pDC = GetDC();
CDC mDC;
mDC.CreateCompatibleDC( pDC );
mDC.SetBoundsRect( &rect, DCB_RESET);
mDC.SelectObject(bitmap.m_hObject);
BOOL bIsChar = false;
corInfo = new OCR_Info[50];
int index = 0;
COLORREF colPix;
int iR;
int iG;
/************** 取出每个数字所占的Rect **************/
// 列扫描
CString str;
for (int i = rect.left; i < rect.right ; i++)
{
for (int j = rect.top - 250 ; j < rect.bottom - 250; j++)
{
colPix = mDC.GetPixel(i,j);
iG = GetGValue(colPix);
// 字符开始
if ( (iG == 0) && (!bIsChar) )
{
corInfo[index].rect.left = i;
corInfo[index].Index = index;
bIsChar = true;
break;
}
// 字符继续
else if ((iG == 0) && (bIsChar))
{
break;
}
// 字符结束
else if ((iG == 255) && ( j > rect.bottom -252) && (bIsChar))
{
corInfo[index].rect.right = i-1;
if ((corInfo[index].rect.right - corInfo[index].rect.left) > 3)
index++;
bIsChar = false;
break;
}
}
}
CClientDC lDC(this);
// 行扫描
bIsChar = false;
int iBZ =0;
for ( int iinx = 0; iinx < index; iinx++)
{
for (int ii = rect.top-250 ; ii < rect.bottom -250; ii++)
{
for (int j = corInfo[iinx].rect.left ; j < corInfo[iinx].rect.right ; j++)
{
colPix = mDC.GetPixel(j,ii);
iG = GetGValue(colPix);
// 字符顶端开始
if ( (iG == 0) && (!bIsChar) )
{
corInfo[iinx].rect.top = ii;
bIsChar = true;
break;
}
// 字符继续
else if ((iG == 0) && (bIsChar))
{
break;
}
// 字符底端结束
else if ((iG == 255) && ( j > corInfo[iinx].rect.right -2 ) && (bIsChar))
{
corInfo[iinx].rect.bottom = ii-1;
bIsChar = false;
break;
}
}
}
}
/****** 位置确定完成,每个字符的位置信息写在 corInfo.rect 中********/
char m_pFilePath[255];
CStdioFile fInfo;
strcpy(m_pFilePath,"D:\\info.ini");
fInfo.Open( m_pFilePath, CFile::modeCreate | CFile::modeWrite );
CDC NewDC;
NewDC.CreateCompatibleDC(pDC);
CBitmap memBmp;
memBmp.CreateCompatibleBitmap( &mDC, 14, 20 );
NewDC.SelectObject( memBmp );
/*
// 标志定义
iBZ =0;
BOOL bBZ = false;
for (int bn = 0; bn<index; bn++)
{
NewDC.StretchBlt( 0,0,14,20,
&mDC,corInfo[bn].rect.left +1,
corInfo[bn].rect.top +1,
corInfo[bn].rect.right - corInfo[bn].rect.left -1,
corInfo[bn].rect.bottom - corInfo[bn].rect.top -1,
SRCCOPY);
for (int yy = 0; yy <20; yy ++)
{
for (int xx = 0; xx <14;xx++)
{
colPix = NewDC.GetPixel(xx,yy);
iR = GetRValue(colPix);
if (iR == 255)
str = "□";
else
str ="■";
fInfo.WriteString(str);
}
fInfo.WriteString("\n");
}
str.Format("NEXT%d\n",bn);
fInfo.WriteString(str);
}
/************************** OCR **************************/
CString strField;
CString strtemp;
char cNum[281];
int iNumIndex = 0;
int iErrCount[10];
int iECount =0;
int iBlack = 0;
int idx = 0;
int ww =0;
int w = 0;
GetCurrentDirectory(255,m_pFilePath);
strcat(m_pFilePath,HOCRINI);
//strcat(m_pFilePath,"\\stdinfo.ini");
// 逐个扫描,识别
for (int l = 0; l<index; l++)
{
NewDC.StretchBlt( 0,0,14,20,
&mDC,corInfo[l].rect.left +1,
corInfo[l].rect.top +1,
corInfo[l].rect.right - corInfo[l].rect.left -1,
corInfo[l].rect.bottom - corInfo[l].rect.top -1,
SRCCOPY);
for (w = 0 ;w< 10; w++)
iErrCount[w] = 0;
for (int itmp = 0; itmp < 10; itmp++)
{
strtemp.Format("%d",itmp);
GetPrivateProfileString("Number",strtemp,"",
cNum,281,m_pFilePath);
for(int iy = 0; iy < 20; iy ++)
{
for(int ix = 0; ix<14;ix++)
{
colPix = NewDC.GetPixel(ix,iy);
iR = GetRValue(colPix);
if (iR == 255)
iR = 49;
else
iR = 48;
if ( iR != cNum[iNumIndex])
iErrCount[itmp]++;
iNumIndex++;
}
}
iNumIndex = 0;
}
iECount = iErrCount[0];
idx = 0;
for(ww =0; ww< 10; ww++)
{
if (iErrCount[ww] < iECount)
{
iECount = iErrCount[ww];
idx = ww;
}
}
// 区别1
if (idx != 1)
{
for (int itx = 7; itx < 9; itx++)
{
for (int ity = 0; ity < 20; ity++)
{
colPix = NewDC.GetPixel(itx,ity);
iR = GetRValue(colPix);
if (iR == 0)
iBlack++;
}
}
if (iBlack > 39)
{
idx = 1;
}
iBlack = 0;
}
// 再将0 和8 进行判断
if ((idx == 0) | (idx ==8))
{
for (int ity = 8; ity < 10; ity++)
{
for (int itx = 2; itx < 12; itx++)
{
colPix = NewDC.GetPixel(itx,ity);
iR = GetRValue(colPix);
if (iR == 0)
iBlack++;
}
}
if (iBlack > 14)
idx = 8;
else
idx = 0;
iBlack = 0;
}
// 再将5 和6 进行判断
if (( idx == 5) | (idx == 6))
{
}
str.Format("%d",idx);
strTemp2 += str;
/*
if (type == 1)
//m_CardNum += str;
else
//m_CardPWD += str;
*/
}
/*****************************************/
delete [] corInfo;
if (type == 1)
m_ctrlCardNum.SetWindowText( strTemp2 );
else
m_ctrlCardPWD.SetWindowText( strTemp2 );
//::ReleaseDC(m_hWnd,(HDC)pDC);
//UpdateData(false);
}
希望能对你有所帮助!
评论