掃描圖像中的數字字符可能大小不一,而後續ANN的訓練和識別都需要同一尺寸的字符對象,因此有必要對字符進行歸一化處理,使其具有相同的尺寸。
代碼如下:
/****************************************************************
功能: 字符歸一化
參數: img:有待歸一化的圖像
dst:歸一化後目標圖像
int nTargWidth:歸一化的目標寬度
int nTargHeight:歸一化的目標高度
RECT lpRect:等待縮放的矩形框
注 : 只能處理二值圖像
返回值: 縮放後的矩形框
***************************************************************/
RECT Ctry::RgnZoom(IplImage* img, IplImage* dst, int nTargWidth, int nTargHeight, RECT lpRect)
{
RECT retRT; //縮放後的區域矩形
double dXScale; //水平方向縮放因子
double dYScale; //豎直方法縮放因子
//確定縮放係數
dXScale = (double)nTargWidth / (lpRect.right - lpRect.left + 1);
dYScale = (double)nTargHeight / (lpRect.bottom - lpRect.top + 1);
int nSrc_i, nSrc_j; //映射源座標
retRT.top = lpRect.top;
retRT.bottom = retRT.top + nTargHeight;
retRT.left = lpRect.left;
retRT.right = retRT.left + nTargWidth;
//對圖像的區域矩形進行逐行掃描,通過像素映射完成縮放
for (int i = retRT.top; i < retRT.bottom; i++)
{
for (int j = retRT.left; j < retRT.right; j++)
{
//計算映射的源座標(最鄰近插值)
nSrc_i = retRT.top + int((i - retRT.top) / dYScale);
nSrc_j = retRT.left + int((j - retRT.left) / dXScale);
//對應像素賦值
double pixel = cvGetReal2D(img, nSrc_i, nSrc_j);
cvSetReal2D(dst, i, j, pixel);
}
}
return retRT;
}
在上一篇博客文章《中字符分割二》中得到矩形框,然後調用此函數,完整代碼如下:
void Ctry::ObjectNorm()
{
// TODO: 在此添加命令處理程序代碼
IplImage* img = cvLoadImage("C:\\Users\\Administrator\\Desktop\\dst.jpg", -1);
vector<RECT> vecRECTBig;
vecRECTBig = ObjectSegment(img, 260);//該函數見上一篇博客《字符分割二》
IplImage *norm = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);
for (int i = 0; i < norm->height; i++)
{
for (int j = 0; j < norm->width; j++)
{
cvSetReal2D(norm, i, j, 255);
}
}
for (int i = 0; i < vecRECTBig.size(); i++)
{
RECT rt = vecRECTBig[i]; //取得一個矩形輪廓
vecRECTBig[i] = RgnZoom(img, norm, 60, 100, rt);
int x = vecRECTBig[i].left - 1;
int y = vecRECTBig[i].top - 1;
int x1 = vecRECTBig[i].right + 1;
int y1 = vecRECTBig[i].bottom + 1;
CvPoint pt1(x, y);
CvPoint pt2(x1, y1);
cvRectangle(norm, pt1, pt2, CV_RGB(255, 0, 0), 1);
}
cvSaveImage("C:\\Users\\Administrator\\Desktop\\norm.jpg", norm);
}
效果圖:
原圖: