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

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

Обзор

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

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

Загрузите и подготовьте наземные данные об истине

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

Загрузите предопределенные левые и правые контуры маршрута эго, заданные в координатах изображений. Каждый контур представлен набором чисел M-2, представляющих M пиксельные местоположения вдоль того контура. Каждый кадр видео имеет самое большее два таких набора, представляющие левый и правый маршрут.

loaded = load('caltech_cordova1_EgoBoundaries.mat');
sensor = loaded.sensor; % Associated monoCamera object
gtImageBoundaryPoints = loaded.groundTruthData.EgoLaneBoundaries;

% Show a sample of the ground truth at this frame index
frameInd = 36;

% Load the video frame
frameTimeStamp = seconds(loaded.groundTruthData(frameInd,:).Time);
videoReader = VideoReader(loaded.videoName);
videoReader.CurrentTime = frameTimeStamp;
frame = videoReader.readFrame();

% Obtain the left lane points for this frame
boundaryPoints = gtImageBoundaryPoints{frameInd};
leftLanePoints = boundaryPoints{1};

figure
imshow(frame)
hold on
plot(leftLanePoints(:,1), leftLanePoints(:,2),'+','MarkerSize',10,'LineWidth',4);
title('Sample Ground Truth Data for Left Lane Boundary');

Преобразуйте наземные точки истины от координат изображений, чтобы транспортировать координаты, чтобы допускать прямое сравнение с граничными моделями. Чтобы выполнить это преобразование, используйте функцию imageToVehicle со связанным объектом monoCamera выполнить это преобразование.

gtVehicleBoundaryPoints = cell(numel(gtImageBoundaryPoints),1);
for frameInd = 1:numel(gtImageBoundaryPoints)
    boundaryPoints   = gtImageBoundaryPoints{frameInd};
    if ~isempty(boundaryPoints)
        ptsInVehicle = cell(1, numel(boundaryPoints));
        for cInd = 1:numel(boundaryPoints)
            ptsInVehicle{cInd} = imageToVehicle(sensor, boundaryPoints{cInd});
        end
        gtVehicleBoundaryPoints{frameInd} = ptsInVehicle;
    end
end

Образцовые контуры маршрута Используя монокулярный датчик

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

monoSensor  = helperMonoSensor(sensor);
boundaries  = detectBoundaries(loaded.videoName, monoSensor);

Оцените модели контура маршрута

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

threshold = 0.25; % in vehicle coordinates (meters)
[numMatches, numMisses, numFalsePositives, assignments] = ...
    evaluateLaneBoundaries(boundaries, gtVehicleBoundaryPoints, 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

Можно использовать эти необработанные количества, чтобы вычислить другую статистику, такую как точность, вспомнить, и счет F1:

precision = numMatches/(numMatches+numFalsePositives);
disp(['Precision: ', num2str(precision)]);

recall = numMatches/(numMatches+numMisses);
disp(['Sensitivity/Recall: ', num2str(recall)]);

f1Score = 2*(precision*recall)/(precision+recall);
disp(['F1 score: ', num2str(f1Score)]);
Precision: 0.92128
Sensitivity/Recall: 0.71011
F1 score: 0.80203

Визуализируйте результаты Используя видимый с большого расстояния график

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

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

hasMatch           = cellfun(@(x)numel(x)==2, assignments);
hasFalsePositive   = cellfun(@(x)nnz(x)==1, assignments);
frameInd           = find(hasMatch&hasFalsePositive,1,'first');
frameVehiclePoints = gtVehicleBoundaryPoints{frameInd};
frameImagePoints   = gtImageBoundaryPoints{frameInd};
frameModels        = boundaries{frameInd};

Используйте assignments вывод evaluateLaneBoundaries, чтобы найти модели, которые соответствовали (истинные положительные стороны) и модели, которые не имели никакого соответствия (ложные положительные стороны) в наземной истине.

matchedModels    = frameModels(assignments{frameInd}~=0);
fpModels         = frameModels(assignments{frameInd}==0);

Настройте видимый с большого расстояния график и визуализируйте наземные точки истины и модели на нем.

bep = birdsEyePlot();
gtPlotter = laneBoundaryPlotter(bep,'DisplayName','Ground Truth',...
    'Color','blue');
tpPlotter = laneBoundaryPlotter(bep,'DisplayName','True Positive',...
    'Color','green');
fpPlotter = laneBoundaryPlotter(bep,'DisplayName','False Positive',...
    'Color','red');

plotLaneBoundary(gtPlotter, frameVehiclePoints);
plotLaneBoundary(tpPlotter, matchedModels);
plotLaneBoundary(fpPlotter, fpModels);
title('Bird''s-Eye Plot of Comparison Results');

Визуализируйте результаты на видео при закрытых дверях и виде с высоты птичьего полета

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

Получите кадр, соответствующий кадру интереса.

videoReader             = VideoReader(loaded.videoName);
videoReader.CurrentTime = seconds(loaded.groundTruthData.Time(frameInd));
frame                   = videoReader.readFrame();

Рассмотрите граничные модели как сплошную линию (независимо от того, как датчик классифицирует ее) для визуализации.

fpModels.BoundaryType      = 'Solid';
matchedModels.BoundaryType = 'Solid';

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

xVehicle = 3:20;
frame = insertLaneBoundary(frame, fpModels, sensor, xVehicle,'Color','Red');
frame = insertLaneBoundary(frame, matchedModels, sensor, xVehicle,'Color','Green');
figure
ha = axes;
imshow(frame,'Parent', ha);

% Combine the left and right boundary points
boundaryPoints = [frameImagePoints{1};frameImagePoints{2}];
hold on
plot(ha, boundaryPoints(:,1), boundaryPoints(:,2),'+','MarkerSize',10,'LineWidth',4);
title('Camera View of Comparison Results');

Можно также визуализировать результаты в виде с высоты птичьего полета на этот кадр.

birdsEyeImage = transformImage(monoSensor.BirdsEyeConfig,frame);

xVehicle = 3:20;
birdsEyeImage = insertLaneBoundary(birdsEyeImage, fpModels, monoSensor.BirdsEyeConfig, xVehicle,'Color','Red');
birdsEyeImage = insertLaneBoundary(birdsEyeImage, matchedModels, monoSensor.BirdsEyeConfig, xVehicle,'Color','Green');

% Combine the left and right boundary points
ptsInVehicle = [frameVehiclePoints{1};frameVehiclePoints{2}];
gtPointsInBEV  = vehicleToImage(monoSensor.BirdsEyeConfig, ptsInVehicle);

figure
imshow(birdsEyeImage);
hold on
plot(gtPointsInBEV(:,1), gtPointsInBEV(:,2),'+','MarkerSize', 10,'LineWidth',4);
title('Bird''s-Eye View of Comparison Results');

Настройте параметры моделирования контура

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

  • LaneSegmentationSensitivity - Управляет чувствительностью функции segmentLaneMarkerRidge. Эта функция возвращает кандидата маршрута точки в форме бинарной маски функции маршрута. Значение чувствительности может отличаться от 0 до 1 со значением по умолчанию 0,25. Увеличение этого номера приводит к большему количеству кандидата маршрута точки и потенциально более ложные обнаружения.

  • LaneXExtentThreshold - Задает минимальную степень (длина) маршрута. Это выражается как отношение обнаруженной длины маршрута к максимальной длине маршрута, возможной для заданной настройки камеры. Значение по умолчанию 0.4. Увеличьте это число, чтобы отклонить более короткие контуры маршрута.

  • LaneStrengthThreshold - Задает минимальную нормированную силу, чтобы принять обнаруженный контур маршрута.

LaneXExtentThreshold и LaneStrengthThreshold выведены из свойств XExtent и Strength объекта parabolicLaneBoundary. Эти свойства являются примером того, как дополнительные ограничения могут быть помещены в алгоритмы моделирующего контура, чтобы получить приемлемые результаты. Влияние переменного LaneStrengthThreshold имеет дополнительные нюансы, которые стоит исследовать. Типичные контуры маршрута отмечены или сплошными или пунктирными линиями. Когда по сравнению со сплошными линиями, пунктирные линии имеют более низкое количество точек inlier, ведя к более низким значениям силы. Это делает его бросающий вызов, чтобы установить общий порог силы. Чтобы осмотреть влияние этого параметра, сначала сгенерируйте все контуры установкой LaneStrengthThreshold к 0. Эта установка гарантирует, что не оказывает влияния на вывод.

monoSensor.LaneStrengthThreshold = 0;
boundaries = detectBoundaries('caltech_cordova1.avi', monoSensor);

Свойство LaneStrengthThreshold helperMonoSensor управляет нормированным параметром Strength каждой модели parabolicLaneBoundary. Коэффициентом нормализации, MaxLaneStrength, является сила виртуального маршрута, который запускается для в полной мере видимого с большого расстояния изображения. Это значение определяется только настройкой birdsEyeView helperMonoSensor. Чтобы оценить влияние LaneStrengthThreshold, сначала вычислите распределение нормированных сильных мест маршрута для всех обнаруженных контуров в демонстрационном видео. Отметьте присутствие двух ясных peaks, один в нормированной силе 0,3 и один в 0,7. Эти два peaks соответствуют пунктирным и твердым контурам маршрута соответственно. Из этого графика можно опытным путем решить, что, чтобы гарантировать пунктирные контуры маршрута обнаруживаются, LaneStrengthThreshold должен быть ниже 0.3.

strengths = cellfun(@(b)[b.Strength], boundaries,'UniformOutput',false);
strengths = [strengths{:}];
normalizedStrengths = strengths/monoSensor.MaxLaneStrength;
figure;
hist(normalizedStrengths);
title('Histogram of Normalized Lane Strengths');

Можно использовать среду сравнения, чтобы далее оценить влияние параметров LaneStrengthThreshold на производительности обнаружения алгоритма моделирования. Обратите внимание на то, что значение threshold, управляющее максимальным физическим расстоянием между моделью и наземной истиной, остается то же самое как прежде. Это значение диктуют требования точности системы ADAS и обычно не изменяется.

threshold = .25;
[~, ~, ~, assignments] = ...
    evaluateLaneBoundaries(boundaries, gtVehicleBoundaryPoints, threshold);

Интервал каждый контур согласно его нормированной силе. Информация о assignments помогает классифицировать каждый контур или как истину, положительную (соответствующий) или как положительную ложь. LaneStrengthThreshold является порогом "min", таким образом, контур, классифицированный как истина, положительная в данном значении, продолжит быть истиной, положительной для всех более низких пороговых значений.

nMatch = zeros(1,100); % Normalized lane strength is bucketed into 100 bins
nFP    = zeros(1,100); % ranging from 0.01 to 1.00.
for frameInd = 1:numel(boundaries)
    frameBoundaries  = boundaries{frameInd};
    frameAssignment  = assignments{frameInd};
    for bInd = 1:numel(frameBoundaries)
        normalizedStrength = frameBoundaries(bInd).Strength/monoSensor.MaxLaneStrength;
        strengthBucket     = floor(normalizedStrength*100);
        if frameAssignment(bInd)
            % This boundary was matched with a ground truth boundary,
            % record as a true positive for all values of strength above
            % its strength value.
            nMatch(1:strengthBucket) = nMatch(1:strengthBucket)+1;
        else
            % This is a false positive
            nFP(1:strengthBucket) = nFP(1:strengthBucket)+1;
        end
    end
end

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

gtTotal = sum(cellfun(@(x)numel(x),gtVehicleBoundaryPoints));
nMiss   = gtTotal - nMatch;

precisionPlot = nMatch./(nMatch + nFP);
recallPlot    = nMatch./(nMatch + nMiss);

Постройте точность и вспомните метрики против различных значений порогового параметра силы маршрута. Этот график полезен в определении оптимального значения для параметра силы маршрута. Для этого видеоклипа, чтобы максимизировать метрики отзыва и точности, LaneStrengthThreshold должен быть в области значений 0.20 - 0.25.

figure;
plot(precisionPlot);
hold on;
plot(recallPlot);
xlabel('LaneStrengthThreshold*100');
ylabel('Precision and Recall');
legend('Precision','Recall');
title('Impact of LaneStrengthThreshold on Precision and Recall Metrics');

Поддерживание функции

Обнаружьте контуры в видео.

detectBoundaries использует предварительно сконфигурированный объект helperMonoSensor обнаружить контуры в видео.

function boundaries = detectBoundaries(videoName, monoSensor)
videoReader = VideoReader(videoName);
hwb         = waitbar(0,'Detecting and modeling boundaries in video...');
closeBar    = onCleanup(@()delete(hwb));
frameInd    = 0;
boundaries  = {};
while hasFrame(videoReader)
    frameInd  = frameInd+1;
    frame     = readFrame(videoReader);
    sensorOut = processFrame(monoSensor, frame);
    % Save the boundary models
    boundaries{end+1} =...
        [sensorOut.leftEgoBoundary, sensorOut.rightEgoBoundary];  %#ok<AGROW>
    waitbar(frameInd/(videoReader.Duration*videoReader.FrameRate), hwb);
end
end

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

Приложения

Функции

Похожие темы