车牌识别
分为三个步骤:车牌区域定位、车牌字符分割、车牌字符识别。
车牌区域定位
首先,我们使用Hough变换检测直线来定位车牌边界进而获取车牌区域(还有一种就是用蓝色来进行行列查找,等会会演示,这个方法有一些情况是无法满足要求的)。
但是,在那之前,我们需要对图片进行去噪、二值化处理。
去噪、二值化
f = imread('车牌.jpg');
g = rgb2gray(f);
g = adapthisteq(g);
g = imfilter(g, fspecial('gaussian', [5 5], 0.2));
h1 = edge(g,'sobel', 0.25, 'vertical'); % 使用sobel算子进行边缘检测
h2 = edge(g,'sobel', 0.25, 'horizontal'); % 使用sobel算子进行边缘检测
subplot(1, 3, 1), imshow(g);
subplot(1, 3, 2), imshow(h1);
subplot(1, 3, 3), imshow(h2);
接着,再使用Hough检测直线。
f = imread('车牌.jpg');
g = rgb2gray(f);
g = adapthisteq(g);
g = imfilter(g, fspecial('gaussian', [5 5], 0.2));
h1 = edge(g,'sobel', 0.25, 'vertical'); % 使用sobel算子进行边缘检测
h2 = edge(g,'sobel', 0.25, 'horizontal'); % 使用sobel算子进行边缘检测
imshow(f), hold on;
[H theta rho] = hough(h1);
peaks = houghpeaks(H, 50);
lines = houghlines(h1, theta , rho, peaks, 'FillGap', 10, 'MinLength', 25);
len = 0;
for i = 1 : length(lines)
xy = [lines(i).point1; lines(i).point2];
plot(xy(:, 1), xy(:, 2), 'LineWidth', 2, 'Color', 'red');
end
[H theta rho] = hough(h2);
peaks = houghpeaks(H, 50);
lines = houghlines(h2, theta , rho, peaks, 'FillGap', 20, 'MinLength', 50);
len = 0;
for i = 1 : length(lines)
xy = [lines(i).point1; lines(i).point2];
plot(xy(:, 1), xy(:, 2), 'LineWidth', 2, 'Color', 'yellow');
end
可以看到,分别用水平、垂直方向的sobel算子来进行边缘检测后进行hough直线检测,可以检测出来牌照的位置。
我们可以按照这样的策略,如果找到二条直线,垂直(水平)方向的长度近似相等,那么这个区域内就是牌照的区域,让我们试一试。
f = imread('车牌.jpg');
g = rgb2gray(f);
g = adapthisteq(g);
g = imfilter(g, fspecial('gaussian', [5 5], 0.2));
h1 = edge(g,'sobel', 0.25, 'vertical'); % 使用sobel算子进行边缘检测
h2 = edge(g,'sobel', 0.25, 'horizontal'); % 使用sobel算子进行边缘检测
[H theta rho] = hough(h1, 'RhoResolution', 0.5);
peaks = houghpeaks(H, 50);
lines = houghlines(h1, theta , rho, peaks, 'FillGap', 10, 'MinLength', 25);
n = 1;
for i = 1 : length(lines)
xy = [lines(i).point1; lines(i).point2];
LEND(n) = norm(lines(i).point1 - lines(i).point2);
XYD{n} = xy;
n = n + 1;
end
[H theta rho] = hough(h2, 'RhoResolution', 0.5);
peaks = houghpeaks(H, 50);
lines = houghlines(h2, theta , rho, peaks, 'FillGap', 20, 'MinLength', 50);
for i = 1 : length(lines)
xy = [lines(i).point1; lines(i).point2];
LEND(n) = norm(lines(i).point1 - lines(i).point2);
XYD{n} = xy;
n = n + 1;
end
imshow(f), hold on;
for i = 1 : n - 1
for j = 1 : n - 1
xy1 = XYD{i};
xy2 = XYD{j};
k1 = (xy1(2, 2) - xy1(1, 2))/(xy1(2, 1) - xy1(1, 1));
k2 = (xy2(2, 2) - xy2(1, 2))/(xy2(2, 1) - xy2(1, 1));
if abs(k1 - k2) < 0.1
if abs(xy1(1, 1) - xy2(1, 1)) < 5 || abs(xy1(2, 2) - xy2(2, 2)) < 5 || abs(xy1(1, 2) - xy2(1, 2)) < 5 || abs(xy1(2, 1) - xy2(2, 1)) < 5
plot(xy1(:, 1), xy1(:, 2), 'LineWidth', 2, 'Color', 'red');
plot([xy1(1, 1), xy2(1, 1)], [xy1(1, 2), xy2(1, 2)], 'LineWidth', 2, 'Color', 'red');
plot(xy2(:, 1), xy2(:, 2), 'LineWidth', 2, 'Color', 'red');
plot([xy1(2, 1), xy2(2, 1)], [xy1(2, 2), xy2(2, 2)], 'LineWidth', 2, 'Color', 'red');
end
end
end
end
也可以用下面这个方法
function [Plate, bw, Loc] = Pre_Process(Img, parm, flag)
if nargin < 1
Img = imread(fullfile(pwd, 'images/car.jpg'));
end
if 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];
end
end
if nargin < 3
flag = 1;
end
I = Img;
[y, ~, ~] = size(I);
if y > 800
rate = 800/y;
I = imresize(I, rate);
end
[y, x, ~] = size(I);
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);
if (rij < parm(1) && gij < parm(2) && bij > parm(3)) ...
|| (gij < parm(1) && rij < parm(2) && bij > parm(3))
Blue_y(i, 1) = Blue_y(i, 1) + 1;
bw1(i, j) = 1;
end
end
end
[~, MaxY] = max(Blue_y);
Th = parm(7);
PY1 = MaxY;
while ((Blue_y(PY1,1)>Th) && (PY1>1))
PY1 = PY1 - 1;
end
PY2 = MaxY;
while ((Blue_y(PY2,1)>Th) && (PY2<y))
PY2 = PY2 + 1;
end
PY1 = PY1 - 2;
PY2 = PY2 + 2;
if PY1 < 1
PY1 = 1;
end
if PY2 > y
PY2 = y;
end
IY = I(PY1:PY2, :, :);
Blue_x = zeros(1,x);
for j = 1:x
for i = PY1:PY2
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);
if (rij < parm(4) && gij < parm(5) && bij > parm(6)) ...
|| (gij < parm(4) && rij < parm(5) && bij > parm(6))
Blue_x(1,j) = Blue_x(1,j) + 1;
bw2(i, j) = 1;
end
end
end
PX1 = 1;
while (Blue_x(1,PX1)<Th) && (PX1<x)
PX1 = PX1 + 1;
end
PX2 = x;
while (Blue_x(1,PX2)<Th) && (PX2>PX1)
PX2 = PX2 - 1;
end
PX1 = PX1 - 2;
PX2 = PX2 + 2;
if PX1 < 1
PX1 = 1;
end
if PX2 > x
PX2 = x;
end
IX = I(:, PX1:PX2, :);
Plate = I(PY1:PY2, PX1:PX2, :);
Loc.row = [PY1 PY2];
Loc.col = [PX1 PX2];
bw = bw1 + bw2;
bw = logical(bw);
bw(1:PY1, :) = 0;
bw(PY2:end, :) = 0;
bw(:, 1:PX1) = 0;
bw(:, PX2:end) = 0;
if flag
figure;
subplot(2, 2, 3); imshow(IY); title('行过滤结果', 'FontWeight', 'Bold');
subplot(2, 2, 1); imshow(IX); title('列过滤结果', 'FontWeight', 'Bold');
subplot(2, 2, 2); imshow(I); title('原图像', 'FontWeight', 'Bold');
subplot(2, 2, 4); imshow(Plate); title('分割结果', 'FontWeight', 'Bold');
end
但是下面这个方法,如果背景有蓝色,还有白色的字,你看。
用Hough的结果
写到这,测试了第二张图,发现根本找不到边缘,改用canny算子来进行边缘检测。
f = imread('车牌2.jpg');
g = rgb2gray(f);
g = adapthisteq(g);
g = imfilter(g, fspecial('gaussian', [5 5], 0.2));
h = edge(g,'canny', 0.25); % 使用sobel算子进行边缘检测
subplot(1, 2, 1), imshow(g);
subplot(1, 2, 2), imshow(h);
但是可以看到,这边的线不是直线,我需要将它变成直线。
f = imread('车牌2.jpg');
g = rgb2gray(f);
g = adapthisteq(g);
g = imfilter(g, fspecial('gaussian', [5 5], 0.2));
h = edge(g,'canny', 0.25); % 使用sobel算子进行边缘检测
subplot(1, 2, 1), imshow(h);
h = bwmorph(h, 'dilate', 1);
subplot(1, 2, 2), imshow(h);
试了好多方法,还是不行,无法正确的找到直线,等明天再写。
你听说了么,传说中的人形大宝宝又来了。