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

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

Обзор

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

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

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

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

Загрузите предопределенные ego-маршруты контуров заданные в координатах изображения. Каждый контур представлен набором M-by-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 модуль, представленный в примере Visual Perception Using Monocular Camera. При обработке видео необходим дополнительный шаг, чтобы вернуть обнаруженные краевые модели. Эта логика упакована в вспомогательную функцию, 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: 321
Number of misses: 124
Number of false positives: 25

Можно использовать эти необработанные счетчики для вычисления другой статистики, такой как точность, отзыв и 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.92775
Sensitivity/Recall: 0.72135
F1 score: 0.81163

Визуализация результатов с помощью графика птичьего глаза

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);

The LaneStrengthThreshold свойство helperMonoSensor управляет нормированным Strength параметр каждого parabolicLaneBoundary модель. Коэффициент нормализации, MaxLaneStrength, является силой виртуального маршрута, который проходит на всю длину изображения птичьего глаза. Это значение определяется исключительно birdsEyeView строение helperMonoSensor. Оценка влияния LaneStrengthThresholdсначала вычислите распределение нормализованных прочностей маршрута для всех обнаруженных контуров в видео выборки. Обратите внимание на наличие двух чистых peaks, один при нормализованной прочности 0,3 и один при 0,7. Эти два пика соответствуют штриховым и сплошным контурам маршрута соответственно. На основе этого графика можно эмпирически определить, что для обеспечения обнаружения контуров маршрута, 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);

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

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

См. также

Приложения

Функции

Похожие темы

Для просмотра документации необходимо авторизоваться на сайте