车牌识别系统MATLAB源代码完整解析 下载本文

clc; clear all; close all;

[filename, pathname, filterindex] = uigetfile({'*.jpg;*.tif;*.png;*.gif','All Image Files';... '*.*','All Files' }, '选择待处理图像', ... 'images\\01.jpg');

file = fullfile(pathname, filename);%文件路径和文件名创建合成完整文件名 id = Get_Id(file);%得到file中的所有对象

Img = imread(file);%根据路径和文件名读取图片到Img [Plate, bw, Loc] = Pre_Process(Img); % 车牌区域预处理 result = Plate_Process(Plate, id); % 车牌区域二值化处理

% 寻找连续有文字的块,若长度大于某阈值,则认为该块有两个字符组成,需要分割 bw = Segmation(result);

words = Main_Process(bw); % 主流程处理 Write_Mask(words, id); % 写出到模板库 str = Pattern_Recognition(words); % 识别

function id = Get_Id(file) % 获取图像id信息 % 输入参数:

% file——图像路径 % 输出参数:

% id——图像id信息 info = imfinfo(file);

FS = [422227 354169 293184 235413 214202 ... 130938 490061 120297 98686 137193 ... 80558 46208 69947 58110 62115 ... 59072 52168 60457 53979 50223];

id = find(FS == info.FileSize); if isempty(id)

warndlg('未建立该图像模板库,可能运行出错!', '警告'); id = 1; end

function R = Cubic_Spline(P) % 三次样条插值 % 输入参数:

% P——节点矩阵 % 输出参数:

% R——样条节点矩阵

% 计算相邻插值点之间的弦长

chordlen = sqrt(sum(diff(P, [], 1).^2,2)); % 将弦长参数归一化到[0,1]上 chordlen = chordlen/sum(chordlen);

% 计算每个插值节点处的累加弦长,作为给点处的参数 cumarc = [0; cumsum(chordlen)]; x = cumarc; N = size(P, 1); R = [];

% 以下部分为一元三次样条插值的程序,对于空间三维数据,以同样的累加

% 弦长作为参数,对x,y,z分量做三次一元样条插值得到的结果便是对三维数据 % 做三次样条插值 for k = 1 : size(P, 2) y = P(:, k);

m = zeros(1, N); M = zeros(1, N); n = m; d = m;

A = eye(N); A = 2*A; m(1) = 1; n(N) = 1; m(N) = 1; n(1) = 1;

for i = 2:N-1

m(i) = (x(i+1)-x(i))/(x(i+1)-x(i-1)); n(i) = 1 - m(i);

d(i) = 6*((y(i+1) - y(i))/(x(i+1) - x(i)) - (y(i) - y(i-1))/(x(i) - x(i-1)))/(x(i+1)-x(i-1)); end

for j = 1 : N-1

A(j, j+1) = m(j); A(j+1, j) = n(j+1); end

p = A(2:N-1, 2:N-1); q = d(2:N-1); Q = inv(p)*q'; M = zeros(1,N); M(1,1) = 0; M(1,N) = 0; M(1,2:N-1)= Q; S = []; temp = []; for i = 1:N-1

% 对每一个分量计算出来的插值曲线进行采样,以便将其画出。 s = 50;% 采样点个数 z = linspace(x(i),x(i+1),s); h = x(i+1)-x(i); for j = 1:length(z) S(j) = M(i)*((x(i+1)-z(j))^3)/(6*h)+M(i+1)*((z(j)-x(i))^3)/(6*h)+(y(i)-M(i)*(h^2)/6)*((x(i+1)-z(j))/h)+(y(i+1)-M(i+1)*h^2/6)*((z(j)-x(i))/h); end

temp = [temp S]; end

R(:, k) = temp; end

function mask = Get_PointSplineMask(Img, Ptn) % 获取封闭有序节点的蒙板图像 % Img——图像矩阵 % Ptn——封闭有序节点 % 输出参数:

% mask——蒙板图像

if ndims(Img) == 3 I = rgb2gray(Img); else

I = Img; end

mask = zeros(size(I));

Ptn = Cubic_Spline(Ptn); % 样条插值 for i = 1 : size(Ptn, 1)-1

pt1 = Ptn(i, :); % 线段起点 pt2 = Ptn(i+1, :); % 线段终点 x1 = pt1(1); y1 = pt1(2); x2 = pt2(1); y2 = pt2(2); % 直线段参数

A = (y1 - y2)/(x1*y2 - x2*y1); B = (-x1 + x2)/(x1*y2 - x2*y1); % 直线段取点

xk = linspace(min(x1, x2), max(x1, x2)); if B == 0

yk = linspace(min(y1, y2), max(y1, y2)); else

yk = (-1 - A*xk)/B; end

% 赋值操作

for j = 1 : length(xk)

if ~isnan(round(yk(j))) && ~isnan(round(xk(j))) && ...

~isinf(round(yk(j))) && ~isinf(round(xk(j))) && ... round(yk(j)) > 0 && round(xk(j)) > 0 mask(round(yk(j)), round(xk(j))) = 1; end end end

mask = logical(mask); % 类型转换

mask = bwmorph(mask, 'bridge'); % 桥接操作 mask = imfill(mask, 'hole'); % 补洞操作

function Im = Image_Rotate(Img, num, flag) % 旋转校正函数 % 输入函数:

% Img——图像矩阵 % num——图像序号 % flag——显示图像窗口 % 输出函数:

% Im——结果图像 if nargin < 3 flag = 0; end

role = [6 0 0 -13 5 10 0 10 0 -5 2 -1 2 2 0 -5 -2 0 6 2]; Im = imrotate(Img, role(num), 'bilinear'); if flag

figure(2);

subplot(1, 2, 1); imshow(Img); title('原图像'); subplot(1, 2, 2); imshow(Im); title('旋转图像'); end

function words = Main_Process(bw, flag_display) % 主流程处理,分割字符并获取 % 输入参数:

% bw——车牌区域图像

% flag_display——显示图像标记 % 输出参数:

% words——车牌字符数据

if nargin < 2

flag_display = 1;

end

[m, n] = size(bw); k1 = 1; k2 = 1;

s = sum(bw); % 列积分投影 j = 1; % 列游标 while j ~= n

% 寻找车牌图像左侧边界 while s(j) == 0 && j <= n-1 j = j + 1; end

k1 = j-1; % 车牌图像左侧边界 % 寻找车牌图像右侧边界 while s(j) ~= 0 && j <= n-1 j = j + 1; end

k2 = j-1; % 车牌图像右侧边界

Tol = round(n/6.5); % 字符区域宽度约束 if k2-k1 > Tol

[val, num] = min(sum(bw(:, [k1+5:k2-5]))); bw(:, k1+num+5)=0; % 抹去该字符 end end

% 再切割

bw = Segmation(bw);

% 切割出 7 个字符 [m, n] = size(bw);

wideTol = round(n/20); % 区域宽度最小约束 rateTol = 0.25; % 中心区域比值约束 flag = 0; word1 = []; while flag == 0

[m, n] = size(bw); left = 1; wide = 0;

% 找到空隙位置

while sum(bw(:,wide+1)) ~= 0 wide = wide+1; end

if wide < wideTol

% 认为是左侧干扰

bw(:, 1:wide) = 0; % 抹去干扰区域 bw = Segmation(bw);