[记录帖]Matlab车牌识别系统

2023年9月2日 由于课题是机器视觉方向 一直在学习图像处理的知识 对这方面的小项目也很感兴趣 但是一直没有上手做过项目 暑假在家无聊 看见有博主发有关车牌识别的小项目 就想着自己上手跟着操作一下。  由于课题繁忙,项目并没有完成的很好,还有很少地方需要优化,现简单记录一下。接下来有时间的话会完善没实现的一部分功能和使用外接摄像头获取图片。

如图1.1所示,由于拍摄车牌的时候不可能很完美的把文字部分拍好,所以需要我们对图像进行操作,做图像切割。

1.图像获取

图1.1 车牌示意图

本文使用Word做一张带有框线的车牌,使用QQ截图工具截下来,如图1.2所示。注意这与真实的车牌相比还有较大的差距,首先在拍摄车牌时,如果遇到拍摄存在倾斜的问题,可能需要做图像校正,变回水平,便于处理。其次将真实车牌切割下来也不是这么简单的,需要很多其他的处理。本文没有完成这一步,但是接下来的操作应该可以为大家提供思路。

图1.2 Word制作的车牌示意图

如图1.2所示,边缘框线是黑色的,说明二值化该图片后黑色部分数值为0,白色部分数值为1。首先通过矩阵行相加找到最小值,存进一个数组。该数组里面数字的个数为偶数个,因为上下的宽度对称。通过寻找数组中的最小值索引,中间两个数字即为上框线的最后一行和下框线的第一行。同理,找出左右边的极限位置,通过矩阵切割的方法将有用的部分留出来。

grayimage = rgb2gray(image);
grayimage2  = imbinarize(grayimage);
T = sum(grayimage2,2);%求每一行之和
[row,~]=find(T==min(T));%找到上下框线的边缘位置 row的中间两个数
upline = row(0.5*length(row));
downline =  row(0.5*length(row)+1);
T1 = sum(grayimage2,1);
[row1,col1]=find(T1==min(T1));%找到上下框线的边缘位置 row的中间两个数
leftline = col1(0.5*length(row1));
rightline =  col1(0.5*length(row1)+1);
imageRecon = grayimage2(upline+1:downline-1,leftline+1:rightline-1);
imageIvert=imcomplement(imageRecon);%二值图反向 便于后续找点
imshow(imageIvert);

将框线去除之后,保留的字符部分如图1.3所示。

图1.3 切割后的车牌

接下来就是将图片中的包括汉字在内的8个字符切割下来,并将这8个矩阵分别存在data结构体中。切割的方法和切割框线类似,可以看到,不管是汉字还是数字、字母,他们之间在竖直方向都是没有间隙的,也就是说,可以通过求矩阵的列之和,列之和不为0的地方一定是有文字的地方。通过列之和从0到非0和从非0到0,就可以实现文字的分割。

%切割需要识别的车牌 出来单个的字符 利用sum来找列之和位于等于0和不等于0的交汇点 可以分两个数组 一个记录01分界点 一个记录10分界点
R = sum(imageIvert,1);
%定义一个储存数组store 存储分界点
store1 = zeros(1,8);
store2 = zeros(1,8);
j=1;
k=1;
for i = 1:size(R,2)-1%列数
    if R(1,i)==0 && R(1,i+1)~=0
       store1(j) = i;
       j=j+1;
    end
    if R(1,i)~=0 && R(1,i+1)==0
       store2(k) = i;
       k=k+1;
    end
end
%找出了边界点之后 开始分割裁剪 使用方法(上:下,左:右)
l = size(imageIvert,1);
data1 = cell(8,1);
for i = 1:8
scaleFactor = 229/l;
data1{i} =     imresize(  imageIvert(1:l,store1(i):store2(i)),scaleFactor);
end

切割出来的字符如图1.4所示。但是要注意,图中显示的字符在列数不同是正常的,因为字的宽度肯定不,但是在行数上,他们都是一样的,因为在做切割操作的时候,没有在横向切割。通过matlab的工作区中data1的数组维数可以看出。

图1.4 切割之后的字符

图1.5 data1数组维数

通过以上步骤,将一张车牌照片中的文字分割了出来8个字符,接下来就是第二步,形成对比库。

2。形成字符库

将切割下来的字符图片与库中的字符图片逐个对比,找出差异最小的一对,认定这张图片的文件名就是该图片的内容。所以第一步就是形成字符库,如图2.1所示。

图2.1 字符库

形成字符库的方法和上面说过的方法一致,通过0和非0位置找出分界点,进行图像分割。在word中通过形成上述图片的方法打出0-9 A-Z 以及车牌开头的字如图2.2所示,截图,切割。将切割好的字符imwirte保存。

图2.2 切割样本

clc;
clear all;
%%
%获取图像
image = imread("i.png");
%%
%图像裁剪 获取中间部分
grayimage = rgb2gray(image);
grayimage2  = imbinarize(grayimage);
T = sum(grayimage2,2);%求每一行之和
[row,~]=find(T==min(T));%找到上下框线的边缘位置 row的中间两个数
upline = row(0.5*length(row));
downline =  row(0.5*length(row)+1);
T1 = sum(grayimage2,1);
[row1,col1]=find(T1==min(T1));%找到上下框线的边缘位置 row的中间两个数
leftline = col1(0.5*length(row1));
rightline =  col1(0.5*length(row1)+1);
imageRecon = grayimage2(upline+1:downline-1,leftline+1:rightline-1);
imageIvert=imcomplement(imageRecon);%二值图反向 便于后续找点
imshow(imageIvert);

%%
%切割出来单个的字符 利用sum来找列之和位于等于0和不等于0的交汇点 可以分两个数组 一个记录01分界 一个记录10分界
R = sum(imageIvert,1);
%定义一个储存数组store 存储分界点
store1 = zeros(1,5);%注意这里 5代表有5个字符在这张图片中
store2 = zeros(1,5);
j=1;
k=1;
for i = 1:size(R,2)-1%列数
    if R(1,i)==0 && R(1,i+1)~=0
       store1(j) = i;
       j=j+1;
    end
    if R(1,i)~=0 && R(1,i+1)==0
       store2(k) = i;
       k=k+1;
    end
end

%找出了边界点之后 开始分割裁剪 使用方法(上:下,左:右)
l = size(imageIvert,1);
Char1 =imageIvert(1:l,store1(1):store2(1));
imshow(Char1);
imwrite(Char1,"57.jpg");
Char2 =imageIvert(1:l,store1(2):store2(2));
imwrite(Char2,"58.jpg");
Char3 =imageIvert(1:l,store1(3):store2(3));
imwrite(Char3,"59.jpg");
Char4 =imageIvert(1:l,store1(4):store2(4));
imwrite(Char4,"60.jpg");
Char5 =imageIvert(1:l,store1(5):store2(5));
imwrite(Char5,"61.jpg");

3.字符对比

创建一个结构体,将字符库中的字符从0开始命名为.png格式,再将数据读入结构体中。将读入的车牌中分割出来的图片数据归一化后,逐个与库中的图片数据对比,找出最小差异值,将该库中图片的文件名显示出来。

第一步 读入字符库

%%
%接下来就是对比阶段 先裁剪可能会出现的所有字符 形成库 关键点就是归一化 使用imresize调整车牌裁剪后的图片与库里面的图片尺寸一致
%先读入图片
% 创建一个空的结构体
imageStruct = struct("name", {}, "data", {});
% 文件夹路径和图片格式
folderPath = "D:\leishizhou\硕士资料\Matlab学习\车牌识别系统";
imageFormat = ".jpg";
% 获取文件夹中的所有文件名
fileNames = dir(fullfile(folderPath, strcat("*", imageFormat)));
fileNames = {fileNames.name};
% 提取文件名中的数字
nameDigits = cellfun(@(x) str2double(x(1:end-4)), fileNames);
% 按命名数字从大到小的顺序排序文件名
[~, sortedIndices] = sort(nameDigits, "ascend");
sortedFileNames = fileNames(sortedIndices);
% 遍历排序后的文件名,并读取图片数据
for i = 1:numel(sortedFileNames)
    % 构造图片文件路径
    imagePath = fullfile(folderPath, sortedFileNames{i});
    % 读取图片数据
    imageData = imread(imagePath);
    % 将图片数据存储到结构体中
    imageStruct(i).name = sortedFileNames{i};
    l = size( imageData,1);
    scaleFactor = 229/l;
    imageStruct(i).data =  imresize(imageData, scaleFactor);
end

第二步 归一化找最小差异值

 将车牌切割下来的字符和库中的字符变为300*300的矩阵 通过两张图对应位置相减的结果求和,出现最小值的一组对比就是最相似的图片。

%下面为图片归一化过程 转化为300*300 不是通过尺度变化 而是使用从右边和上面补0实现的
for i = 1:8
    img1 = data1{i};
    ind = zeros(i,1);
    for j = 1:59
        a=zeros(8,59);
        img2 = imbinarize(imageStruct(j).data);
        length1 = size(img1,1);
        width1 = size(img1,2);
        img1=horzcat(img1,zeros(length1,300-width1));
        img1 = vertcat(img1,zeros(300-length1,300));
        length2 = size(img2,1);
        width2 = size(img2,2);  
        img2=horzcat(img2,zeros(length2,300-width2));
        img2 = vertcat(img2,zeros(300-length2,300));%归一化为300大小的图片
       %接下来就是对比 找出差异值最小的索引
        compare(i,j)=sum(sum(abs(img1-img2)));
    end
end

第三步 找出索引值 显示车牌

ind2=zeros(1,8);
for m  = 1:8
    for n = 1:59
           ind2(m) = find(compare(m,:)==min(compare(m,:)));
    end
end
%%
%上面内容已经实现通过ind2找出值 接下来通过操作ind2 显示车牌
zifuku =["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","赣","陕","甘","宁","青","新","黑","吉","辽","沪","苏","京","津","冀","晋","蒙","渝","贵","鄂","湘","粤","桂","琼"];

for k = 1:8
    string(k)=zifuku(ind2(k));
    
end
string=strcat(string(1),string(2),string(3),string(4),string(5),string(6),string(7),string(8));
disp(string);

结果如图3.1所示

图3.1 车牌识别结果

4.做成界面

图4.1 MatlabAppdesigner做的界面

AppDesigner教程参考B站小刘老师

我想当你的验证码的个人空间_哔哩哔哩_bilibili

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值