机器学习-学习笔记 学习总结归纳(第八周)

来源:互联网 发布:hadoop 知乎 编辑:程序博客网 时间:2024/05/20 11:26

图像去噪

减少数字图像中噪声的过程,广泛应用于图像处理领域的预处理过程,去噪效果的好坏会直接影响后续的图像处理效果,如图像分割、图像模式识别等。

噪声的产生

噪声只要产生于获取、传输图像的过程中。

常见的噪声有高斯噪声和椒盐噪声,其中高斯噪声主要由摄像机传感器元器件内部产生的,椒盐噪声主要是由图像切割所产生的黑白相间的亮暗点噪声,椒指黑色噪声,盐指白色噪声,还有另外泊松噪声,想继续了解的可以看这里浅析三种的噪声区别。

f = imread('onion.png');g = imnoise(f, 'salt & pepper', 0.05);h = imnoise(f, 'gaussian', 0.05, 0.05);subplot(1, 3, 1), imshow(f), title('原图');subplot(1, 3, 2), imshow(g), title('椒盐');subplot(1, 3, 3), imshow(h), title('高斯');

这里写图片描述

图像去噪

图像去噪可以分为空域和频域来完成。

空域图像去噪常用的有均值滤波算法和中值滤波算法(对像素做邻域的运算来达到去噪效果)。

f = imread('onion.png');f = rgb2gray(f);g = imnoise(f, 'salt & pepper', 0.05);subplot(2, 2, 1), imshow(f), title('原图');subplot(2, 2, 2), imshow(g), title('椒盐');g1 = imfilter(g, fspecial('average'));g2 = medfilt2(g, [5 5]);subplot(2, 2, 3), imshow(g1), title('均值滤波');subplot(2, 2, 4), imshow(g2), title('中值滤波');

这里写图片描述

可以看出来,去噪效果还是很明显的(中值滤波去除椒盐噪声)。
那高斯噪声怎么去除呢?用均值滤波可以减弱对高斯噪声的影响。

f = imread('onion.png');f = rgb2gray(f);h = imnoise(f, 'gaussian', 0, 0.025);subplot(2, 2, 1), imshow(f), title('原图');subplot(2, 2, 2), imshow(h), title('高斯');subplot(2, 2, 3), imshow(wiener2(h, [5 5])), title('二维自适应除噪滤波器');subplot(2, 2, 4), imshow(imfilter(h, fspecial('average', 5))), title('5*5 均值滤波');

这里写图片描述

function igo = myFun(f)s = getStrelList();e = erodeList(f, s);g = getRateList(f, e);igo = getRemoveResult(g, e);endfunction s = getStrelList()s.co11 = strel('line', 5, -45);s.co12 = strel('line', 7, -45);s.co21 = strel('line', 5, 45);s.co22 = strel('line', 7, 45);s.co31 = strel('line', 3, 90);s.co32 = strel('line', 5, 90);s.co41 = strel('line', 3, 0);s.co42 = strel('line', 5, 0);endfunction e = erodeList(ig, s)e.eroded_co11 = imerode(ig, s.co11);e.eroded_co12 = imerode(e.eroded_co11, s.co12);e.eroded_co21 = imerode(ig, s.co21);e.eroded_co22 = imerode(e.eroded_co21, s.co22);e.eroded_co31 = imerode(ig, s.co31);e.eroded_co32 = imerode(e.eroded_co31, s.co32);e.eroded_co41 = imerode(ig, s.co41);e.eroded_co42 = imerode(e.eroded_co41, s.co42);endfunction f = getRateList(ig, e)f.df1 = sum(sum(abs(double(e.eroded_co12) - double(ig))));f.df2 = sum(sum(abs(double(e.eroded_co22) - double(ig))));f.df3 = sum(sum(abs(double(e.eroded_co32) - double(ig))));f.df4 = sum(sum(abs(double(e.eroded_co42) - double(ig))));f.df = sum([f.df1 f.df2 f.df3 f.df4]);endfunction igo = getRemoveResult(f, e)igo = f.df1 / f.df * double(e.eroded_co12) + f.df2 / f.df * double(e.eroded_co22) + ...    f.df3 / f.df * double(e.eroded_co32) + f.df4 / f.df ...    * double (e.eroded_co42);igo = mat2gray(igo);end
f = imread('人像.jpg');h = imnoise(f, 'poisson');r = h(:, :, 1);g = h(:, :, 2);b = h(:, :, 3);subplot(2, 2, 1), imshow(f), title('原图');subplot(2, 2, 2), imshow(h), title('泊松');subplot(2, 2, 3), imshow(cat(3, imfilter(r, fspecial('average', 5)), imfilter(g, fspecial('average', 5)), imfilter(b, fspecial('average', 5)))), title('5*5 均值滤波');subplot(2, 2, 4), imshow(cat(3, myFun(r), myFun(g), myFun(b))), title('形态学滤波');

这里写图片描述

感觉没什么太大的区别,要说的话,就是形态学保留了原先的色彩细节,均值的话,就有点失去了的意思(感觉像是磨皮- -)。

答题卡识别

答题卡自动阅卷系统通过获取答题卡图像作为系统输入,并通过计算机处理、自动识别填图标记,存入数据库完成阅卷。
但是答题卡在运输和使用过程中,容易受到设备、环境等因素的影响,使得图像质量在一定程度上有所下降,影响了自动阅卷的准确率,甚至导致无法正常阅卷,因此要对答题卡图像进行一系列的预处理,滤去干扰、噪声,做几何校正(有的答题卡可能是倒着的),彩色校正等,并进行二值化处理。

图像二值化

图像的二值化,就是将图像的像素点只有1和0的取值,用来表示黑(0)白(1)二种颜色。

 f = imread('答题卡.jpg'); subplot(1, 2, 1), imshow(f), title('原图'); subplot(1, 2, 2), imshow(im2bw(f, graythresh(f))), title('二值化');

这里写图片描述

可以看到,如果不预先对图像进行处理的话,就会出现这种情况,那么结合我们现在学习的知识,让我们试一试一些处理方法吧。

对比度增强处理
 f = imread('答题卡.jpg'); f = rgb2gray(f); subplot(1, 3, 1), imshow(f), title('原图'); f = adapthisteq(f); subplot(1, 3, 2), imshow(f), title('增强后'); subplot(1, 3, 3), imshow(im2bw(f, graythresh(f))), title('二值化');

这里写图片描述

这下子清晰了很多,但是呢,我们是不是还录用了一些没有必要的干扰信息,我们现在就去除干扰信息。

对比度拉伸(归一化处理)

图像归一化是指对图像进行了一系列标准的处理变换,使之变换为一固定标准形式的过程,该标准图像称作归一化图像。

f = imread('答题卡.jpg');f = rgb2gray(f);subplot(1, 3, 1), imshow(f), title('原图');f = adapthisteq(f); % 对比度增强Low_High = stretchlim(f, [0.0 0.3]);f= imadjust(f, [0.0 0.25], [ ]);subplot(1, 3, 2), imshow(f), title('归一化处理');subplot(1, 3, 3), imshow(im2bw(f, graythresh(f))), title('二值化');

这里写图片描述

是不是加强了很多,接着,我们继续用中值滤波进行平滑处理。

f = imread('答题卡.jpg');f = rgb2gray(f);subplot(1, 3, 1), imshow(f), title('原图');f = adapthisteq(f); % 对比度增强Low_High = stretchlim(f, [0.0 0.3]);f= imadjust(f, Low_High, [ ]);f = medfilt2(f, [7 5]);subplot(1, 3, 2), imshow(f), title('平滑处理');f = im2bw(f, graythresh(f));subplot(1, 3, 3), imshow(f), title('二值化');

这里写图片描述

发现还是有一些小的点, 我们只需要进行开闭操作即可。

f = imread('答题卡.jpg');f = rgb2gray(f);subplot(1, 3, 1), imshow(f), title('原图');f = adapthisteq(f); % 对比度增强Low_High = stretchlim(f, [0.0 0.3]);f= imadjust(f, Low_High, [ ]);f = medfilt2(f, [7 5]);f = im2bw(f, graythresh(f));subplot(1, 3, 2), imshow(f), title('开闭前');f = imopen(f, strel('square', 4));f = imclose(f, strel('square', 4));subplot(1, 3, 3), imshow(f), title('开闭后');

这里写图片描述

可以看到,一些小点点都消失了,接着,我们发现有的小方块太小了,那怎么办?只需要进行腐蚀操作即可。

f = imread('答题卡.jpg');f = rgb2gray(f);subplot(1, 3, 1), imshow(f), title('原图');f = adapthisteq(f); % 对比度增强Low_High = stretchlim(f, [0.0 0.3]);f= imadjust(f, Low_High, [ ]);f = medfilt2(f, [7 5]);f = im2bw(f, graythresh(f));f = imopen(f, strel('square', 4));f = imclose(f, strel('square', 4));subplot(1, 3, 2), imshow(imcomplement(f)), title('腐蚀前');f = imerode(f, strel('square', 4));subplot(1, 3, 3), imshow(imcomplement(f)), title('腐蚀后');

这里写图片描述

怎么样,是不是很霸气- -,其中imcomplement是获得图像的负片的函数,就是1变成0,0变成1。

现在图像预处理完成了,接下来要干什么呢?就是要进行判断,分析!

先将其变为线的形式

f = imread('答题卡.jpg');f = rgb2gray(f);f = adapthisteq(f); % 对比度增强Low_High = stretchlim(f, [0.0 0.3]);f= imadjust(f, Low_High, [ ]);f = medfilt2(f, [7 5]);f = im2bw(f, graythresh(f));f = imopen(f, strel('square', 4));f = imclose(f, strel('square', 4));f = imerode(f, strel('square', 4));subplot(1, 2, 1), imshow(imcomplement(f)), title('画线前');f = edge(f, 'canny', [0.04, 0.10], 1.5 , 'vertical');subplot(1, 2, 2), imshow(f), title('画线后');

这里写图片描述

再找到最长的基准线

f = imread('答题卡.jpg');f = rgb2gray(f);f = adapthisteq(f); % 对比度增强Low_High = stretchlim(f, [0.0 0.3]);f= imadjust(f, Low_High, [ ]);f = medfilt2(f, [7 5]);f = im2bw(f, graythresh(f));f = imopen(f, strel('square', 4));f = imclose(f, strel('square', 4));f = imerode(f, strel('square', 4));f = edge(f, 'canny', [0.04, 0.10], 1.5 , 'vertical');[h t r] = hough(f);peaks = houghpeaks(h, 5);lines = houghlines(f, t, r, peaks, 'FillGap', 50, 'MinLength', 7);imshow(f), hold on;len = 0;for i = 1 : length(lines)    tLen = norm(lines(i).point1 - lines(i).point2);    if len < tLen        len = tLen        xy = [lines(i).point1; lines(i).point2];    endendplot(xy(:, 1), xy(:, 2), 'LineWidth', 4, 'Color', 'red');

这里写图片描述

不过可以看出来,这个有点歪,我们需要对他进行校正

f = imread('答题卡.jpg');f = rgb2gray(f);f = adapthisteq(f); % 对比度增强Low_High = stretchlim(f, [0.0 0.3]);f= imadjust(f, Low_High, [ ]);f = medfilt2(f, [7 5]);f = im2bw(f, graythresh(f));f = imopen(f, strel('square', 4));f = imclose(f, strel('square', 4));f = imerode(f, strel('square', 4));f = edge(f, 'canny', [0.04, 0.10], 1.5 , 'vertical');flag = true;while flag    figure;    [h t r] = hough(f);    peaks = houghpeaks(h, 5);    lines = houghlines(f, t, r, peaks, 'FillGap', 50, 'MinLength', 7);    subplot(1, 2, 1), imshow(f), title('校正前');    len = 0;    for i = 1 : length(lines)        tLen = norm(lines(i).point1 - lines(i).point2);        if len < tLen            len = tLen;            xy = [lines(i).point1; lines(i).point2];        end    end    x1 = xy(:, 1);    y1 = xy(:, 2);    K1 = (x1(2)-x1(1))/(y1(2)-y1(1));    angle = atan(K1)*180/pi;    s = size(f);    if y1(1) <= s(2) / 2 && y1(2) <= s(2) / 2&& abs(angle) > 75        f= imrotate(f, angle, 'bilinear');        flag = true;    else        f= imrotate(f, -angle, 'bilinear');        flag = false;    end    subplot(1, 2, 2), imshow(f), title('校正后');end

第一次校正
这里写图片描述
第二次校正
这里写图片描述

现在,我们的答题卡已经校正完毕,接着,我们需要将答题卡分割为信息部分和答题部分

f = imread('答题卡.jpg');f = rgb2gray(f);f = adapthisteq(f); % 对比度增强Low_High = stretchlim(f, [0.0 0.3]);f= imadjust(f, Low_High, [ ]);f = medfilt2(f, [7 5]);f = im2bw(f, graythresh(f));f = imopen(f, strel('square', 4));f = imclose(f, strel('square', 4));f = imerode(f, strel('square', 4));f = edge(f, 'canny', [0.04, 0.10], 1.5 , 'vertical');flag = true;while flag    [h t r] = hough(f);    peaks = houghpeaks(h, 5);    lines = houghlines(f, t, r, peaks, 'FillGap', 50, 'MinLength', 7);    len = 0;    for i = 1 : length(lines)        tLen = norm(lines(i).point1 - lines(i).point2);        if len < tLen            len = tLen;            xy = [lines(i).point1; lines(i).point2];        end    end    x1 = xy(:, 1);    y1 = xy(:, 2);    K1 = (x1(2)-x1(1))/(y1(2)-y1(1));    angle = atan(K1)*180/pi;    s = size(f);    if y1(1) <= s(2) / 2 && y1(2) <= s(2) / 2&& abs(angle) > 75        f= imrotate(f, angle, 'bilinear');        flag = true;    else        f= imrotate(f, -angle, 'bilinear');        flag = false;    endend% 再进行画线,画出三条基准线[h t r] = hough(f);peaks = houghpeaks(h, 5);lines = houghlines(f, t, r, peaks, 'FillGap', 50, 'MinLength', 7);figure, imshow(f), title('分割前'), hold on;for i = 1 : length(lines)    xy = [lines(i).point1; lines(i).point2];    if abs(lines(i).point1(2) - lines(i).point2(2)) <= 10        len(i) = norm(lines(i).point1 - lines(i).point2);    else        len(i) = -1;    end    plot(xy(:, 1), xy(:, 2), 'LineWidth', 4, 'Color', 'red');    plot(lines(i).point1(1), lines(i).point1(2), 'bo');    plot(lines(i).point2(1), lines(i).point2(2), 'yo');    xyD{i} = xy;end[len, ind] = sort(len(:), 'descend');for i = 1 : length(ind)    xyN{i} = xyD{ind(i)};endup = f;down = f;u = xyN{1};d = xyN{2};if u(1, 2) > d(1, 2)    t = u;    u = d;    d = t;endup(u(1, 2) : 1 : d(1, 2), :) = 0;down(1 : u(1, 2), :) = 0;figure, imshow(up), title('信息部分');figure, imshow(down), title('答题部分');

这里写图片描述
这里写图片描述
这里写图片描述

分割完了以后,让我们来获取信息。

f = imread('答题卡.jpg');rg = f;f = rgb2gray(f);f = adapthisteq(f); % 对比度增强Low_High = stretchlim(f, [0.0 0.3]);f= imadjust(f, Low_High , [ ]);f = medfilt2(f, [7 5]);f = im2bw(f, graythresh(f));f = imopen(f, strel('square', 4));f = imclose(f, strel('square', 4));f = imerode(f, strel('square', 4));f = edge(f, 'canny', [0.04, 0.10], 1.5 , 'vertical');flag = true;while flag    [h t r] = hough(f);    peaks = houghpeaks(h, 5);    lines = houghlines(f, t, r, peaks, 'FillGap', 50, 'MinLength', 7);    len = 0;    for i = 1 : length(lines)        tLen = norm(lines(i).point1 - lines(i).point2);        if len < tLen            len = tLen;            xy = [lines(i).point1; lines(i).point2];        end    end    x1 = xy(:, 1);    y1 = xy(:, 2);    K1 = (x1(2)-x1(1))/(y1(2)-y1(1));    right = x1(2);    angle = atan(K1)*180/pi;    s = size(f);    if y1(1) <= s(2) / 2 && y1(2) <= s(2) / 2&& abs(angle) > 75        f = imrotate(f, angle, 'bilinear');        rg = imrotate(rg, angle, 'bilinear');        flag = true;    else        f= imrotate(f, -angle, 'bilinear');        rg = imrotate(rg, -angle, 'bilinear');        flag = false;    endenddown = f;% 再进行画线,画出三条基准线[h t r] = hough(f);peaks = houghpeaks(h, 5);lines = houghlines(f, t, r, peaks, 'FillGap', 50, 'MinLength', 7);for i = 1 : length(lines)    xy = [lines(i).point1; lines(i).point2];    if abs(lines(i).point1(2) - lines(i).point2(2)) <= 10        len(i) = norm(lines(i).point1 - lines(i).point2);    else        len(i) = -1;    end    xyD{i} = xy;end[len, ind] = sort(len(:), 'descend');for i = 1 : length(ind)    xyN{i} = xyD{ind(i)};endu = xyN{1};d = xyN{2};if u(1, 2) > d(1, 2)    t = u;    u = d;    d = t;end% 下半部分处理subplot(1, 2, 1), imshow(rg), title('原图'), hold on;l = d(1, 2) - u(1, 2);l = l / 31;for i = 1 : 31    plot([0 1000], [u(1, 2) + l * (i - 1), u(1, 2) + l * (i - 1)], 'LineWidth', 1, 'Color', 'red');endl = right - d(1, 1);l = l / 26;for i = 1 : 26    plot([d(1, 1) + l * (i - 1), d(1, 1) + l * (i - 1)], [u(1, 2) d(1, 2)], 'LineWidth', 1, 'Color', 'red');enddown(1 : u(1, 2), :) = 0;down = imdilate(down, strel('square', 3));down = imfill(down, 'holes');subplot(1, 2, 2), imshow(down), title('处理图'), hold on;l = d(1, 2) - u(1, 2);l = l / 31;for i = 1 : 31    plot([0 1000], [u(1, 2) + l * (i - 1), u(1, 2) + l * (i - 1)], 'LineWidth', 1, 'Color', 'red');endl = right - d(1, 1);l = l / 27;for i = 1 : 27    plot([d(1, 1) + l * (i - 1), d(1, 1) + l * (i - 1)], [u(1, 2) d(1, 2)], 'LineWidth', 1, 'Color', 'red');end

这里写图片描述

到这里就差不多了,只需要判断对应方格内是否为1即可。

下面是另外一张答题卡的图像

这里写图片描述

车牌识别

分为三个步骤:车牌区域定位、车牌字符分割、车牌字符识别。

车牌区域定位

首先,我们使用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;endimshow(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    endend

这里写图片描述

也可以用下面这个方法

function [Plate, bw, Loc] = Pre_Process(Img, parm, flag)if nargin < 1    Img = imread(fullfile(pwd, 'images/car.jpg'));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];    endendif nargin < 3    flag = 1;endI = 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    endend[~, MaxY] = max(Blue_y);Th = parm(7);PY1 = MaxY;while ((Blue_y(PY1,1)>Th) && (PY1>1))    PY1 = PY1 - 1;endPY2 = MaxY;while ((Blue_y(PY2,1)>Th) && (PY2<y))    PY2 = PY2 + 1;endPY1 = PY1 - 2;PY2 = PY2 + 2;if PY1 < 1    PY1 = 1;endif PY2 > y    PY2 = y;endIY = 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    endendPX1 = 1;while (Blue_x(1,PX1)<Th) && (PX1<x)    PX1 = PX1 + 1;endPX2 = x;while (Blue_x(1,PX2)<Th) && (PX2>PX1)    PX2 = PX2 - 1;endPX1 = PX1 - 2;PX2 = PX2 + 2;if PX1 < 1    PX1 = 1;endif PX2 > x    PX2 = x;endIX = 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);

这里写图片描述

试了好多方法,还是不行,无法正确的找到直线,等明天再写。

蓝色区域切割

继续使用上节的Pre_Process来获得蓝色区域,并对蓝色区域进行判断。
流程如下

  • 获得蓝色区域
  • 对蓝色区域进行Hough直线检测并进行校正
  • 分析蓝色区域
  • 分析失败则返回第一步,并将此蓝色区域置为0。

我们先模拟一下如果第一次获取失败,进行第二次的过程。

hsv = rgb2hsv(f);v = hsv(:, :, 3);v = imfilter(v, fspecial('gaussian', [5 5], 0.2));f = hsv2rgb(cat(3, hsv(:, :, 1), hsv(:, :, 2), adapthisteq(v)));
f = imread('车牌2.jpg');[P B L] = Pre_Process(f);g = f(L.row(1):L.row(2), L.col(1):L.col(2), :);subplot(1, 2, 1), imshow(g), title('第一次分割');f(L.row(1):L.row(2), L.col(1):L.col(2), :) = 0;[P B L] = Pre_Process(f);g = f(L.row(1):L.row(2), L.col(1):L.col(2), :);subplot(1, 2, 2), imshow(g), title('第二次分割');

这里写图片描述

结果是可行的。

接着,我们进行校正,这里先假设第二次成功找到。

f = imread('车牌2.jpg');[P B L] = Pre_Process(f);f(L.row(1):L.row(2), L.col(1):L.col(2), :) = 0;[P B L] = Pre_Process(f);area = f(L.row(1):L.row(2), L.col(1):L.col(2), :);g = rgb2gray(area);g = adapthisteq(g); % 对比度增强h = edge(g,'canny', 0.25); % 使用sobel算子进行边缘检测h = bwmorph(h, 'dilate', 1);subplot(1, 2, 1), imshow(h), hold on;[H theta rho] = hough(h);peaks = houghpeaks(H, 1);lines = houghlines(h, theta , rho, peaks, 'FillGap', 25, 'MinLength', 25);for i = 1 : length(lines)    xy = [lines(i).point1; lines(i).point2];    plot(xy(:, 1), xy(:, 2), 'LineWidth', 2, 'Color', 'red');    x1 = xy(:, 1);    y1 = xy(:, 2);    K1 = (x1(2)-x1(1))/(y1(2)-y1(1));    angle = atan(K1)*180/pi;    area = imrotate(area, 90 - angle, 'bilinear');endsubplot(1, 2, 2), imshow(area);

这里写图片描述

接着在进行字符提取

f = imread('车牌2.jpg');[P B L] = Pre_Process(f);f(L.row(1):L.row(2), L.col(1):L.col(2), :) = 0;[P B L] = Pre_Process(f);area = f(L.row(1):L.row(2), L.col(1):L.col(2), :);g = rgb2gray(area);g = adapthisteq(g); % 对比度增强h = edge(g,'canny', 0.25); % 使用sobel算子进行边缘检测h = bwmorph(h, 'dilate', 1);[H theta rho] = hough(h);peaks = houghpeaks(H, 1);lines = houghlines(h, theta , rho, peaks, 'FillGap', 25, 'MinLength', 25);for i = 1 : length(lines)    xy = [lines(i).point1; lines(i).point2];    x1 = xy(:, 1);    y1 = xy(:, 2);    K1 = (x1(2)-x1(1))/(y1(2)-y1(1));    angle = atan(K1)*180/pi;    area = imrotate(area, 90 - angle, 'bilinear');endarea = rgb2gray(area);g_max=double(max(max(area)));g_min=double(min(min(area)));T=round(g_max-(g_max-g_min)/3);area = im2bw(area, T/256);area = bwareaopen(area, 20);[H theta rho] = hough(area);peaks = houghpeaks(H, 1);lines = houghlines(area, theta , rho, peaks, 'FillGap', 25, 'MinLength', 25);for i = 1 : length(lines)    xy = [lines(i).point1; lines(i).point2];    x1 = xy(:, 1);    y1 = xy(:, 2);    area(y1(1) : y1(2), x1(1):x1(2)) = 0;endarea2 = imfill(area, 'holes'); % 先将空洞删除X=[];z=0;flag=0;for j=1:size(area ,2)    sum_y=sum(area(:,j));    if logical(sum_y)~=flag          %列和有变化时,记录下此列        if(j-z > 3)            X=[X j];            flag=logical(sum_y);            z=j;                        %用z记录上一个j的值,防止两个列坐标间隔太小        end    endend[y x] = size(area2);X = [X y];for n=1:7    res = area(:, X(2 * n - 1):X(2 * n));     %进行粗分割    for i=1:size(res,1)                  %这两个for循环对分割字符的上下进行裁剪        if sum(res(i,:))~=0            top=i;            break        end    end    for i=1:size(res,1)        if sum(res(size(res,1)-i,:))~=0            bottom=size(res,1)-i;            break        end    end    res=res(top:bottom,:);    subplot(2, 4, n), imshow(res);end

这里写图片描述

接着对字符进行分析。

获取传入的二维图的车牌信息

function rec = getCarPlate(g)    g = adapthisteq(g); % 对比度增强    h = edge(g,'canny', 0.25); % 使用sobel算子进行边缘检测    h = bwmorph(h, 'dilate', 1);    [H theta rho] = hough(h);    peaks = houghpeaks(H, 1);    lines = houghlines(h, theta , rho, peaks, 'FillGap', 25, 'MinLength', 25);    for i = 1 : length(lines)        xy = [lines(i).point1; lines(i).point2];        x1 = xy(:, 1);        y1 = xy(:, 2);        K1 = (x1(2)-x1(1))/(y1(2)-y1(1));        angle = atan(K1)*180/pi;        area = imrotate(area, 90 - angle, 'bilinear');    end    area = rgb2gray(area);    g_max=double(max(max(area)));    g_min=double(min(min(area)));    T=round(g_max-(g_max-g_min)/3);    area = im2bw(area, T/256);    area = bwareaopen(area, 20);    area2 = imfill(area, 'holes'); % 先将空洞删除    X=[];    z=0;    flag=0;    for j=1:size(area ,2)        sum_y=sum(area(:,j));        if logical(sum_y)~=flag          %列和有变化时,记录下此列            if(j-z > 3)                X=[X j];                flag=logical(sum_y);                z=j;                        %用z记录上一个j的值,防止两个列坐标间隔太小            end        end    end    [y x] = size(area2);    X = [X y];    for n=1:7        res = area(:, X(2 * n - 1):X(2 * n));     %进行粗分割        for i=1:size(res,1)                  %这两个for循环对分割字符的上下进行裁剪            if sum(res(i,:))~=0                top=i;                break            end        end        for i=1:size(res,1)            if sum(res(size(res,1)-i,:))~=0                bottom=size(res,1)-i;                break            end        end        res=res(top:bottom,:);        res = imresize(res,[40,20],'nearest');    %归一化为40*20的大小,以便模板匹配        imgchar{n}=res;    end    res=[];    store1=strcat('贵','豫','粤','湘','鄂','皖','鲁','藏','京','苏','黑','吉','冀','晋','辽','浙','津','闽','云','陕','琼');  %创建汉字识别模板库    for j=1:21        Im=imgchar{1};        Template=imread(strcat('车牌汉字库\',num2str(j),'.jpg'));        Template=im2bw(Template);        Differ=Im-Template;        Compare(j)=sum(sum(abs(Differ)));    end    index=find(Compare==(min(Compare)));    res=[res store1(index)];    store2=strcat('A','B','C','D','E','F','G','H','J','K','L','M','N','P','Q','R','S','T','U','V','W','X','Y','Z','0','1','2','3','4','5','6','7','8','9'); %创建字母与数字识别模板库    for i=2:7        for j=1:34            Im=imgchar{i};            Template=imread(strcat('车牌字符库\',num2str(j),'.jpg'));            Template=im2bw(Template);            Differ=Im-Template;            Compare(j)=sum(sum(abs(Differ)));        end        index=find(Compare==(min(Compare)));        res=[res store2(index)];    endend

主函数

clear;clear all;f = imread('车牌.jpg');real = f;n = 1;while n < 5    [P B L] = Pre_Process(f);    area = f(L.row(1):L.row(2), L.col(1):L.col(2), :);    try        res = getCarPlate(area);        n = 999;    catch err        disp(err);        disp('截取失败,进行下一次截取');        f(L.row(1):L.row(2), L.col(1):L.col(2), :) = 0;        figure, imshow(f);        n = n + 1;    endendimshow(real), title(res);

这里写图片描述

我们还需要去除一些因为反光而白色的线。

h = imread('车牌8.jpg');subplot(1, 2, 1), imshow(h), hold on;[H theta rho] = hough(h);peaks = houghpeaks(H, 1);lines = houghlines(h, theta , rho, peaks, 'FillGap', 25, 'MinLength', 25);for i = 1 : length(lines)    xy = [lines(i).point1; lines(i).point2];    plot(xy(:, 1), xy(:, 2), 'LineWidth', 2, 'Color', 'red');    x1 = xy(:, 1);    y1 = xy(:, 2);    h(y1(1) : y1(2), x1(1):x1(2)) = 0;endsubplot(1, 2, 2), imshow(h);

这里写图片描述

接着再按照上面的过程执行即可。

阅读全文
1 0
原创粉丝点击