车牌定位的算法主要分为三类:

  • 基于边缘
  • 基于颜色
  • 基于机器学习

参考链接:
常用车牌定位算法浅析https://blog.csdn.net/weixin_43958974/article/details/84886649.
图像处理基本算法 车牌识别与定位
https://blog.csdn.net/aihao_diy/article/details/72628427

基本思路是提取车牌的特征然后根据特征进行筛选。
主函数代码:

close all;
clc
[fn,pn,fi] = uigetfile('*.jpg','请选择所要识别的图片');    
I = imread([pn fn]); % 读取图像 参数为图像名称和图像路径
figure,imshow(I);                   
title('原始图像'); %显示原始图像 

%------车牌定位,并得到车牌的上边界PY1、下边界PY2、左边界PX1、右边界 PX2
[PY2,PY1,PX2,PX1] = Dingwei_Chepai(I);                     % 1.定位车牌边界

%------车牌修正,将车牌轮廓稍微扩张                             % 2.修正边界
[PY2,PY1,PX2,PX1,threshold] = Xiuzheng_Chepai(PY2,PY1,PX2,PX1);

%------框选出车牌信息,得到车牌图像
bw = I(PY1:PY2,PX1:PX2,:);                                   % 3.裁剪车牌照

figure,imshow(bw); 
title('车牌图像'); 
1.车牌定位

图像有RGB三层矩阵,每种车牌的底色具有各自特殊的RGB值,例如程序中使用的蓝底车牌的典型RGB值为 R = 28,G = 63, B = 138;
当RGB值接近时则认为可能是车牌,将该点像素赋值为255,否则0;利用颜色特征可以获取二值图像,可以去除大部分的其他物体,但是会有很多的干扰。

[PY2,PY1,PX2,PX1] = Dingwei_Chepai(I);     %定位车牌边界

代码实现

// 上下左右边界值
function [PY2,PY1,PX2,PX1] = Dingwei_Chepai(I)
[y,x,z]=size(I); % 行数/列数/RGB层数
myI=double(I);  %I数据转换成双精度型
Y_threshlow=5;  %提取彩图的质量因子
X_firrectify=5;  %干扰因子 transaction
%====================== Y 方向============================
Blue_y=zeros(y,1); % 创建y列向量,统计蓝色像素点
for i=1:y
    for j=1:x
         if((myI(i,j,1)<=48)&&((myI(i,j,2)<=100)&&(myI(i,j,2)>=40))...
                 &&((myI(i,j,3)<=200)&&(myI(i,j,3)>=80)))
             %蓝色像素的判断条件:R<=48;  40<=G<=100;  80<=B<=200
             % R:28  G:63  B:138
             Blue_y(i,1)= Blue_y(i,1)+1;           % 1. 统计每行蓝色像素点数                    
        end  
    end       
end
baisebili=0;   % 白色比例
changkuanbi=0;  %窗口比例 
k=0; % 表示进入次数
while(~((baisebili>=0.12)&&(baisebili<=0.5)&&(changkuanbi>=0.20)&&(changkuanbi<=0.6))) 
    if  (k==0)  %第一次进来
        [temp, MaxY]=max(Blue_y);
        % temp表示最多的点数,MaxY表示最多点数所在的行
        if temp<=20   
           %若蓝色像素小于这个值,不符合
           msgbox('车牌定位出错','warning'); % 对话框提示
        end
        PY1=MaxY; %将有最多蓝色像素点的行赋值给PY1  
        while ((Blue_y(PY1,1)>=Y_threshlow)&&(PY1>1))     % 2.寻找图片上边界
            PY1=PY1-1;
        end        
       
        PY2=MaxY; %将有最多蓝色像素点的行赋值给PY2
        while ((Blue_y(PY2,1)>=Y_threshlow)&&(PY2<y))     % 3.寻找图片下边界
             PY2=PY2+1;
        end
%==============X 方向===============================
        X_threshhigh=(PY2-PY1)/11;   %X方向长度
        %决定了提取的彩图的质量,适当提高可抗干扰,但是小图会照成剪裁太多
        Blue_x=zeros(1,x);          % 创建x行向量,统计蓝色像素点
        for j=1:x
            for i=PY1:PY2    % 由于已经确定Y方向范围,因此在此处只需要处理PY1:PY2阶段
               if((myI(i,j,1)<=65)&&((myI(i,j,2)<=100)&&(myI(i,j,2)>=40))...
                   &&((myI(i,j,3)<=160)&&(myI(i,j,3)>=90)))    % ??
                    %蓝色像素的判断条件:R<=65;  40<=G<=100;  90<=B<=160
                    % R:28  G:63  B:138
                   Blue_x(1,j)= Blue_x(1,j)+1;      % 1. X方向蓝色象素点统计        
                end  
            end       
        end
        [~, MaxX]=max(Blue_x); 
        % MaxX表示最多点数所在的行
        PX1=MaxX-6*(PY2-PY1);                          % 2. 寻找X方向左边界
        if  PX1<=1
            PX1=1;
        end
        while ((Blue_x(1,PX1)<=X_threshhigh)&&(PX1<x)) 
              % 阈值: X_threshhigh=(PY2-PY1)/11;
              PX1=PX1+1;
        end   %确定出X方向车牌起点   
        PX2=MaxX+6*(PY2-PY1);                          % 3. 寻找X方向右边界
        if  PX2>=x
            PX2=x;
        end
        while ((Blue_x(1,PX2)<=X_threshhigh)&&(PX2>PX1)) %阈值
               PX2=PX2-1;
        end  %确定出X方向车牌终点
       
%=========================================================       
        a=PY2-PY1+1; % 宽度
        b=PX2-PX1+1; % 长度
        White=0; %存储白色区域色素点
        for i=PY1:PY2
            for j=PX1:PX2
                if   (std([myI(i,j,1) myI(i,j,2) myI(i,j,3)],1,2)<=22)...
                        &&(myI(i,j,1)>=90)&&(myI(i,j,1)<=255)             
                White= White+1;    % 白色像素点统计                    
                else
                end  
            end       
        end 
        baisebili=White/(a*b); % 白色像素区域比例
        changkuanbi=a/b;  % 宽高比
        k=k+1;
%===========================蓝色区域不是车牌区域=================
    elseif (k~=0)
        Blue_y(PY1:PY2,1)=0;
        
        [temp, MaxY]=max(Blue_y);
        if temp<=20
           msgbox('车牌定位出错','warning');   
        end
        PY1=MaxY;  %PY1:存储车牌上边界值
        while ((Blue_y(PY1,1)>=Y_threshlow)&&(PY1>1))%找到图片上边界  阈值为5
             PY1=PY1-1; 
        end   
        
        PY2=MaxY;
        while ((Blue_y(PY2,1)>=Y_threshlow)&&(PY2<y))%阈值为5
        PY2=PY2+1; %PY2:存储车牌上边界值
        end
        PY1; PY2;
%==============2次寻找X方向===============================
        X_threshhigh=(PY2-PY1)/15;
        Blue_x=zeros(1,x);             % 进一步确定X方向的车牌区域
        for j=1:x
            for i=PY1:PY2
                if((myI(i,j,1)<=45)&&((myI(i,j,2)<=90)&&(myI(i,j,2)>=20))...
                        &&((myI(i,j,3)<=160)&&(myI(i,j,3)>=80)))      
                    Blue_x(1,j)= Blue_x(1,j)+1;               
                end  
            end       
        end
          [~, MaxX]=max(Blue_x);
          PX1=MaxX-6*(PY2-PY1);
          if  PX1<=1
              PX1=1;
          end          
          while ((Blue_x(1,PX1)<=X_threshhigh)&&(PX1<x))%阈值
                PX1=PX1+1;
          end %确定出X方向车牌起点   
          PX2=MaxX+6*(PY2-PY1);
          if  PX2>=x
              PX2=x;
          end
          while ((Blue_x(1,PX2)<=X_threshhigh)&&(PX2>PX1))%阈值
                PX2=PX2-1;
          end 
%=========================================================       
        a=PY2-PY1+1;b=PX2-PX1+1;
        White=0;
        for i=PY1:PY2
            for j=PX1:PX2
                if   (std([myI(i,j,1) myI(i,j,2) myI(i,j,3)],1,2)<=16)...
                        &&(myI(i,j,1)>=90)&&(myI(i,j,1)<=255)
                    White= White+1;    % 白色象素点统计                    
                end  
            end       
        end        
        baisebili=White/(a*b);
        changkuanbi=a/b;
        k=k+1;       
    end
end
%========================================================
Y_firrectify=fix((PY2-PY1)/5); %取整 车牌区域修正系数
PY1=PY1-Y_firrectify;%对车牌区域的修正,向上
PY2=PY2+Y_firrectify;%对车牌区域的修正,向下
PX1=PX1-X_firrectify;% 对车牌区域的修正
PX2=PX2+X_firrectify;% 对车牌区域的修正,

end
2.车牌边界修正

由于上步中有对车牌区域的修正,对大部分图像足够,此步骤也可以省略。
作为进一步地边界修正,在接下来操作中可使车牌区域的可读性更大
代码如下:

// 边界修正
function [PY2,PY1,PX2,PX1,threshold] = Xiuzheng_Chepai(PY2,PY1,PX2,PX1)
 
S = (PY2-PY1)*(PX2-PX1);  %% 获得车牌面积
if       S <= 25000   
    threshold = 50;
    Y_secrectify = 3;
    X_secrectify = 3;
elseif S>25000&&S<=45000  
    threshold=100;
    Y_secrectify=-3;
    X_secrectify=3;
elseif S>45000&&S<=80000
    threshold=200;
    Y_secrectify=-3;
    X_secrectify=3;
elseif S>80000&&S<=150000
    threshold=300;
    Y_secrectify=-10;
    X_secrectify=-10;
elseif S>150000&&S<=400000
    threshold=600;
    Y_secrectify=-10;
    X_secrectify=-10;
else
    threshold=1800;
    Y_secrectify=-10;
    X_secrectify=-10;
end
PY1=PY1-Y_secrectify;%对车牌区域的进一步修正
PY2=PY2+Y_secrectify;%对车牌区域的进一步修正
PX1=PX1-X_secrectify;%对车牌区域的进一步修正
PX2=PX2+X_secrectify;%对车牌区域的进一步修正
end

在这里插入图片描述
在这里插入图片描述

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐