在车牌识别中,经常会遇到车牌断裂的情形。致使这种缘由的多是:执行形态学 操做时(开运算、闭运算)的结构元素过小,而车牌区域过大的情形。此时出现断裂的车牌就须要进行区域的融合,使其断裂的区域从新成为一个连通域。车牌断裂的情形好比有以下情形:
形态学操做致使车牌断裂:
原图中A 和 9 的距离过长 对于出现的断裂的情形,融合的算法取决于如何断定所断裂的区域具备某种联系? 融合算法首先应当考虑到情形断定两个区域之间的联系,便是否在同一水平、或者在同一竖直方向上,其次是要考虑车牌自己的特征。如车牌的颜色分布、字符纹理等先验知识。同时,为了不区域的错误融合,还应作一些区域距离上的限制。好比设定阈值,距离在该范围以内的知足条件。算法
这里给出区域融合的算法步骤: step 1. 获取全部轮廓外接矩形放入集合A中。 step 2. 遍历A,并考察矩形颜色的分布,若目标颜色(蓝、黄)比率较大,则放入候选矩形集合B中。 step 3. 考察集合B中矩形位置关系,若在同一水平(同一竖直)方向,而且知足限定的距离时,在两个区域中画线,使其融合。函数
对于区域融合,主要的难点在于如何合理的断定区域的正确性。因为咱们所取得的区域并不必定只包含有车牌区域,还有可能与噪声粘连在一块儿,这样会致使区域过大过宽带情形,区域位置变得不太明显。这里算法所取得方法是,计算区域的几何中心,利用几何中心评判区域的位置。 可靠性就会更高点。测试
区域的融合问题,目前只能想到这种方法,可能还有更好的算法更为可靠。
继昨天以后,进行上述算法,能够获得相要点结果。废话很少说,看代码:调试
<!-- lang: cpp --> void MergeProbabilityRectArea(IplImage* img_rgb,IplImage* in_imgBin)
{ if(img_rgb == NULL || in_imgBin == NULL) return; if((img_rgb->depth != 8 && img_rgb->nChannels != 3) || (in_imgBin->depth != 8 && in_imgBin->nChannels != 1)) return;code
const int nMinArea = 40; //定义最小面积 const int nMaxDist = 100; //允许的最大距离 const int nOffSet = 20; //允许的中心偏移量 int count = 0; int nRect = 0; CvRect* tmp_rect = 0; CvRect* coarseRect = 0; coarseRect = FindAllAreaRect(in_imgBin,nRect); //找到全部的区域 tmp_rect = new CvRect[nRect]; memset(tmp_rect,0,sizeof(CvRect)*nRect); //显示测试 //for(int i=0;i<nRect;i++) // cvRectangle(img_rgb,cvPoint(coarseRect[i].x,coarseRect[i].y), // cvPoint(coarseRect[i].x+coarseRect[i].width,coarseRect[i].y+coarseRect[i].height), // CV_RGB(0,255,0),3); //cvShowImage("img_rgb",img_rgb); for(int i=0;i<nRect;i++) { IplImage* img_tmp = NULL; int area = coarseRect[i].width * coarseRect[i].height; img_tmp = GetRectImage(img_rgb,coarseRect[i]); float colorRate = GetColorDistributed(img_tmp,NULL,COLOR_BLUE); //获取区域颜色分布的比率 if(area < nMinArea || colorRate < 0.02) continue; tmp_rect[count++] = coarseRect[i]; cvReleaseImage(&img_tmp); } for(int i=0;i<count;i++) { for(int j=i+1;j<count;j++) { CvPoint irtCentroid,jrtCentroid; GetRectCentroid(tmp_rect[i],irtCentroid); GetRectCentroid(tmp_rect[j],jrtCentroid); //whether in the horizontal direction if(abs(irtCentroid.y -jrtCentroid.y) < nOffSet) { int dist = 0; int x = MIN(irtCentroid.x,jrtCentroid.x); if(x == irtCentroid.x) { dist = jrtCentroid.x - (irtCentroid.x + tmp_rect[i].width / 2); } else { dist = irtCentroid.x - (jrtCentroid.x + tmp_rect[j].width / 2); } if(dist < nMaxDist) DrawLine(in_imgBin,tmp_rect[i],tmp_rect[j]); } //竖直方向上也差很少,这里代码缺省 } } delete [] coarseRect; delete [] tmp_rect; tmp_rect = NULL; coarseRect = NULL;
}it
如图: 车牌断裂情形
执行区域融合效果,图中黑色圆点为矩形的重心点
最终造成的连通域io
此处须要说明的是,函数里面的参数,如分布的比率以及 最小面积 等 须要调试后再肯定,不一样的需求可能参数值不一样