.
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——样条节点矩阵
Word文档
.
% 计算相邻插值点之间的弦长
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
Word文档
.
% 对每一个分量计算出来的插值曲线进行采样,以便将其画出。 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
Word文档
.
% 赋值操作
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;
Word文档
.
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);
Word文档