想要一个简单的文字识别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); } 希望能对你有所帮助!

评论