Оцените и визуализируйте обнаружения контура маршрута по основной истине

В этом примере показано, как оценить эффективность обнаружения контура маршрута против известной основной истины. В этом примере вы охарактеризуете эффективность алгоритма обнаружения контура маршрута на основе на систему координат путем вычисления меры качества подгонки. Эта мера может использоваться, чтобы точно определить, визуализировать, и изучить типы отказа в базовом алгоритме.

Обзор

С возрастающим интересом к основанным на видении решениям автоматизированных ведущих проблем способность оценить и проверить точность алгоритмов обнаружения стала очень важной. Проверка точности особенно важна в алгоритмах обнаружения, которые имеют несколько параметров, которые могут быть настроены, чтобы достигнуть результатов, которые удовлетворяют предопределенным требованиям к уровню качества. Этот пример идет через один такой рабочий процесс, где контуры маршрута могут быть измерены для их уровня точности. Этот рабочий процесс помогает точно определить типы отказа в этих алгоритмах на основе на систему координат, а также охарактеризовать его общую производительность. Этот рабочий процесс также помогает вам визуально, и количественно изучите эффективность алгоритма. Можно затем использовать это понимание, чтобы настроить базовый алгоритм, чтобы улучшать его производительность.

Загрузите достоверные данные

Набор данных, используемый в этом примере, является видеофайлом от фронтальной камеры на транспортном средстве, проезжающем улица. Основная истина для контуров маршрута была вручную отмечена на видео с приложением Ground Truth Labeler, использование ROI Линии пометило "LaneBoundary". Это видео составляет 8 секунд или 250 систем координат долго. Это имеет три перекрестных пересечения, несколько транспортных средств (припаркованный и перемещающийся), и контуры маршрута (двойная линия, одна, и подчеркнутая штриховой линией). Чтобы создать набор данных контура маршрута основной истины для вашего собственного видео, можно использовать приложение Ground Truth Labeler.

% Load MAT file with ground truth data
loaded = load('caltech_cordova1_laneAndVehicleGroundTruth.mat');

loaded структура содержит три поля:

  1. groundTruthData, расписание с двумя столбцами: LaneBoundaries и Vehicles. LaneBoundaries содержит точки основной истины для контуров маршрута эго (левых и правых), представленных как массив ячеек точек XY, формирующих poly линию. Vehicles содержит ограничительные рамки основной истины для транспортных средств в поле зрения камеры, представленном как массивы M-4 [x, y, ширина, высота].

  2. sensor, monoCamera объект со свойствами о калиброванной камере, смонтированной на транспортном средстве. Этот объект позволяет вам оценить реальные расстояния между транспортным средством и объектами перед ним.

  3. videoName, символьный массив, содержащий имя файла видео, где системы координат хранятся.

Из данных в этой структуре откройте видеофайл при помощи VideoReader циклично выполняться через системы координат. VideoReader возразите использует helperMonoSensor объект обнаружить маршруты и объекты в видеокадре, с помощью настройки камеры, сохраненной в sensor. timetable переменная сохранена в gtdata содержит достоверные данные. Эта переменная содержит данные на систему координат, которые используются для анализа позже.

% Create a VideoReader object to read frames of the video.
videoName  = loaded.videoName;
fileReader = VideoReader(videoName);

% The ground truth data is organized in a timetable.
gtdata = loaded.groundTruthData;

% Display the first few rows of the ground truth data.
head(gtdata)
ans =

  8x2 timetable

        Time          Vehicles      LaneBoundaries
    ____________    ____________    ______________

    0 sec           {6x4 double}      {2x1 cell}  
    0.033333 sec    {6x4 double}      {2x1 cell}  
    0.066667 sec    {6x4 double}      {2x1 cell}  
    0.1 sec         {6x4 double}      {2x1 cell}  
    0.13333 sec     {6x4 double}      {2x1 cell}  
    0.16667 sec     {6x4 double}      {2x1 cell}  
    0.2 sec         {6x4 double}      {2x1 cell}  
    0.23333 sec     {5x4 double}      {2x1 cell}  

gtdata расписание имеет столбцы Vehicles и LaneBoundaries. В каждой метке времени, Vehicles столбец содержит массив M-4 ограничительных рамок транспортного средства и LaneBoundaries столбец содержит двухэлементный массив ячеек левых и правых граничных точек маршрута.

Во-первых, визуализируйте загруженные достоверные данные для фрейма изображения.

% Read the first frame of the video.
frame = readFrame(fileReader);

% Extract all lane points in the first frame.
lanePoints = gtdata.LaneBoundaries{1};

% Extract vehicle bounding boxes in the first frame.
vehicleBBox = gtdata.Vehicles{1};

% Superimpose the right lane points and vehicle bounding boxes.
frame = insertMarker(frame, lanePoints{2}, 'X');
frame = insertObjectAnnotation(frame, 'rectangle', vehicleBBox, 'Vehicle');

% Display ground truth data on the first frame.
figure
imshow(frame)

Запустите алгоритм обнаружения контура маршрута

Используя видеокадры и monoCamera параметры, можно автоматически оценить местоположения контуров маршрута. Для рисунка, processFrame метод helperMonoSensor класс используется здесь, чтобы обнаружить контуры маршрута (как parabolicLaneBoundary объекты) и транспортные средства (как [x, y, ширина, высота] матрицы ограничительной рамки). В целях этого примера это - алгоритм "обнаружения контура маршрута под тестом". Можно использовать тот же шаблон для оценки пользовательского алгоритма обнаружения контура маршрута, где processFrame заменяется пользовательской функцией обнаружения. Точки основной истины в координатах транспортного средства также хранятся в LanesInVehicleCoord столбец gtdata расписание. Тем путем они могут визуализироваться в отображении Вида с высоты птичьего полета позже. Во-первых, сконфигурируйте helperMonoSensor объект с sensor. helperMonoSensor класс собирает все необходимые шаги, требуемые запускать алгоритм обнаружения контура маршрута.

% Set up monoSensorHelper to process video.
monoCameraSensor = loaded.sensor;
monoSensorHelper = helperMonoSensor(monoCameraSensor);

% Create new timetable with same Time vector for measurements.
measurements = timetable(gtdata.Time);

% Set up timetable columns for holding lane boundary and vehicle data.
numFrames = floor(fileReader.FrameRate*fileReader.Duration);
measurements.LaneBoundaries    = cell(numFrames, 2);
measurements.VehicleDetections = cell(numFrames, 1);
gtdata.LanesInVehicleCoord     = cell(numFrames, 2);

% Rewind the video to t = 0, and create a frame index to hold current
% frame.
fileReader.CurrentTime = 0;
frameIndex  = 0;

% Loop through the videoFile until there are no new frames.
while hasFrame(fileReader)
    frameIndex = frameIndex+1;
    frame      = readFrame(fileReader);

    % Use the processFrame method to compute detections.
    % This method can be replaced with a custom lane detection method.
    detections = processFrame(monoSensorHelper, frame);

    % Store the estimated lane boundaries and vehicle detections.
    measurements.LaneBoundaries{frameIndex} = [detections.leftEgoBoundary ...
                                               detections.rightEgoBoundary];
    measurements.VehicleDetections{frameIndex} = detections.vehicleBoxes;

    % To facilitate comparison, convert the ground truth lane points to the
    % vehicle coordinate system.
    gtPointsThisFrame = gtdata.LaneBoundaries{frameIndex};
    vehiclePoints = cell(1, numel(gtPointsThisFrame));
    for ii = 1:numel(gtPointsThisFrame)
        vehiclePoints{ii} = imageToVehicle(monoCameraSensor, gtPointsThisFrame{ii});
    end

    % Store ground truth points expressed in vehicle coordinates.
    gtdata.LanesInVehicleCoord{frameIndex} = vehiclePoints;
end

Теперь, когда вы обработали видео с алгоритмом обнаружения маршрута, проверьте, что точки основной истины правильно преобразовываются в систему координат транспортного средства. Первая запись в LanesInVehicleCoord столбец gtdata расписание содержит координаты транспортного средства для первой системы координат. Постройте эти точки основной истины на первой системе координат в Виде с высоты птичьего полета.

% Rewind video to t = 0.
fileReader.CurrentTime = 0;

% Read the first frame of the video.
frame = readFrame(fileReader);
birdsEyeImage = transformImage(monoSensorHelper.BirdsEyeConfig, frame);

% Extract right lane points for the first frame in Bird's-Eye View.
firstFrameVehiclePoints = gtdata.LanesInVehicleCoord{1};
pointsInBEV = vehicleToImage(monoSensorHelper.BirdsEyeConfig, firstFrameVehiclePoints{2});

% Superimpose points on the frame.
birdsEyeImage = insertMarker(birdsEyeImage, pointsInBEV, 'X', 'Size', 6);

% Display transformed points in Bird's-Eye View.
figure
imshow(birdsEyeImage)

Измерьте ошибки обнаружения

Вычисление ошибок в обнаружении контура маршрута является существенным шагом в проверке эффективности нескольких нисходящих подсистем. Такие подсистемы включают системы предупреждения о сходе с полосы, которые зависят от точности подсистемы обнаружения маршрута.

Можно оценить эту точность путем измерения качества подгонки. С точками основной истины и вычисленными оценками, можно теперь сравнить и визуализировать их, чтобы узнать, как хорошо алгоритмы обнаружения выполняют.

Качество подгонки может быть измерено или на уровне на систему координат или для целого видео. Статистические данные на систему координат предоставляют подробную информацию об определенных сценариях, таких как поведение в дорожных поворотах, где эффективность алгоритма обнаружения может варьироваться. Глобальные статистические данные обеспечивают большую оценку изображения количества маршрутов, которые пропустили обнаружение.

Используйте evaluateLaneBoundaries функционируйте, чтобы возвратить глобальную статистику обнаружения и assignments массив. Этот массив соответствует, предполагаемые объекты контура маршрута с соответствующей основной истиной указывает.

Пороговый параметр в evaluateLaneBoundaries функция представляет максимальное боковое расстояние в координатах транспортного средства, чтобы квалифицировать как соответствие с предполагаемыми параболическими контурами маршрута.

threshold = 0.25; % in meters

[numMatches, numMisses, numFalsePositives, assignments] = ...
    evaluateLaneBoundaries(measurements.LaneBoundaries, ...
                           gtdata.LanesInVehicleCoord, ...
                           threshold);

disp(['Number of matches: ', num2str(numMatches)]);
disp(['Number of misses: ', num2str(numMisses)]);
disp(['Number of false positives: ', num2str(numFalsePositives)]);
Number of matches: 316
Number of misses: 129
Number of false positives: 27

Используя assignments массив, можно вычислить полезные метрики на маршрут, такие как среднее боковое расстояние между оценками и точками основной истины. Такие метрики указывают, как хорошо алгоритм выполняет. Чтобы вычислить среднюю метрику расстояния, используйте функцию помощника helperComputeLaneStatistics, который задан в конце этого примера.

averageDistance = helperComputeLaneStatistics(measurements.LaneBoundaries, ...
                                              gtdata.LanesInVehicleCoord, ...
                                              assignments, @mean);

% Plot average distance between estimates and ground truth.
figure
stem(gtdata.Time, averageDistance)
title('Average Distance Between Estimates and Ground Truth')
grid on
ylabel('Distance in Meters')
legend('Left Boundary','Right Boundary')

Визуализируйте и рассмотрите различия между основной истиной и вашим алгоритмом

У вас теперь есть количественное понимание точности алгоритма обнаружения маршрута. Однако не возможно полностью изучить отказы только на основе графика в предыдущем разделе. Смотрение видео и визуализация ошибок на основе на систему координат поэтому крайне важны для идентификации определенных типов отказа, которые могут быть улучшены путем совершенствования алгоритма.

Можно использовать приложение Ground Truth Labeler в качестве инструмента визуализации, чтобы смотреть видео, содержащее достоверные данные и предполагаемые контуры маршрута. driving.connector.Connector класс обеспечивает интерфейс, чтобы присоединить пользовательские инструменты визуализации к Ground Truth Labeler.

Используйте parabolicLaneBoundary массив и достоверные данные, чтобы вычислить транспортное средство координируют местоположения предполагаемых точек. parabolicLaneBoundary массив задает линию, и достоверным данным отметили дискретные точки на дороге. helperGetCorrespondingPoints функционируйте оценочные точки на предполагаемых линиях, которые соответствуют тому же расстоянию Оси Y от транспортного средства. Эта функция помощника задана в конце примера.

Точки основной истины и предполагаемые точки теперь включены в новый timetable визуализироваться в приложении Ground Truth Labeler. Созданный groundTruth объект затем хранится как файл MAT.

% Compute the estimated point locations using the monoCamera.
[estVehiclePoints, estImagePoints] = helperGetCorrespondingPoints(monoCameraSensor, ...
                                     measurements.LaneBoundaries, ...
                                     gtdata.LanesInVehicleCoord, ...
                                     assignments);

% Add estimated lanes to the measurements timetable.
measurements.EstimatedLanes      = estImagePoints;
measurements.LanesInVehicleCoord = estVehiclePoints;

% Create a new timetable with all the variables needed for visualization.
names = {'LanePoints'; 'DetectedLanePoints'};
types = labelType({'Line'; 'Line'});
labelDefs = table(names, types, 'VariableNames', {'Name','Type'});

visualizeInFrame = timetable(gtdata.Time, ...
                             gtdata.LaneBoundaries, ...
                             measurements.EstimatedLanes, ...
                             'VariableNames', names);

% Create groundTruth object.
dataSource = groundTruthDataSource(videoName);
dataToVisualize = groundTruth(dataSource, labelDefs, visualizeInFrame);

% Save all the results of the previous section in distanceData.mat in a
% temporary folder.
dataToLoad = [tempdir 'distanceData.mat'];
save(dataToLoad, 'monoSensorHelper', 'videoName', 'measurements', 'gtdata', 'averageDistance');

helperCustomUI класс создает график и Виды с высоты птичьего полета с помощью данных, загруженных из файла MAT, как тот, который вы только создали. Интерфейс Connector приложения Ground Truth Labeler взаимодействует с helperCustomUI класс через helperUIConnector класс, чтобы синхронизировать видео со средним графиком расстояния и Видом с высоты птичьего полета. Эта синхронизация позволяет вам анализировать результаты на систему координат и аналитически и визуально.

Выполните эти шаги, чтобы визуализировать результаты как показано в изображениях, которые следуют:

  • Перейдите к временной директории где distanceData.mat сохранено, и откройте приложение Ground Truth Labeler. Затем запустите приложение Ground Truth Labeler с указателем коннектора, заданным как helperUIConnector использование следующих команд:

>> origdir = pwd;
>> cd(tempdir)
>> groundTruthLabeler(dataSource, 'ConnectorTargetHandle', @helperUIConnector);
  • Метки импорта: Визуализируйте маркеры маршрута основной истины и предполагаемые маршруты в координатах изображений. От панели инструментов приложения нажмите Import Labels. Затем выберите Из опции Рабочей области и загрузите dataToVisualize основная истина в приложение. Окно главного приложения теперь содержит аннотации для маркеров маршрута.

Можно теперь перейти через видео и исследовать ошибки. Чтобы возвратиться назад к исходной директории, можно ввести:

>> cd(origdir)

От этой визуализации можно сделать несколько выводов об алгоритме и качестве достоверных данных.

  • Левая точность маршрута последовательно хуже, чем правильная точность маршрута. После более близкого наблюдения в отображении Вида с высоты птичьего полета достоверные данные отмечены как внешняя граница двойной линии, тогда как предполагаемый контур маршрута обычно лежит в центре двойного маркера линии. Это указывает, что левая оценка маршрута, вероятно, более точна, чем числа изображают, и что ясно заданный набор данных основной истины крайне важен для таких наблюдений.

  • Обнаружение разрывает приблизительно 2,3 секунды, и 4 секунды соответствуют пересечениям на дороге, которым предшествуют переходы. Это указывает, что алгоритм не выполняет хорошо в присутствии переходов.

  • Приблизительно 6,8 секунд, когда транспортное средство приближается к третьему пересечению, маршрут эго, отличаются в лево-единственный маршрут и прямой маршрут. Здесь также, алгоритму не удается получить левый маршрут точно, и достоверные данные также не содержат информации для пяти систем координат.

Заключение

Этот пример показал, как измерить точность алгоритма обнаружения контура маршрута и визуализировать ее с помощью приложения Ground Truth Labeler. Можно расширить эту концепцию к другим пользовательским алгоритмам, чтобы упростить эти рабочие процессы и расширить функциональность приложения для пользовательских измерений.

Вспомогательные Функции

helperComputeLaneStatistics

Эта функция помощника вычисляет статистику для обнаружений контура маршрута по сравнению с точками основной истины. Это берет в указателе на функцию, который может использоваться, чтобы обобщить статистическую величину, которая должна быть вычислена, включая @mean и @median.

function stat = helperComputeLaneStatistics(estModels, gtPoints, assignments, fcnHandle)

    numFrames = length(estModels);
    % Make left and right estimates NaN by default to represent lack of
    % data.
    stat = NaN*ones(numFrames, 2);

    for frameInd = 1:numFrames
        % Make left and right estimates NaN by default.
        stat(frameInd, :) = NaN*ones(2, 1);

        for idx = 1:length(estModels{frameInd})
            % Ignore false positive assignments.
            if assignments{frameInd}(idx) == 0
                continue;
            end

            % The kth boundary in estModelInFrame is matched to kth
            % element indexed by assignments in gtPointsInFrame.
            thisModel = estModels{frameInd}(idx);
            thisGT = gtPoints{frameInd}{assignments{frameInd}(idx)};
            thisGTModel = driving.internal.piecewiseLinearBoundary(thisGT);
            if mean(thisGTModel.Points(:,2)) > 0
                % left lane
                xPoints = thisGTModel.Points(:,1);
                yDist = zeros(size(xPoints));
                for index = 1:numel(xPoints)
                    gtYPoints   = thisGTModel.computeBoundaryModel(xPoints(index));
                    testYPoints = thisModel.computeBoundaryModel(xPoints(index));
                    yDist(index) = abs(testYPoints-gtYPoints);
                end
                stat(frameInd, 1) = fcnHandle(yDist);
            else % right lane
                xPoints = thisGTModel.Points(:,1);
                yDist = zeros(size(xPoints));
                for index = 1:numel(xPoints)
                    gtYPoints   = thisGTModel.computeBoundaryModel(xPoints(index));
                    testYPoints = thisModel.computeBoundaryModel(xPoints(index));
                    yDist(index) = abs(testYPoints-gtYPoints);
                end
                stat(frameInd, 2) = fcnHandle(yDist);
            end
        end
    end
end

helperGetCorrespondingPoints

Эта функция помощника создает транспортное средство и точки координаты изображений в местоположениях Оси X, которые совпадают с точками основной истины.

function [vehiclePoints, imagePoints] = helperGetCorrespondingPoints(monoCameraSensor, estModels, gtPoints, assignments)

    numFrames = length(estModels);
    imagePoints = cell(numFrames, 1);
    vehiclePoints = cell(numFrames, 1);

    for frameInd = 1:numFrames
        if isempty(assignments{frameInd})
            imagePointsInFrame = [];
            vehiclePointsInFrame = [];
        else
            estModelInFrame = estModels{frameInd};
            gtPointsInFrame = gtPoints{frameInd};
            imagePointsInFrame = cell(length(estModelInFrame), 1);
            vehiclePointsInFrame = cell(length(estModelInFrame), 1);
            for idx = 1:length(estModelInFrame)

                % Ignore false positive assignments.
                if assignments{frameInd}(idx) == 0
                    imagePointsInFrame{idx} = [NaN NaN];
                    continue;
                end

                % The kth boundary in estModelInFrame is matched to kth
                % element indexed by assignments in gtPointsInFrame.
                thisModel = estModelInFrame(idx);
                thisGT = gtPointsInFrame{assignments{frameInd}(idx)};
                xPoints = thisGT(:, 1);
                yPoints = thisModel.computeBoundaryModel(xPoints);

                vehiclePointsInFrame{idx} = [xPoints, yPoints];
                imagePointsInFrame{idx} = vehicleToImage(monoCameraSensor, [xPoints yPoints]);
            end
        end
        vehiclePoints{frameInd} = vehiclePointsInFrame;
        imagePoints{frameInd}   = imagePointsInFrame;
        % Make imagePoints [] instead of {} to comply with groundTruth object.
        if isempty(imagePoints{frameInd})
            imagePoints{frameInd} = [];
        end
        if isempty(vehiclePoints{frameInd})
            vehiclePoints{frameInd} = [];
        end
    end
end

Смотрите также

Приложения

Функции

Объекты

Похожие темы