车牌识别系统MATLAB源代码完整解析.doc
精品文档,仅供学习与交流,如有侵权请联系网站删除clc; clear all; close all;filename, pathname, filterindex = uigetfile('*.jpg;*.tif;*.png;*.gif','All Image Files'. '*.*','All Files' , '选择待处理图像', . 'images01.jpg');file = fullfile(pathname, filename);%文件路径和文件名创建合成完整文件名id = Get_Id(file);%得到file中的所有对象Img = imread(file);%根据路径和文件名读取图片到ImgPlate, 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;endfunction 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)*(h2)/6)*(x(i+1)-z(j)/h)+(y(i+1)-M(i+1)*h2/6)*(z(j)-x(i)/h); end temp = temp S; end R(:, k) = temp; endfunction mask = Get_PointSplineMask(Img, Ptn)% 获取封闭有序节点的蒙板图像% Img图像矩阵% Ptn封闭有序节点% 输出参数:% mask蒙板图像if ndims(Img) = 3 I = rgb2gray(Img);else I = Img;endmask = 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 endendmask = 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;endrole = 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('旋转图像');endfunction words = Main_Process(bw, flag_display)% 主流程处理,分割字符并获取% 输入参数:% bw车牌区域图像% flag_display显示图像标记% 输出参数:% words车牌字符数据if nargin < 2 flag_display = 1;endm, 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; % 抹去该字符 endend% 再切割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); else % 提取字符区域 temp = Segmation(imcrop(bw, 1 1 wide m); m, n = size(temp); tall = sum(temp(:); % 该字符所有像素之和 % 该字符图像2/3图像区域像素和 two_thirds = sum(sum( temp(round(m/3):2*round(m/3), :) ); rate = two_thirds/tall; % 中间区域像素/全局区域像素 if rate > rateTol flag = 1; word1 = temp; %提取WORD 1 end bw(:, 1:wide) = 0; % 抹去已处理的区域 bw = Segmation(bw); endend% 分割出第二个字符word2, bw = Word_Segmation(bw);% 分割出第三个字符word3, bw = Word_Segmation(bw);% 分割出第四个字符word4, bw = Word_Segmation(bw);% 分割出第五个字符word5, bw = Word_Segmation(bw);% 分割出第六个字符word6, bw = Word_Segmation(bw);% 分割出第七个字符word7, bw = Word_Segmation(bw);wid = size(word1, 2) size(word2, 2) size(word3, 2) . size(word4, 2) size(word5, 2) size(word6, 2) size(word7, 2);maxwid, indmax = max(wid);maxwid = maxwid + 10;wordi = word1;wordi = zeros(size(wordi, 1), round(maxwid-size(word1, 2)/2) wordi zeros(size(wordi, 1), round(maxwid-size(word1, 2)/2);word1 = wordi;wordi = word2;wordi = zeros(size(wordi, 1), round(maxwid-size(word2, 2)/2) wordi zeros(size(wordi, 1), round(maxwid-size(word2, 2)/2);word2 = wordi;wordi = word3;wordi = zeros(size(wordi, 1), round(maxwid-size(word3, 2)/2) wordi zeros(size(wordi, 1), round(maxwid-size(word3, 2)/2);word3 = wordi;wordi = word4;wordi = zeros(size(wordi, 1), round(maxwid-size(word4, 2)/2) wordi zeros(size(wordi, 1), round(maxwid-size(word4, 2)/2);word4 = wordi;wordi = word5;wordi = zeros(size(wordi, 1), round(maxwid-size(word5, 2)/2) wordi zeros(size(wordi, 1), round(maxwid-size(word5, 2)/2);word5 = wordi;wordi = word6;wordi = zeros(size(wordi, 1), round(maxwid-size(word6, 2)/2) wordi zeros(size(wordi, 1), round(maxwid-size(word6, 2)/2);word6 = wordi;wordi = word7;wordi = zeros(size(wordi, 1), round(maxwid-size(word7, 2)/2) wordi zeros(size(wordi, 1), round(maxwid-size(word7, 2)/2);word7 = wordi;% figure(1);% subplot(2, 7, 1); imshow(word1); title('字符1');% subplot(2, 7, 2); imshow(word2); title('字符2');% subplot(2, 7, 3); imshow(word3); title('字符3');% subplot(2, 7, 4); imshow(word4); title('字符4');% subplot(2, 7, 5); imshow(word5); title('字符5');% subplot(2, 7, 6); imshow(word6); title('字符6');% subplot(2, 7, 7); imshow(word7); title('字符7');% 切割出的字符归一化大小为 40*20,此处演示word11 = imresize(word1, 40 20);word21 = imresize(word2, 40 20);word31 = imresize(word3, 40 20);word41 = imresize(word4, 40 20);word51 = imresize(word5, 40 20);word61 = imresize(word6, 40 20);word71 = imresize(word7, 40 20);% subplot(2, 7, 8); imshow(word11); title('字符1');% subplot(2, 7, 9); imshow(word21); title('字符2');% subplot(2, 7, 10); imshow(word31); title('字符3');% subplot(2, 7, 11); imshow(word41); title('字符4');% subplot(2, 7, 12); imshow(word51); title('字符5');% subplot(2, 7, 13); imshow(word61); title('字符6');% subplot(2, 7, 14); imshow(word71); title('字符7');% 赋值操作words.word1 = word11;words.word2 = word21;words.word3 = word31;words.word4 = word41;words.word5 = word51;words.word6 = word61;words.word7 = word71;if flag_display figure; subplot(2, 7, 1); imshow(word1); title('字符1', 'FontWeight', 'Bold'); subplot(2, 7, 2); imshow(word2); title('字符2', 'FontWeight', 'Bold'); subplot(2, 7, 3); imshow(word3); title('字符3', 'FontWeight', 'Bold'); subplot(2, 7, 4); imshow(word4); title('字符4', 'FontWeight', 'Bold'); subplot(2, 7, 5); imshow(word5); title('字符5', 'FontWeight', 'Bold'); subplot(2, 7, 6); imshow(word6); title('字符6', 'FontWeight', 'Bold'); subplot(2, 7, 7); imshow(word7); title('字符7', 'FontWeight', 'Bold'); subplot(2, 7, 8); imshow(word11); title('字符1', 'FontWeight', 'Bold'); subplot(2, 7, 9); imshow(word21); title('字符2', 'FontWeight', 'Bold'); subplot(2, 7, 10); imshow(word31); title('字符3', 'FontWeight', 'Bold'); subplot(2, 7, 11); imshow(word41); title('字符4', 'FontWeight', 'Bold'); subplot(2, 7, 12); imshow(word51); title('字符5', 'FontWeight', 'Bold'); subplot(2, 7, 13); imshow(word61); title('字符6', 'FontWeight', 'Bold'); subplot(2, 7, 14); imshow(word71); title('字符7', 'FontWeight', 'Bold');endfunction mask = Mask_Process(Img, id)% 图像蒙版处理函数% 输入参数:% Img图像矩阵% id图像序号% 输出参数:% mask模板图像% 如果已经存在模板图像则不再取模板filename = sprintf('maskmask%d.jpg', id);if exist(filename, 'file') mask = imread(filename); if isa(mask, 'logical') mask = im2bw(mask); end sz = size(Img); if isequal(sz(1:2), size(mask) mask = imresize(mask, sz(1:2); mask = logical(mask); end return;endI = Img;Ptn = ;figure;subplot(1, 3, 1); imshow(I);title('取点_左键取点,右键退出', 'Color', 'r', . 'FontWeight', 'Bold');hold on;set(gcf, 'units', 'normalized', 'position', 0 0 1 1);x, y, button = ginput(1); % 点击while button = 1 plot(x, y, 'r+', 'LineWidth', 2); % 绘制节点 Ptn = Ptn; x y; % 存储节点 x, y, button = ginput(1); % 点击endif size(Ptn, 1) < 2 return;endPtn = Ptn; Ptn(1, :);plot(Ptn(:, 1), Ptn(:, 2), 'ro-', 'LineWidth', 2, 'MarkerFaceColor', 'k');title('原图像', 'Color', 'k', . 'FontWeight', 'Bold');mask = Get_PointSplineMask(I, Ptn); % 获取蒙板图像subplot(1, 3, 2); imshow(mask);title('蒙板图像', 'Color', 'k', . 'FontWeight', 'Bold');if ndims(I) = 3 I1 = I .* uint8(cat(3, mask, mask, mask);else if isequal(size(I), size(mask) mask = imresize(mask, size(I); mask = logical(mask); end I1 = I .* mask;endsubplot(1, 3, 3); imshow(I1);title('蒙板分割结果', 'Color', 'k', . 'FontWeight', 'Bold');imwrite(mask, filename);function str = Pattern_Recognition(words)% 车牌字符识别% 输入参数:% words车牌字符图像% 输出参数:% str识别结果pattern = ;dirpath = './标准库/'%读取所有样本文件files = ls(dirpath '*.jpg');for t = 1 : length(files) imagedata = imread(dirpath, files(t,:); %读取样本文件 imagedata = im2bw(imagedata, 0.5); pattern(t).feature = imagedata; end % 字符库列表chepaiword=. '沪' 'C' 'E' 'N' '2' '6' '7' '浙' 'B' 'T' '2' '0' '0' '8' . '皖' 'N' '6' '9' '3' '3' '5' '皖' 'A' 'M' '3' '7' '6' '7' . '沪' 'B' '9' '1' '2' '1' '3' '沪' 'F' 'S' '2' '6' '9' '5' . '吉' 'A' 'E' '3' '1' '2' '7' '沪' 'B' 'B' '3' '3' '9' '3' . '沪' 'J' 'B' '7' '7' '7' '8' '京' 'H' 'Z' '9' '1' '3' '9' . '晋' 'K' 'C' '3' '8' '4' '1' '苏' 'D' 'V' '0' '0' '0' '1' . '苏' 'A' 'V' '8' '8' '8' '8' '浙' 'B' '8' '8' '8' '8' '8' . '沪' 'F' 'Q' '1' '2' '7' '7' '苏' 'E' 'D' '0' '0' '0' '9' . '沪' 'E' 'C' '1' '2' '8' '8' '苏' 'G' 'B' '0' '5' '7' '8' . '沪' 'B' 'B' '2' '0' '2' '9' '沪' 'D' '5' '4' '2' '2' '6'for m = 1 : 7; for n = 1 : length(files); switch m case 1 distance(n)=sum(sum(abs(words.word1-pattern(n).feature); case 2 distance(n)=sum(sum(abs(words.word2-pattern(n).feature); case 3 distance(n)=sum(sum(abs(words.word3-pattern(n).feature); case 4 distance(n)=sum(sum(abs(words.word4-pattern(n).feature); case 5 distance(n)=sum(sum(abs(words.word5-pattern(n).feature); case 6 distance(n)=sum(sum(abs(words.word6-pattern(n).feature); case 7 distance(n)=sum(sum(abs(words.word7-pattern(n).feature); end end yvalue,xnumber=min(distance); filename = files(xnumber, :); pathstr, name, ext = fileparts(filename); result(m) = chepaiword(str2num(name);endstr = '识别结果为:' result;msgbox(str, '车牌识别', 'modal'); str = result;function result = Plate_Process(plate, id, flag)% 车牌区域处理% 输入参数:% plate车牌区域% id车牌序号% flag显示图像标记% 输出参数:% result结果图像if nargin < 3 flag = 1;endif ndims(plate) = 3 plate1 = rgb2gray(plate);% figure(1)% imshow(plate1)else plate1 = plate;endIm = Image_Rotate(plate1, id);th = 0.85 0.50 0.85 0.70 0.30 . 0.40 0.65 0.45 0.45 0.65 . 0.51 0.80 0.40 0.75 0.60 . 0.55 0.40 0.40 0.76 0.72;bw = im2bw(Im, th(id); % 车牌区域二值化h = fspecial('average', 2); % 均值滤波模板bw1 = imfilter(bw, h, 'replicate'); % 均值滤波% figure(1)% imshow(bw1)mask = Mask_Process(bw1, id); % 模板处理bw2 = bw1 .* mask; % 模板滤波result = bw2;if flag figure; subplot(2, 2, 1); imshow(plate); title('车牌区域图像', 'FontWeight', 'Bold'); subplot(2, 2, 2); imshow(Im); title('车牌区域校正图像', 'FontWeight', 'Bold'); subplot(2, 2, 3); imshow(bw1); title('车牌区域二值图像', 'FontWeight', 'Bold'); subplot(2, 2, 4); imshow(bw2); title('滤波二值图像', 'FontWeight', 'Bold');endfunction Plate, bw, Loc = Pre_Process(Img, parm, flag)% 车牌图像预处理,提取车牌区域% 输入参数:% Img图像矩阵% parm参数向量% flag是否显示处理结果% 输出参数:% Plate分割结果if nargin < 3 flag = 1;endif nargin < 2 | isempty(parm) if size(Img, 2) > 900 parm = 0.35 0.9 90 0.35 0.7 90 2; end if size(Img, 2) > 700 && size(Img, 2) < 900 parm = 0.6 0.9 90 0.6 0.8 90 0.5; end if size(Img, 2) > 500 && size(Img, 2) < 700 parm = 0.5 0.54 50 0.6 0.7 50 3; end if size(Img, 2) < 500 parm = 0.8 0.9 150 0.8 0.9 150 3; endendI = Img;y, x, z = size(I); % y方向对应行、x方向对应列、z方向对应深度% 图像尺寸过大会影响处理效率,所以进行放缩处理if y > 800 rate = 800/y; I = imresize(I, rate);endy, x, z = size(I); % y方向对应行、x方向对应列、z方向对应深度myI = double(I); % 数据类型转换bw1 = zeros(y, x);bw2 = zeros(y, x);Blue_y = zeros(y, 1);% 对每一个像素进行分析,统计满足条件的像素所在的行对应的个数for i = 1 : y for j = 1 : x rij = myI(i, j, 1)/(myI(i, j, 3)+eps); gij = myI(i, j, 2)/(myI(i, j, 3)+eps); bij = myI(i, j, 3); % 蓝色RGB的灰度范围 if (rij < parm(1) && gij < parm(2)