ドキュメンテーション

最新のリリースでは、このページがまだ翻訳されていません。 このページの最新版は英語でご覧になれます。

車線逸脱警告システム

この例では、ビデオ ストリーム内で路上の車線マーカーを検出する方法と、車両の走行車線を強調表示する方法を説明します。こうした情報は、意図しない車線逸脱を検出し、警告を発するために使用できます。

はじめに

この例では、ビデオ シーケンス内で路上の車線マーカーを検出して追跡し、車線を超えた場合はドライバーに知らせます。また、HoughTransformHoughLines および LocalMaximaFinder の System object を使用して車線の検出と追跡用のアルゴリズムを作成する方法について説明します。例では以下の手順を使用してこのアルゴリズムを実装します。

  1. 現在のビデオ フレーム内で車線マーカーを検出する。

  2. 現在の車線マーカーを前のビデオ フレームで検出されたマーカーとマッチングする。

  3. 左と右の車線マーカーを見つける。

  4. 車両がどちらかの車線マーカーを超えた場合、警告メッセージを発行する。

ここでは車線マーカーが見づらかったり、オブジェクトの背後に隠れているような低品質のビデオ シーケンスを処理するため、車線マーカーが複数のフレームに現れるまで待ってからマーカーを有効とみなします。車線マーカーを無視し始めるタイミングを決定する場合にも、同じプロセスを使用します。

初期化

次のコード セクションを使用して必要な変数と System object を初期化します。

DrawPoly = 1;  % Set to 0 to draw only lines
NumRows = 120; % Number of rows in the image region to process.
MaxLaneNum = 20; % Maximum number of lanes to store in the tracking repository.
ExpLaneNum = 2;  % Maximum number of lanes to find in the current frame.
Rep_ref   = zeros(2, MaxLaneNum); % Stored lines
Count_ref = zeros(1, MaxLaneNum); % Count of each stored line
TrackThreshold = 75; % Maximum allowable change of lane distance
                     % metric between two frames.
LaneColors = single([0 0 0;1 1 0; 1 1 0; 1 1 1;1 1 1]);
% Minimum number of frames a lane must be detected to become a valid lane.
frameFound = 5;
% Maximum number of frames a lane can be missed without marking it invalid.
frameLost = 20;

% For selecting Rho values 35:45 (1-based index: 415:424)
startIdxRho_R = 415;
NumRhos_R = 11;

% For selecting Theta values -90:-70deg (1-based index: 1:21)
startIdxTheta_R = 1;
NumThetas_R = 21;

% For selecting Rho values 379:415 (1-based index: 1:36)
startIdxRho_L = 380;
NumRhos_L = 36;

% For selecting Theta values 55:85deg (1-based index: 146:176)
startIdxTheta_L = 146;
NumThetas_L = 21;

% Offset for displaying the lines
offset = int32([0, NumRows, 0, NumRows]);

ファイルからビデオを読み取る VideoFileReader の System object™ を作成します。

hVideoSrc = vision.VideoFileReader('viplanedeparture.mp4');

車線マーカーで定義されたラインの直交座標を見つける HoughLines の System object を作成します。

hHoughLines1 = vision.HoughLines('SineComputation', 'Trigonometric function');
hHoughLines3 = vision.HoughLines('SineComputation', 'Trigonometric function');

車線逸脱の警告テキストを挿入するためのパラメーターを定義します。

warnText = {sprintf('Right\nDeparture'), '', sprintf(' Left\n Departure')};
warnTextLoc = [120 170;-1 -1; 2 170];

車線マーカーの色やタイプを指定するテキストを挿入するためのパラメーターを定義します。

lineText = {'', ...
        sprintf('Yellow\nBroken'), sprintf('Yellow\nSolid'), ...
        sprintf('White\nBroken'), sprintf('White\nSolid')};

出力ビデオを表示する VideoPlayer の System object を作成します。

hVideoOut = vision.VideoPlayer;

ストリーム処理ループで使用される変数を初期化します。

Frame = 0;
NumNormalDriving = 0;
OutMsg = int8(-1);
OutMsgPre = OutMsg;
Broken = false;

ストリーム処理ループ

入力ビデオで車線検出を実行する処理ループを作成します。このループはインスタンス化した System object を使用します。

warningTextColors = {[1 0 0], [1 0 0], [0 0 0], [0 0 0]};
while ~isDone(hVideoSrc)
    RGB = step(hVideoSrc);

    % Select the lower portion of input video (confine field of view)
    Imlow  = RGB(NumRows+1:end, :, :);

    % Edge detection and Hough transform
    Imlow = rgb2gray(Imlow); % Convert RGB to intensity
    I = imfilter(Imlow, [-1 0 1], 'replicate','corr');

    % Saturate the values to be between 0 and 1
    I(I < 0) = 0;
    I(I > 1) = 1;

    th = multithresh(I); % compute threshold
    [H, Theta, Rho] = hough(I > th);

    % Convert Theta to radians
    Theta = Theta * pi / 180;

    % Peak detection
    H1 = H;
    % Wipe out H matrix with theta < -78 deg and theta >= 78 deg
    H1(:, 1:12) = 0;
    H1(:, end-12:end) = 0;
    Idx1 = houghpeaks(H1, ExpLaneNum, 'NHoodSize', [301 81], 'Threshold', 1);
    Count1 = size(Idx1,1);

    % Select Rhos and Thetas corresponding to peaks
    Line = [Rho(Idx1(:, 1)); Theta(Idx1(:, 2))];
    Enable = [ones(1,Count1) zeros(1, ExpLaneNum-Count1)];

    % Track a set of lane marking lines
    [Rep_ref, Count_ref] = videolanematching(Rep_ref, Count_ref, ...
                                MaxLaneNum, ExpLaneNum, Enable, Line, ...
                                TrackThreshold, frameFound+frameLost);

    % Convert lines from Polar to Cartesian space.
    Pts = step(hHoughLines1, Rep_ref(2,:), Rep_ref(1,:), Imlow);

    % Detect whether there is a left or right lane departure.
    [TwoValidLanes, NumNormalDriving, TwoLanes, OutMsg] = ...
            videodeparturewarning(Pts, Imlow, MaxLaneNum, Count_ref, ...
                                   NumNormalDriving, OutMsg);
    % Meaning of OutMsg: 0 = Right lane departure,
    %                    1 = Normal driving, 2 = Left lane departure

    % Detect the type and color of lane marker lines
    YCbCr  = rgb2ycbcr(double(RGB(NumRows+1:240, :, :)));
    ColorAndTypeIdx = videodetectcolorandtype(TwoLanes, YCbCr);
    % Meaning of ColorAndTypeIdx:
    % INVALID_COLOR_OR_TYPE = int8(0);
    % YELLOW_BROKEN = int8(1); YELLOW_SOLID = int8(2);
    % WHITE_BROKEN = int8(3);  WHITE_SOLID = int8(4).

    % Output
    Frame = Frame + 1;
    if Frame >= 5
        TwoLanes1 = TwoLanes + [offset; offset]';
        if DrawPoly && TwoValidLanes
            if TwoLanes(4,1) >= 239
                Templ = TwoLanes1(3:4, 1);
            else
                Templ = [0 239]';
            end
            if TwoLanes(4,2) >= 239
                Tempr = TwoLanes1(3:4, 2);
            else
                Tempr = [359 239]';
            end
            Pts_poly = [TwoLanes1(:,1); Templ; Tempr; ...
                TwoLanes1(3:4,2); TwoLanes1(1:2,2)];

            % Draw Polygon for lane
            RGB = insertShape(RGB,'FilledPolygon',Pts_poly.',...
                              'Color',[0 1 1],'Opacity',0.2);
        end

        % Draw lane marker lines
        RGB = insertShape(RGB,'Line',TwoLanes1',...
            'Color',{'yellow','magenta'});
        % Insert Departure warning text (empty text will not be drawn)
        txt = warnText{OutMsg+1};
        txtLoc = warnTextLoc(OutMsg+1, :);
        txtColor = single(warningTextColors{mod(Frame-1,4)+1});
        RGB = insertText(RGB,txtLoc,txt,'TextColor', txtColor, ...
                            'FontSize',20, 'BoxOpacity', 0);

        % Insert text indicating type and color of left and right lanes
        for ii=1:2
            % empty text will not be drawn
           txtLoc = TwoLanes1([1 2], ii)' + int32([0 -35]);
           lineTxt = lineText{ColorAndTypeIdx(ii)};
           txtColor = LaneColors(ColorAndTypeIdx(ii), :);
           RGB = insertText(RGB,txtLoc,lineTxt,'TextColor',txtColor, ...
                              'FontSize',14, 'BoxOpacity', 0);
        end

        % Draw third lane if needed
        if OutMsgPre ~= OutMsg
            ColorType = ColorAndTypeIdx(2-(OutMsg == 2));
            Broken    = ColorType == 2 || ColorType == 4;
        end
        ShowThirdLane = Broken && (OutMsg~=1);
        if ShowThirdLane
            if OutMsg == 0
                % Find right third lane
                Idx2 = houghpeaks(H(startIdxRho_R:startIdxRho_R+NumRhos_R-1, ...
                           startIdxTheta_R:startIdxTheta_R+NumThetas_R-1), ...
                           'NHoodSize', [7 7], 'Threshold', 1);
                Rhor = Rho(Idx2(:,1) + startIdxRho_R);
                Thetar = Theta(Idx2(:,2) + startIdxTheta_R);
                ThirdLane = step(hHoughLines3, Thetar, Rhor, Imlow);
            else
                % Find left third lane
                Idx3 = houghpeaks(H(startIdxRho_L:startIdxRho_L+NumRhos_L-1 , ...
                           startIdxTheta_L:startIdxTheta_L+NumThetas_L-1),...
                            'NHoodSize', [7 7], 'Threshold', 1);
                Rhol = Rho(Idx3(:,1) + startIdxRho_L);
                Thetal = Theta(Idx3(:,2) + startIdxTheta_L);
                ThirdLane = step(hHoughLines3, Thetal, Rhol, Imlow);
            end

            OutThirdLane = videoexclude3rdlane(ThirdLane, ShowThirdLane,...
                                   TwoLanes, TwoValidLanes, YCbCr);
            OutThirdLane = OutThirdLane(:) + offset(:);
            RGB = insertShape(RGB,'Line',OutThirdLane.','Color','green');
        end
    end
    OutMsgPre = OutMsg;

    step(hVideoOut, RGB);    % Display video
end

Release

ここでは System object に対して release メソッドを呼び出し、開いているファイルと装置を閉じます。

release(hVideoSrc);

まとめ

ビデオ プレーヤー ウィンドウにおいて、車両前方の車線の位置が検出され、その位置をマークするためにシアンの多角形が描かれたのがわかります。また、この例では車両が車線を逸脱すると通知が出て、検出された車線マーカー ラインのタイプも知らされます。

付録

この例では次の補助関数が使用されています。

この情報は役に立ちましたか?