%程序功能:实现车牌自动定位
%作者:郭雄伟
clear;clc;close all
filename='36.jpg'; %输入使用的图片名
figure
imshow(filename);title('原图')
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
I=im2gray(filename); %调用自编函数读取图像,并转化为灰度图象;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
figure
imshow(I);title('灰度图')
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
I=medfilt2(I); %中值滤波
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
figure
imshow(I);title('中值滤波后的灰度图')
tic %计时开始
[height,width]=size(I); %读取图片大小信息
I_edge=zeros(height,width); % 创建height*width的矩阵
for i=1:width-1 % 对每一列开始遍历
I_edge(:,i)=abs(I(:,i+1)-I(:,i)); % 每列的值赋为原图像中左右两列相减的绝对值(即梯度)
end
I_edge=(255/(max(max(I_edge))-min(min(I_edge))))*(I_edge-min(min(I_edge)));% 归一化处理(0~255)
[I_edge,y1]=select(I_edge,height,width); %调用select函数,进行边缘提取
figure
imshow(I_edge);title('选择')
BW2 = I_edge;%BW2为0和255二值图像
%%%%%%%%%%%%%%%%%%%%%%%%%%%一些形态学处理
SE=strel('rectangle',[10,10]);
IM2=imerode(BW2,SE);%腐蚀
figure
imshow(IM2);title('腐蚀');
IM2=bwareaopen(IM2,20);%开运算,消除细小物体
figure
imshow(IM2);title('开运算');
IM3=imdilate(IM2,SE);%膨胀
figure
imshow(IM2);title('膨胀');
%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%投影估计车牌位置
p_h=projection(double(IM3),'h'); %调用projection函数,水平投影
if(p_h(1)>0)
p_h=[0,p_h];
end
p_v=projection(double(IM3),'v'); %调用projection函数,垂直投影
if(p_v(1)>0)
p_v=[0,p_v];
end
p_h=double((p_h>5));
p_h=find(((p_h(1:end-1)-p_h(2:end))~=0));
len_h=length(p_h)/2;
p_v=double((p_v>5));
p_v=find(((p_v(1:end-1)-p_v(2:end))~=0));
len_v=length(p_v)/2;
%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%粗略计算车牌候选区
k=1;
for i=1:len_h
for j=1:len_v
s=IM3(p_h(2*i-1):p_h(2*i),p_v(2*j-1):p_v(2*j));
if(mean(mean(s))>0.1) %根据投影值变化确定阈值,此值可以调节
p{k}=[p_h(2*i-1),p_h(2*i)+1,p_v(2*j-1),p_v(2*j)+1];
k=k+1;
end
end
end
k=k-1;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%进一步缩小车牌候选区
for i=1:k
edge_IM3=double(edge(double(IM3(p{i}(1):p{i}(2),p{i}(3):p{i}(4))),'canny'));
[x,y]=find(edge_IM3==1);
p{i}=[p{i}(1)+min(x),p{i}(2)-(p{i}(2)-p{i}(1)+1-max(x)),...%矩形的行起点与终点
p{i}(3)+min(y),p{i}(4)-(p{i}(4)-p{i}(3)+1-max(y))]; %矩形的列起点与终点
p_center{i}=[fix((p{i}(1)+p{i}(2))/2),fix((p{i}(3)+p{i}(4))/2)]; %矩形中心
p_ratio(i)=(p{i}(4)-p{i}(3))/(p{i}(2)-p{i}(1)); % 矩形长宽比
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%对上面参数和变量的说明:p为一元胞,用于存放每个图像块的左上和右下两个点的坐标;
%存放格式为:p{k}=[x1,x2,y1,y2];x1,x2分别为行坐标,y1,y2为列坐标
%p_center为一元胞,用于存放每个图像块的中心坐标,p_center{k}=[x,y];x,y分别为行,列坐标
%p_ratio为一矩阵,用来存放图像块的长宽比例
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%合并临近区域%%%%%%%
%如果有多个区域则执行合并
if k>1
n=0;
ncount=zeros(1,k);
for i=1:k-1
%需要调整if条件中的比例
%检查是否满足合并条件
if(abs(p{i}(1)+p{i}(2)-p{i+1}(1)-p{i+1}(2))<=height/30&&abs(p{i+1}(3)-p{i}(4))<=width/15)%设置合并的阈值
p{i+1}(1)=min(p{i}(1),p{i+1}(1));
p{i+1}(2)=max(p{i}(2),p{i+1}(2));
p{i+1}(3)=min(p{i}(3),p{i+1}(3));
p{i+1}(4)=max(p{i}(4),p{i+1}(4)); %向后合并
n=n+1;
ncount(n)=i+1;
end
end
%如果有合并,求出合并后最终区域
if(n>0)
d_ncount=ncount(2:n+1)-ncount(1:n);%避免重复记录临近的多个区域。
index=find(d_ncount~=1);
m=length(index);
for i=1:m
pp{i}=p{ncount(index(i))};
%重新记录合并区域的比例
pp_ratio(i)=(pp{i}(4)-pp{i}(3))/(pp{i}(2)-pp{i}(1)); %长宽比例
end
p=pp;%更新区域记录
p_ratio=pp_ratio; %更新区域比例记录
clear pp;clear pp_ratio; %清除部分变量
end
end
k=length(p); %更新区域个数
%%%%%%%%%%%%%%合并结束%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%根据区域比例判断是否为车牌区域%%%%%%%%%%%%
m=1;T=0.6*max(p_ratio);%此式中的0.6参数可以调节调整
for i=1:k
if(p_ratio(i)>=T&p_ratio(i)<10)%有区域长宽比值判断是否为车牌,此值需要根据实际调节
%%%%% %%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%根据区域占图片比例判断
disw=p{i}(4)-p{i}(3);
dish=p{i}(2)-p{i}(1);
if((disw>=width*0.01 & disw<=width*0.5)... %假定车牌长度大于整张图片长度的0.01,小于0.5,可以
&(dish>=height*0.01 & dish<=height*0.5)) %根据实际要求调节
%参数可修改
%车牌区域宽度各高度占整个图像的大小不能太大也不能太小
p1{m}=p{i};
m=m+1;
end
%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%
end
end
p=p1;clear p1;
k=m-1; %更新区域数
%%%%%%%%%%%判定结束%%%%%%%%%%%%%%%%%%%%%
toc %计时结束
%%%%%%%%%%%%%%%%%显示选定的车牌区域
figure;
for i=1:k
subplot(1,k,i);
index=p{i};
imshow(I(index(1)-2:index(2),index(3):index(4)));
end
if(k==1)
imwrite(I(index(1)-2:index(2),index(3):index(4)),'车牌.jpg');
end