車線検出|エッジ検出の原理を利用して車線画像を識別

序文

那么这里博主先安利一些干货满满的专栏了!

这两个都是博主在学习Linux操作系统过程中的记录,希望对大家的学习有帮助!

操作系统Operating Syshttps://blog.csdn.net/yu_cblog/category_12165502.html?spm=1001.2014.3001.5482Linux Sys https://blog.csdn.net/yu_cblog/category_11786077.html?spm=1001.2014.3001.5482これら 2 つは、ブロガーがデータ構造を学習し、STL 標準テンプレート ライブラリ内のさまざまなコンテナをシミュレートするための列です。

STL ソース コード分析https://blog.csdn.net/yu_cblog/category_11983210.html?spm=1001.2014.3001.5482手で引き裂かれたデータ構造https://blog.csdn.net/yu_cblog/category_11490888.html


1. 概要 

本実験では、エッジ検出の原理を学習し、Matlabプログラミング言語を使用することで、出力された与えられた画像のエッジ検出画像と車線認識を完成させます。

2. 実験内容と目的

与えられた画像のエッジ検出画像を出力し、車線境界線認識を完了します。

3. 関連する実験原理の説明

エッジ検出は、画像内のオブジェクトやシーンのエッジや輪郭を検出するために使用される画像処理技術です。その原理は、画像内の明るさや色の変化を分析してエッジの位置を特定することです。一般的に使用されるエッジ検出方法には、Sobel、Prewitt、Canny などが含まれます。

この実験の主なプロセスは次のとおりです。

主な手順の原則 

ガウスフィルタリング:

ガウス フィルタリングは、画像の平滑化、ノイズの除去、エッジ検出などのアプリケーションで使用される一般的な画像処理技術です。これはガウス関数 (正規分布関数とも呼ばれる) の概念に基づいており、画像内のピクセルの加重平均を取ることで平滑化効果を実現します。

ガウス フィルタリングの式は次のとおりです。
G(x, y) = \frac{1}{2\pi\sigma^2} \cdot e^{-\frac{x^2 + y^2}{2\sigma^2}}

このうち、G ( x,y)は座標(x,y)におけるガウスフィルタの重み値を表し、σはフィルタのぼけ度合いを制御するガウス関数の標準偏差を表す。標準偏差が大きいほど、フィルターはよりぼやけます。

ガウス フィルタリングの原理は、ガウス関数の重み値を使用して画像内のピクセルに重み付けを行うことです。フィルタの中心ピクセルの重みが最も大きく、中心ピクセルから遠くにあるピクセルの重みは小さくなります。隣接するピクセルの平均を重み付けすることにより、画像内のノイズを平均化し、画像の全体的な構造とエッジの特徴を保存することができます。

Sobel 演算子は勾配を計算します。

水平方向のソーベル演算子:
G_x = \begin{bmatrix} -1 & 0 & 1 \\ -2 & 0 & 2 \\ -1 & 0 & 1 \end{bmatrix}\displaystyle

垂直方向のソーベル演算子:
G_y = \begin{bmatrix} -1 & -2 & -1 \\ 0 & 0 & 0 \\ 1 & 2 & 1 \end{bmatrix}

これらのテンプレートは、それぞれ水平方向と垂直方向の微分演算に対応する 3x3 行列です。これらのテンプレートを画像と畳み込むことで、画像の水平方向と垂直方向の勾配値を取得できます。

非最大抑制:

非最大値抑制を使用して、ピクセルの極大値を見つけ、非最大値に対応するグレー値を 0 に設定し、最大値ポイントを 1 に設定することで、多数の非エッジ ピクセルがを除去することができるため、一対のバイナリ画像が得られ、エッジは理想的には単一ピクセルのエッジになります。
\begin{array}{l} g_{up}(i, j)=(1-t) \cdot g_{xy}(i, j+1)+t \cdot g_{xy}(i-1, j +1)\\ g_{\text {down }}(i, j)=(1-t) \cdot g_{xy}(i, j-1)+t \cdot g_{xy}(i+1, j-1) \end{配列}

4. 実験の過程と結果

% 读取图片
img = imread('图像路径');
imshow(img);
% 将图像转换为灰度
gray_img = rgb2gray(img);
% 高斯滤波
sigma = 2; % 高斯滤波器的标准差
gaussian_filtered_img = imgaussfilt(gray_img, sigma);
% 使用Sobel算子进行梯度计算
sobel_filtered_img = double(edge(gaussian_filtered_img, 'sobel'));
% 显示原始图像和处理后的图像
imshow(img); title('原始图像');
imshow(sobel_filtered_img); title('梯度计算后的图像');
% 定义梯度方向
directions = [-pi/2, -pi/4, 0, pi/4, pi/2, 3*pi/4, pi, -3*pi/4];

% 对每个像素,找到沿着梯度方向的两个相邻像素,计算它们的插值
nms_img = zeros(size(sobel_filtered_img));
for i=2:size(sobel_filtered_img,1)-1
    for j=2:size(sobel_filtered_img,2)-1
        % 找到最近的两个方向
        [~, index] = min(abs(directions - atan2d(-sobel_filtered_img(i,j), sobel_filtered_img(i,j+1))));
        if index == 1 || index == 5
            left = sobel_filtered_img(i-1,j-1);
            right = sobel_filtered_img(i+1,j+1);
        elseif index == 2 || index == 6
            left = sobel_filtered_img(i-1,j+1);
            right = sobel_filtered_img(i+1,j-1);
        elseif index == 3 || index == 7
            left = sobel_filtered_img(i,j-1);
            right = sobel_filtered_img(i,j+1);
        elseif index == 4 || index == 8
            left = sobel_filtered_img(i+1,j-1);
            right = sobel_filtered_img(i-1,j+1);
        end
        
        % 如果像素值是局部最大值,则保留
        if sobel_filtered_img(i,j) >= left && sobel_filtered_img(i,j) >= right
            nms_img(i,j) = sobel_filtered_img(i,j);
        end
    end
end

% 显示非极大值抑制后的图像
figure; imshow(nms_img); title('非极大值抑制后的图像');
% 阈值滞后处理
low_threshold = 0.05;
high_threshold = 0.2;
edge_map = zeros(size(nms_img));
edge_map(nms_img > high_threshold) = 1;
for i=2:size(nms_img,1)-1
    for j=2:size(nms_img,2)-1
        if (nms_img(i,j) > low_threshold) && (edge_map(i,j) == 0)
            if (edge_map(i-1,j-1) == 1) || (edge_map(i-1,j) == 1) || (edge_map(i-1,j+1) == 1) || (edge_map(i,j-1) == 1) || (edge_map(i,j+1) == 1) || (edge_map(i+1,j-1) == 1) || (edge_map(i+1,j) == 1) || (edge_map(i+1,j+1) == 1)
                edge_map(i,j) = 1;
            end
        end
    end
end
imshow(edge_map);

% 孤立弱边缘抑制
isolated_threshold = 1;
for i=2:size(edge_map,1)-1
    for j=2:size(edge_map,2)-1
        if (edge_map(i,j) == 1) && (sum(sum(edge_map(i-1:i+1,j-1:j+1))) <= isolated_threshold)
            edge_map(i,j) = 0;
        end
    end
end
imshow(edge_map);
% 车道线检测
% [m,n] = size(edge_map)
% x = [1600,0,0,1600];
% y = [1000,0,0,1000];
% mask = poly2mask(x,y,m,n);
% new_img = mask.*edge_map;
% imshow(new_img);

new_img = edge_map;
lines = HoughStraightRecognize(new_img);

hold on;
imshow(img);
for k = 1:length(lines)
% k = 7;
xy = [lines(k).point1; lines(k).point2];
plot(xy(:,1),xy(:,2),'LineWidth',2,'Color','green');
plot(xy(1,1),xy(1,2),'x','LineWidth',2,'Color','yellow');
plot(xy(2,1),xy(2,2),'x','LineWidth',2,'Color','red');
end

function lines = HoughStraightRecognize(BW)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%该函数为霍夫变换识别直线的函数
%input:图像(可以是二值图,也可以是灰度图)
%output:直线的struct结构,其结构组成为线段的两个端点
%以及在极坐标系下的坐标【rho,theta】
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    [H,T,R] = hough(BW);
    % imshow(H,[],'XData',T,'YData',R,...
    %             'InitialMagnification','fit');
    % xlabel('\theta'), ylabel('\rho');
        % axis on, axis normal, hold on;
    P  = houghpeaks(H,5,'threshold',ceil(0.3*max(H(:))));
    %x = T(P(:,2)); y = R(P(:,1));
    %plot(x,y,'s','color','white');
    lines = houghlines(BW,T,R,P,'FillGap',5,'MinLength',7);
    %FillGap 两个线段之间的距离,小于该值会将两个线段合并
    %MinLength 最小线段长度
end

実験中に得られた出力画像を次の図に示します。

おすすめ

転載: blog.csdn.net/Yu_Cblog/article/details/131751019
おすすめ