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