车牌断裂区域的融合

 在车牌识别中,常常会遇到车牌断裂的情形。导致这种原因的可能是:执行形态学 操作时(开运算、闭运算)的结构元素太小,而车牌区域过大的情形。此时出现断裂的车牌就需要进行区域的融合,使其断裂的区域重新成为一个连通域。车牌断裂的情形比如有如下情形:

形态学操作导致车牌断裂

  **形态学操作导致车牌断裂:**

原图中A 和 9 的距离过长

 **原图中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;

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;

}

如图:
车牌断裂情形

           **车牌断裂情形**

执行区域融合效果

           **执行区域融合效果,图中黑色圆点为矩形的重心点**

最终形成的连通域

            **最终形成的连通域**

    此处需要说明的是,函数里面的参数,如分布的比率以及 最小面积 等 需要调试后再确定,不同的需求可能参数值不同

你可能感兴趣的:(形态学,车牌识别,区域融合)