扫描图像中的数字字符可能大小不一,而后续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);
}
效果图:
原图: