车牌识别算法实现及其代码实现之二:字符分割

版权声明:本文为博主原创文章,欢迎转载,转载请注明出处。 https://blog.csdn.net/shanglianlm/article/details/78045170

本文地址:http://blog.csdn.net/shanglianlm/article/details/78045170

本文主要处理汽车车牌的识别过程,包括三个步骤,一:车牌区域检测,本文利用车牌的颜色和形状特征确认并获取汽车的车牌位置,二:字符分割,将获取到的汽车车牌按不同字符进行切割,三:车牌识别,最后利用模板匹配方式对切割的字符进行识别达到最终的车牌识别。

二 字符分割
1 首先对输入的车牌二值化,阈值使用最大类间方差法获取
这里写图片描述
代码

thresh = graythresh(Img);     %自动确定二值化阈值
bwImg = im2bw(Img,thresh);       %对图像二值化

2 去除上下左右边框 下图是图像的X轴(图像行累加)和Y轴(图像列累加)以及去除边框的车牌区域。
这里写图片描述
直观上来说,图像的边框上的值(行累加或者列累加)比较大,因此我们可以用下面条件去去除边框

边框的切割点满足两个条件:
a 切割点一般是图像的极大值点;
b 切割点距离图像边缘不是很远,一般在1/10范围内。
我们根据上述两个条件很容易去掉图像的边框。

3 左右切割,下图是去除边框后X轴(图像行累加)以及最后的切割点(绿色圆圈标识):
这里写图片描述
1)我们先设定每个字符的最小宽度,最大宽度以及最小区域;
2)很明显字符的垂直分割线应该位于字符与字符的中间黑色区域,这些地方的行累加值要比字符上的行累加值要小,所以我们从底到上扫描,递归地找到一些可能的切割区域,递归满足以下条件:
a 每个字符的切割宽度要大于最小宽度,小于最大宽度;
b 当切割区域大于最大宽度时,证明该区域可能含有多个字符,要对该区域继续切割,直至满足条件a。
c 当切割区域小于最小宽度时,证明该区域不存在任何字符,切割无效,要去除该切割点。
3)获取到的切割区域可能会大于7个区域,所以我们从大于最小区域的切割区域中选择最大的7个输出。

代码

[cut_m,cut_n] = size(cut_bwImg);
cut_sumCol = sum(cut_bwImg,1);
cut_sumRow = sum(cut_bwImg,2);

%左右切割
minDigitWidth = 5;
maxDigitWidth = 25;
minColArea = 250;
col_intevl = 1;
offset = 1;
col_seg = findValleys(cut_sumCol, col_intevl, offset,minDigitWidth, maxDigitWidth);
col_seg= clean(col_seg,minDigitWidth);
result_seg_col = chooseBestSeg(col_seg,cut_sumCol,minColArea,7);

seg = result_seg_col;

4 上下切割,下图是去除边框后Y轴(图像列累加)以及最后的切割点(红色圆圈标识):
这里写图片描述
同上,这里我们只需要一个合适的输出即可。

代码

 % 上下切割
minDigitHeight = 20;
maxDigitHeight = 50;
minRowArea = 150;
row_intevl = 1;
offset = 1;
row_seg = findValleys(cut_sumRow', row_intevl, offset,minDigitHeight, maxDigitHeight);
row_seg= clean(row_seg,minDigitHeight);
result_seg_row = chooseBestSeg(row_seg,cut_sumRow',minColArea,1);

new_bwImg = cut_bwImg(result_seg_row(1,1):result_seg_row(1,2),:);

5 最后切割
切割线示意图
这里写图片描述
切割出的字符
这里写图片描述

其他代码如下:
寻找合适切割点

function seg = findValleys(tem, val, offset,minDigitWidth, maxDigitWidth)
   val = val+1;

   seg = find(tem < val);


   if(length(seg) < 2)
       seg = findValleys(tem, val, offset,minDigitWidth, maxDigitWidth);
       return;
   end;


   if length(seg) == 0
       return;
   end;

   if((tem(1,1) >= val) && seg(1) ~= 1)
       seg = [1 seg];
   end;
   if((tem(1, length(tem)) >= val) && seg(length(seg)) ~= length(tem))
       seg = [seg length(tem)];
   end;

   seg = seg + (offset - 1);

   seg = clean(seg, minDigitWidth);

   seg_gap=diff(seg);

   for j=1:length(seg_gap)
       if seg_gap(1,j)>maxDigitWidth
           new_tem = tem(1,seg(j)- offset + 1 :seg(j+1)- offset + 1 );
           new_valleys = findValleys(new_tem,val,seg(j),minDigitWidth,maxDigitWidth);
           seg = [seg(1:j) new_valleys seg(j+1:length(seg))];
       end
   end
end

去除较差的切割点

function t = clean(s, val)
   t = [];
   len = length(s);
   i = 2;
   j = 1;
   while i <= len
       while(s(i) - s(i-1) <= val)
           i = i + 1;
           if(i > len)
               return;
           end;
       end;
       if j == 1 || (s(i-1) - t(j-1)) > val
           t(j) = s(i-1);
           j = j + 1;
       end;
       t(j) = s(i);
       j = j + 1;
       i = i + 1;
   end;
end

最后展示

figure(55),
subplot(331),imshow(Img);title('灰度图片');hold on;
subplot(332),imshow(bwImg);title('二值化');hold on;
subplot(334),plot(1:n,sumCol);title('X轴及其边框位置');hold on;
plot([cutColLeft cutColRight],sumCol([cutColLeft cutColRight]),'b+');hold on;
subplot(335),plot(1:m,sumRow);title('Y轴及其边框位置');hold on;
plot([cutRowTop cutRowBottom],sumRow([cutRowTop cutRowBottom]),'r+');hold on;
subplot(336),imshow(cut_bwImg);title('去除边框');hold on;
subplot(337),plot(1:cut_n,cut_sumCol);title('去除边框后X轴以及切割点');hold on;
plot(result_seg_col,cut_sumCol(result_seg_col),'go');hold on;
subplot(338),plot(1:cut_m,cut_sumRow);title('去除边框后Y轴以及切割点');hold on;
plot(result_seg_row,cut_sumRow(result_seg_row),'ro');hold on;
subplot(339),imshow(cut_bwImg);title('切割线');hold on;
plot([1:cut_n],result_seg_row(1,1),'r.',[1:cut_n],result_seg_row(1,2),'r.');hold on;
for i=1:size(result_seg_col,1)
    plot(result_seg_col(i,1),[1:cut_m],'b.');hold on;
    plot(result_seg_col(i,2),[1:cut_m],'b.');hold on;
end
cut_Img_new = [];
for i=1:size(result_seg_col,1)
    cut_Img_new = [cut_Img_new cut_bwImg(result_seg_row(1,1):result_seg_row(1,2),result_seg_col(i,1):result_seg_col(i,2)) ones(result_seg_row(1,2)-result_seg_row(1,1)+1,1)];
 end
subplot(333),imshow(cut_Img_new);title('切割出的字符');hold on;

猜你喜欢

转载自blog.csdn.net/shanglianlm/article/details/78045170