本文章已收录于:
分类:
作者同类文章
X
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % 字符分割模块算法
- % 定位剪切后的彩色车牌图像--灰度--二值化--统一到黑底白字--去除上下边框
- % --切割出最小范围--滤波--形态学处理--分割出7个字符
- % 去除上下边框算法:
- % 1.黑白跳变小于阈值则被视为背景;2.连续白线大于某阈值则该白线被认为是背景
- % 3.单行白色大于阈值则被认为是背景,考虑FLAG的值;
- % 4.做完以上处理后,上边1/2 中搜索连续两条黑线,认为该黑线以上为背景;在下边1/2 中搜索连续两条黑线,认为该黑线以下为背景
- % 归一化为 40*20 ,商用系统程序中归一化为 32*16 ,此处仅演示作用
- function [d]=lpcseg(jpg)
- I=imread('car1.jpg');
- I1=rgb2gray(I);
- I2=edge(I1,'robert',0.15,'both');
- se=[1;1;1];
- I3=imerode(I2,se);
- se=strel('rectangle',[25,25]);
- I4=imclose(I3,se);
- I5=bwareaopen(I4,2000);
- [y,x,z]=size(I5);
- myI=double(I5);
- tic
- white_y=zeros(y,1);
- for i=1:y
- for j=1:x
- if(myI(i,j,1)==1)
- white_y(i,1)= white_y(i,1)+1;
- end
- end
- end
- [temp MaxY]=max(white_y);
- PY1=MaxY;
- while ((white_y(PY1,1)>=5)&&(PY1>1))
- PY1=PY1-1;
- end
- PY2=MaxY;
- while ((white_y(PY2,1)>=5)&&(PY2<y))
- PY2=PY2+1;
- end
- IY=I(PY1:PY2,:,:);
- white_x=zeros(1,x);
- for j=1:x
- for i=PY1:PY2
- if(myI(i,j,1)==1)
- white_x(1,j)= white_x(1,j)+1;
- end
- end
- end
- PX1=1;
- while ((white_x(1,PX1)<3)&&(PX1<x))
- PX1=PX1+1;
- end
- PX2=x;
- while ((white_x(1,PX2)<3)&&(PX2>PX1))
- PX2=PX2-1;
- end
- PX1=PX1-1;
- PX2=PX2+1;
- dw=I(PY1:PY2-8,PX1:PX2,:);
- t=toc;
- figure(1),subplot(3,2,1),imshow(dw),title('定位剪切后的彩色车牌图像')
- imwrite(dw,'dw.jpg');
- [filename,filepath]=uigetfile('dw.jpg','输入一个定位裁剪后的车牌图像');
- jpg=strcat(filepath,filename);
- a=imread(jpg);
- %figure(1);subplot(3,2,1),imshow(a),title('1.定位剪切后的彩色车牌图像')
- b=rgb2gray(a);
- imwrite(b,'2.车牌灰度图像.jpg');
- figure(1);subplot(3,2,2),imshow(b),title('2.车牌灰度图像')
- g_max=double(max(max(b)));
- g_min=double(min(min(b)));
- T=round(g_max-(g_max-g_min)/3); % T 为二值化的阈值
- [m,n]=size(b);
- d=(double(b)>=T); % d:二值图像
- imwrite(d,'3.车牌二值图像.jpg');
- figure(1);subplot(3,2,3),imshow(d),title('3.车牌二值图像')
- % 旋转
- rotate=0;
- d=imread('3.车牌二值图像.jpg');
- bw=edge(d);
- [m,n]=size(d);
- theta=1:179;
- % bw 表示需要变换的图像,theta 表示变换的角度
- % 返回值 r 表示的列中包含了对应于 theta中每一个角度的 Radon 变换结果
- % 向量 xp 包含相应的沿 x轴的坐标
- [r,xp]=radon(bw,theta);
- i=find(r>0);
- [foo,ind]=sort(-r(i));
- k=i(ind(1:size(i)));
- [y,x]=ind2sub(size(r),k);
- [mm,nn]=size(x);
- if mm~=0 && nn~=0
- j=1;
- while mm~=1 && j<180 && nn~=0
- i=find(r>j);
- [foo,ind]=sort(-r(i));
- k=i(ind(1:size(i)));
- [y,x]=ind2sub(size(r),k);
- [mm,nn]=size(x);
- j=j+1;
- end
- if nn~=0
- if x % Enpty matrix: 0-by-1 when x is an enpty array.
- x=x;
- else % 可能 x 为空值
- x=90; % 其实就是不旋转
- end
- d=imrotate(d,abs(90-x)); % 旋转图像
- rotate=1;
- end
- end
- imwrite(d,'4.Radon 变换旋转后的二值图像.jpg');
- figure(1),subplot(3,2,4),imshow(d),title('4.Radon 变换旋转后的二值图像')
- % 统一到白底黑字
- [m,n]=size(d);
- % flag=0 表示原来就是白底黑字,否则表示原来是黑底白字
- flag=0;
- c=d([round(m/3):m-round(m/3)],[round(n/3):n-round(n/3)]);
- if sum(sum(c))/m/n*9>0.5
- d=~d;flag=1;
- end
- % 对反色后的图像预处理,整列几乎为白的认为是背景
- if flag==1
- for j=1:n
- if sum(sum(d(:,j)))/m>=0.95
- d(:,j)=0;
- end
- end
- % 对以上处理后的图像再处理
- % 在左边 1/2 处找连续两条黑线,认为该黑线左边为背景;在右边 1/2 处找连续两条黑线,认为该黑线右边是背景
- % 左边 1/2
- jj=0;
- for j=1:round(n/2)
- if sum(sum(d(:,[j:j+0])))==0
- jj=j;
- end
- end
- d(:,[1:jj])=0;
- % 右边 1/2
- for j=n:-1:round(n/2)
- if sum(sum(d(:,[j-0:j])))==0
- jj=j;
- end
- end
- d(:,[jj:n])=0;
- end
- imwrite(d,'5.统一成黑底白字.jpg');
- figure(1),subplot(3,2,5),imshow(d),title('5.背景色统一成黑底白字')
- figure(2),subplot(5,1,1),imshow(d),title('5.黑底白字的二值车牌图像')
- % 去除上下边框
- % STEP 1 黑白跳变小于阈值则被视为背景
- % 上面 2/5
- y1=10; % y1: 跳变阈值
- for i=1:round(m/5*2)
- count=0;jump=0;temp=0;
- for j=1:n
- if d(i,j)==1
- temp=1;
- else
- temp=0;
- end
- if temp==jump
- count=count;
- else
- count=count+1;
- end
- jump=temp;
- end
- if count<y1
- d(i,:)=0;
- end
- end
- % 下面 2/5
- for i=3*round(m/5):m
- count=0;jump=0;temp=0;
- for j=1:n
- if d(i,j)==1
- temp=1;
- else
- temp=0;
- end
- if temp==jump
- count=count;
- else
- count=count+1;
- end
- jump=temp;
- end
- if count<y1
- d(i,:)=0;
- end
- end
- imwrite(d,'6.黑白跳变小于某阈值的行则被视为背景.jpg');
- figure(2),subplot(5,1,2),imshow(d),title('6.黑白跳变小于某阈值的行则被视为背景')
- % STEP 2 单行白色大于阈值则被认为是背景,考虑 FLAG 的值
- % 上面 2/5
- y2=round(n/2); % y2: 阈值
- for i=1:round(m/5*2)
- if flag==0
- temp=sum(d(i,:));y2=round(n/2);
- if temp>y2
- d(i,:)=0;
- end
- else
- temp=m-sum(d(i,:));y2=m-round(n/2);
- if temp<y2
- d(i,:)=0;
- end
- end
- end
- % 下面 2/5
- for i=round(3*m/5):m
- if flag==0
- temp=sum(d(i,:));y2=round(n/2);
- if temp>y2
- d(i,:)=0;
- end
- else
- temp=m-sum(d(i,:));y2=m-round(n/2);
- if temp<y2
- d(i,:)=0;
- end
- end
- end
- imwrite(d,'7.单行白色点总数大于某阈值则该行被认为是背景.jpg');
- figure(2),subplot(5,1,3),imshow(d),title('7.单行白色点总数大于某阈值则该行被认为是背景')
- % STEP 3 单行白色大于阈值则被认为是背景,考虑 FLAG 的值
- % 上面 2/5
- y2=round(n/2); % y2: 阈值
- for i=1:round(m/5*2)
- if flag==0
- temp=sum(d(i,:));y2=round(n/2);
- if temp>y2
- d(i,:)=0;
- end
- else
- temp=m-sum(d(i,:));y2=m-round(n/2);
- if temp<y2
- d(i,:)=0;
- end
- end
- end
- % 下面 2/5
- for i=round(3*m/5):m
- if flag==0
- temp=sum(d(i,:));y2=round(n/2);
- if temp>y2
- d(i,:)=0;
- end
- else
- temp=m-sum(d(i,:));y2=m-round(n/2);
- if temp<y2
- d(i,:)=0;
- end
- end
- end
- imwrite(d,'8.单行白色点总数大于某阈值则该行被认为是背景.jpg');
- figure(2),subplot(5,1,4),imshow(d),title('8.单行白色点总数大于某阈值则该行被认为是背景')
- % STEP 4 做完以上处理后,上边 1/2 中搜索连续两条黑线,认为该黑线以上为背景;
- % 在下边 1/2 中搜索连续两条黑线,认为该黑线以下为背景
- % 上边 1/2
- for i=1:round(m/2)
- if sum(sum(d([i,i+0],:)))==0
- ii=i;
- end
- end
- d([1:ii],:)=0;
- % 下边 1/2
- for i=m:-1:round(m/2)
- if sum(sum(d([i-0:i],:)))==0
- ii=i;
- end
- end
- d([ii:m],:)=0;
- imwrite(d,'9.搜索上下两条黑线后的结果.jpg');
- figure(2),subplot(5,1,5),imshow(d),title('9.搜索上下两条黑线后的结果')
- % 反旋转
- if rotate==1
- d=imrotate(d,-abs(x-90));
- end
- imwrite(d,'10.反旋转去毛刺后.jpg');
- figure(3),subplot(3,2,1),imshow(d),title('10.反旋转去毛刺后')
- % 切割处最小范围
- d=qiege(d);e=d;
- imwrite(d,'11.切割处最小范围.jpg');
- figure(3),subplot(3,2,2),imshow(d),title('11.切割处最小范围')
- figure(3),subplot(3,2,3),imshow(d),title('11.均值滤波前')
- % 滤波
- h=fspecial('average',3);
- d=im2bw(round(filter2(h,d)));
- imwrite(d,'12.均值滤波后.jpg');
- figure(3),subplot(3,2,4),imshow(d),title('12.均值滤波后')
- % 某些图像进行操作
- % 膨胀或腐蚀
- % se=strel('square',3); % 使用一个3X3的正方形结果元素对象对创建的图像进行膨胀
- % 'line'/'diamond'/'ball'...
- se=eye(2); % eye(n) returns the n-by-n identity matrix 单位矩阵
- [m,n]=size(d);
- if bwarea(d)/m/n>=0.365
- d=imerode(d,se);
- elseif bwarea(d)/m/n<=0.235
- d=imdilate(d,se);
- end
- imwrite(d,'13.膨胀或腐蚀处理后.jpg');
- figure(3),subplot(3,2,5),imshow(d),title('13.膨胀或腐蚀处理后')
- % 寻找连续有文字的块,若长度大于某阈值,则认为该块有两个字符组成,需要分割
- d=qiege(d);
- [m,n]=size(d);
- figure,subplot(2,1,1),imshow(d),title(n)
- k1=1;k2=1;s=sum(d);j=1;
- while j~=n
- while s(j)==0
- j=j+1;
- end
- k1=j;
- while s(j)~=0 && j<=n-1
- j=j+1;
- end
- k2=j-1;
- if k2-k1>=round(n/6.5)
- [val,num]=min(sum(d(:,[k1+5:k2-5])));
- d(:,k1+num+5)=0; % 分割
- end
- end
- % 再切割
- d=qiege(d);
- % 切割出 7 个字符
- y1=10;y2=0.25;flag=0;word1=[];
- while flag==0
- [m,n]=size(d);
- left=1;wide=0;
- while sum(d(:,wide+1))~=0
- wide=wide+1;
- end
- if wide<y1 % 认为是左侧干扰
- d(:,[1:wide])=0;
- d=qiege(d);
- else
- temp=qiege(imcrop(d,[1 1 wide m]));
- [m,n]=size(temp);
- all=sum(sum(temp));
- two_thirds=sum(sum(temp([round(m/3):2*round(m/3)],:)));
- if two_thirds/all>y2
- flag=1;word1=temp; % WORD 1
- end
- d(:,[1:wide])=0;d=qiege(d);
- end
- end
- % 分割出第二个字符
- [word2,d]=getword(d);
- % 分割出第三个字符
- [word3,d]=getword(d);
- % 分割出第四个字符
- [word4,d]=getword(d);
- % 分割出第五个字符
- [word5,d]=getword(d);
- % 分割出第六个字符
- [word6,d]=getword(d);
- % 分割出第七个字符
- [word7,d]=getword(d);
- subplot(5,7,1),imshow(word1),title('1');
- subplot(5,7,2),imshow(word2),title('2');
- subplot(5,7,3),imshow(word3),title('3');
- subplot(5,7,4),imshow(word4),title('4');
- subplot(5,7,5),imshow(word5),title('5');
- subplot(5,7,6),imshow(word6),title('6');
- subplot(5,7,7),imshow(word7),title('7');
- [m,n]=size(word1);
- % 商用系统程序中归一化大小为 32*16,此处演示
- word1=imresize(word1,[40 20]);
- word2=wordprocess(word2);
- word3=wordprocess(word3);
- word4=wordprocess(word4);
- word5=wordprocess(word5);
- word6=wordprocess(word6);
- word7=wordprocess(word7);
- subplot(5,7,15),imshow(word1),title('1');
- subplot(5,7,16),imshow(word2),title('2');
- subplot(5,7,17),imshow(word3),title('3');
- subplot(5,7,18),imshow(word4),title('4');
- subplot(5,7,19),imshow(word5),title('5');
- subplot(5,7,20),imshow(word6),title('6');
- subplot(5,7,21),imshow(word7),title('7');
- imwrite(word1,'14.字符分割归一化后 1.jpg');
- imwrite(word2,'14.字符分割归一化后 2.jpg');
- imwrite(word3,'14.字符分割归一化后 3.jpg');
- imwrite(word4,'14.字符分割归一化后 4.jpg');
- imwrite(word5,'14.字符分割归一化后 5.jpg');
- imwrite(word6,'14.字符分割归一化后 6.jpg');
- imwrite(word7,'14.字符分割归一化后 7.jpg');
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- clc
- word='';
- word(1)=wordrec(word1);
- word(2)=wordrec(word2);
- word(3)=wordrec(word3);
- word(4)=wordrec(word4);
- word(5)=wordrec(word5);
- word(6)=wordrec(word6);
- word(7)=wordrec(word7);
- clc
- save I 'word1' 'word2' 'word3' 'word4' 'word5' 'word6' 'word7'
- clear
- load I;
- load bp net;
- word='';
- word(1)=wordrec(word1);
- word(2)=wordrec(word2);
- word(3)=wordrec(word3);
- word(4)=wordrec(word4);
- word(5)=wordrec(word5);
- word(6)=wordrec(word6);
- word(7)=wordrec(word7);
- word=strcat('识别结果:',word);
- subplot(5,3,14),imshow([]),title(word,'fontsize',24)
- % 该子程序用于切割出最小范围
- function e=qiege(d)
- [m,n]=size(d);
- top=1;bottom=m;left=1;right=n; % init
- while sum(d(top,:))==0 && top<=m
- top=top+1;
- end
- while sum(d(bottom,:))==0 && bottom>=1
- bottom=bottom-1;
- end
- while sum(d(:,left))==0 && left<=n
- left=left+1;
- end
- while sum(d(:,right))==0 && right>=1
- right=right-1;
- end
- dd=right-left;
- hh=bottom-top;
- e=imcrop(d,[left top dd hh]);
- % 分割字符
- function [word,result]=getword(d)
- word=[];flag=0;y1=8;y2=0.5;
- % if d==[]
- % word=[];
- % else
- while flag==0
- [m,n]=size(d);
- wide=0;
- while sum(d(:,wide+1))~=0 && wide<=n-2
- wide=wide+1;
- end
- temp=qiege(imcrop(d,[1 1 wide m]));
- [m1,n1]=size(temp);
- if wide<y1 && n1/m1>y2
- d(:,[1:wide])=0;
- if sum(sum(d))~=0
- d=qiege(d); % 切割出最小范围
- else word=[];flag=1;
- end
- else
- word=qiege(imcrop(d,[1 1 wide m]));
- d(:,[1:wide])=0;
- if sum(sum(d))~=0;
- d=qiege(d);flag=1;
- else d=[];
- end
- end
- end
- %end
- result=d;
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % 该子程序用于字符归一化处理
- function d=wordprocess(d)
- [m,n]=size(d);
- %top 1/3, bottom 1/3
- for i=1:round(m/3)
- if sum(sum(d([i:i+0],:)))==0
- ii=i;d([1:ii],:)=0;
- end
- end
- for i=m:-1:2*round(m/3)
- if sum(sum(d([i-0:i],:)))==0
- ii=i;d([ii:m],:)=0;
- end
- end
- if n~=1
- d=qiege(d);
- end
- % d=..这个可以通过训练过程设置大小
- % d=imresize(d,[32 16]); % 商用系统程序中归一划大小为:32*16
- d=imresize(d,[40 20]);
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % 编号:A-Z 分别为 1-26; 0-9 分别为 27-36;
- % 京 津 沪 渝 港 澳 吉 辽 鲁 豫 冀 鄂 湘 晋 青 皖 苏
- % 赣 浙 闽 粤 琼 台 陕 甘 云 川 贵 黑 藏 蒙 桂 新 宁
- % 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
- % 60 61 62 63 64 65 66 67 68 69 70
- % 使用 BP 网络
- function word=wordrec(xx)
- % clear
- % clc
- load bp net;
- xx=im2bw(xx);xx=double(xx(:)); % 使用阈值将图像转换为二进制图像
- a=sim(net,xx); % 归一划为: 32*16,则 xx=512*1;
- [val,num]=max(a);
- if num<=26
- word=char(double('A')+num-1);
- elseif num<=36
- word=char(double('0')+num-1-26);
- else
- switch num
- case 37
- word='京';
- case 38
- word='津';
- case 39
- word='沪';
- case 40
- word='渝';
- case 41
- word='港';
- case 42
- word='澳';
- case 43
- word='吉';
- case 44
- word='辽';
- case 45
- word='鲁';
- case 46
- word='豫';
- case 47
- word='冀';
- case 48
- word='鄂';
- case 49
- word='湘';
- case 50
- word='晋';
- case 51
- word='青';
- case 52
- word='皖';
- case 53
- word='苏';
- case 54
- word='赣';
- case 55
- word='浙';
- case 56
- word='闽';
- case 57
- word='粤';
- case 58
- word='琼';
- case 59
- word='台';
- case 60
- word='陕';
- case 61
- word='甘';
- case 62
- word='云';
- case 63
- word='川';
- case 64
- word='贵';
- case 65
- word='黑';
- case 66
- word='藏';
- case 67
- word='蒙';
- case 68
- word='桂';
- case 69
- word='新';
- case 70
- word='宁';
- end
- end