В этом примере показано, как разработать алгоритм автоматической маркировки границ полос в приложении Ground Truth Labeler.
Для разработки алгоритмов вождения и оценки их эффективности крайне важны достоверные данные. Однако создание богатого и разнообразного набора аннотированных данных о вождении требует значительного времени и ресурсов. Приложение Ground Truth Labeler делает этот процесс эффективным. Это приложение можно использовать в качестве полностью ручного инструмента аннотаций для разметки границ полос движения, границ транспортного средства и других объектов, представляющих интерес для системы технического зрения. Однако ручная маркировка требует значительного количества времени и ресурсов. Это приложение также предоставляет структуру для создания алгоритмов для расширения и автоматизации процесса маркировки. Можно использовать созданные алгоритмы для быстрой маркировки целых наборов данных, а затем выполнять ее с более эффективным и коротким шагом ручной проверки. Можно также отредактировать результаты этапа автоматизации, чтобы учесть сложные сценарии, которые алгоритм автоматизации мог пропустить. В этом примере описывается, как вставить алгоритм обнаружения полосы движения в рабочий процесс автоматизации приложения.
Сначала создайте алгоритм обнаружения полосы движения. Пример «Визуальное восприятие с помощью монокулярной камеры» описывает процесс обнаружения границ полосы движения и helperMonoSensor упаковывает этот алгоритм в один класс многократного использования. Опробуйте алгоритм на одном видеокадре, чтобы обнаружить левую границу полосы эго.
configData = load('birdsEyeConfig'); sensor = configData.birdsEyeConfig.Sensor; monoSensor = helperMonoSensor(sensor); I = imread('road.png'); sensorOut = processFrame(monoSensor, I); lb = sensorOut.leftEgoBoundary; figure IwithLane = insertLaneBoundary(I, lb, sensor, [3 30], 'Color', 'blue'); imshow(IwithLane); title('Detected Left Lane Boundary Model');

Полоса движения, обнаруженная на предыдущем шаге, является моделью и должна быть преобразована в набор дискретных точек. Эти точки аналогичны точкам, которые пользователь может поместить на изображение вручную. В виде камеры части границы полосы, расположенные ближе к транспортному средству (нижняя часть изображения с камеры), будут охватывать больше пикселей, чем последующие части. Следовательно, пользователь будет размещать больше точек с более высокой уверенностью в нижних частях изображения камеры. Чтобы воспроизвести это поведение, определите местоположения границ полосы движения из модели границ более плотно в точках ближе к транспортному средству.
ROI = [3 30]; xPoints = [3 3.5 4 5 7 12 30]'; % More dense closer to the vehicle yPoints = lb.computeBoundaryModel(xPoints); % Find corresponding image locations boundaryPointsOnImage = vehicleToImage(sensor, [xPoints, yPoints]); imshow(I) hold on plot(boundaryPointsOnImage(:,1), boundaryPointsOnImage(:,2),... 'o',... 'MarkerEdgeColor','b',... 'MarkerFaceColor','b',... 'MarkerSize',10) title('Automatically Marked Lane Boundary Points'); hold off

Чтобы включить этот алгоритм обнаружения полосы движения в процесс автоматизации приложения, создайте класс, который наследует от абстрактного базового класса vision.labeler.AutomationAlgorithm. Этот базовый класс определяет свойства и сигнатуры для методов, используемых приложением для настройки и запуска пользовательского алгоритма. Приложение Ground Truth Labeler предоставляет удобный способ получения начального шаблона класса автоматизации. Дополнительные сведения см. в разделе Создание алгоритма автоматизации для маркировки. AutoLaneMarking основан на этом шаблоне и предоставляет готовый к использованию класс автоматизации для обнаружения полос движения. Комментарии класса описывают основные шаги, необходимые для реализации каждого вызова API.
Шаг 1 содержит свойства, определяющие имя и описание алгоритма, а также направления использования алгоритма.
%---------------------------------------------------------------------- % Step 1: Define required properties describing the algorithm. This % includes Name, Description, and UserDirections. properties(Constant)
% Name: Give a name for your algorithm.
Name = 'Lane Detector';
% Description: Provide a one-line description for your algorithm.
Description = 'Automatically detect lane-like features';
% UserDirections: Provide a set of directions that are displayed
% when this algorithm is invoked. The directions
% are to be provided as a cell array of character
% vectors, with each element of the cell array
% representing a step in the list of directions.
UserDirections = {...
'Load a MonoCamera configuration object from the workspace using the settings panel',...
'Specify additional parameters in the settings panel',...
'Run the algorithm',...
'Manually inspect and modify results if needed'};
end
Шаг 2 содержит пользовательские свойства, необходимые для основного алгоритма. Необходимые свойства были определены по описанному выше разделу определения полосы движения и создания точки полосы движения.
%---------------------------------------------------------------------
% Step 2: Define properties to be used during the algorithm. These are
% user-defined properties that can be defined to manage algorithm
% execution.
properties
%MonoCamera
% The monoCamera object associated with this video
MonoCamera = [];
%MonoCameraVarname
% The workspace variable name of the monoCamera object
MonoCameraVarname = '';
%BirdsEyeConfig
% The birdsEyeView object needed to create the bird's-eye view
BirdsEyeConfig = [];
%MaxNumLanes
% The maximum number of lanes the algorithm tries to annotate
MaxNumLanes = 2;
%ROI
% The region of interest around the vehicle used to search for
% lanes
ROI = [3, 30, -3, 3];
%LaneMaskSensitivity
% The sensitivity parameter used in the segmentLaneMarkerRidge function
LaneMaskSensitivity = 0.25;
%LaneBoundaryWidth
% The lane boundary width, used in findParabolicLaneBoundaries
LaneBoundaryWidth = 0.6;
%XPoints
% The x-axis points along which to mark the lane boundaries
XPoints = [3 3.5 4 4.5 5 6 7 10 30];
end
На шаге 3 рассматриваются определения функций. Первая функция, checkLabelDefinitionобеспечивает возможность автоматизации только меток соответствующего типа. Для обнаружения полос движения необходимо убедиться, что только метки типа Line включены, поэтому эта версия функции проверяет Type меток:
function TF = checkLabelDefinition(~, labelDef)
% Lane detection only works with Line type labels
TF = labelDef.Type == labelType.Line;
end
Следующая функция - checkSetup. Обратите внимание, что этот алгоритм требует monoCamera должна быть доступна конфигурация датчика. Для всех других свойств определены разумные значения по умолчанию.
function TF = checkSetup(algObj, ~)
% This is the only required input
TF = ~isempty(algObj.MonoCamera);
end
Далее, settingsDialog функция получает и модифицирует свойства, определенные на этапе 2. Этот вызов API позволяет создать диалоговое окно, которое открывается при нажатии пользователем кнопки «Параметры» на вкладке «Автоматизация». Чтобы создать это диалоговое окно, используйте inputdlg функция для быстрого создания простого модального окна, чтобы попросить пользователя указать monoCamera объект. Следующий фрагмент кода описывает основной синтаксис. Полное AutoLaneMarking код расширяет эту логику, а также добавляет шаги проверки ввода.
% Describe the inputs
prompt = {...
'Enter the MonoCamera variable name',...
'Maximum number of Lanes',...
};
defaultAnswer = {...
'',...
num2str(2),...
};
% Create an input dialog name = 'Settings for lane detection'; numLines = 1; options.Resize = 'on'; options.WindowStyle = 'normal'; options.Interpreter = 'none'; answer = inputdlg(prompt,name,numLines,defaultAnswer,options);
% Obtain the inputs
monoCameraVarname = answer{1};
maxNumberOfLanes = answer{2};
Шаг 4 определяет функции выполнения. Некоторые алгоритмы автоматизации должны реализовывать initialize процедура заполнения начального состояния алгоритма на основе существующих меток в приложении. Этот алгоритм обнаружения полосы работает на каждом кадре независимо, поэтому версия шаблона по умолчанию была обрезана, чтобы не предпринимать никаких действий.
function initialize(~, ~, ~)
end
Далее, run функция определяет алгоритм обнаружения основной полосы данного класса автоматизации. run получает вызов для каждого видеокадра и ожидает, что класс автоматизации вернет набор меток. run функция в AutoLaneMarking содержит логику, введенную ранее для обнаружения полосы движения и преобразования в точки. Код от helperMonoSensor был также сложен для более компактной ссылки.
function autoLabels = run(algObj, I)
Ig = im2gray(I);
birdsEyeViewImage = transformImage(algObj.BirdsEyeConfig, Ig);
birdsEyeViewBW = segmentLaneMarkerRidge(birdsEyeViewImage, ...
algObj.BirdsEyeConfig, algObj.LaneBoundaryWidth, ...
'Sensitivity', algObj.LaneMaskSensitivity);
% Obtain lane candidate points in world coordinates
[imageX, imageY] = find(birdsEyeViewBW);
boundaryPointsxy = imageToVehicle(algObj.BirdsEyeConfig, [imageY, imageX]);
% Fit requested number of boundaries to it
lbs = findParabolicLaneBoundaries(...
boundaryPointsxy,algObj.LaneBoundaryWidth, ...
'MaxNumBoundaries',algObj.MaxNumLanes);
numDetectedLanes = numel(lbs);
% Convert the model to discrete set of points at the specified
% x coordinates
boundaryPoints = cell(1,numDetectedLanes);
xPoints = algObj.XPoints';
for ind = 1:numel(lbs)
yPoints = lbs(ind).computeBoundaryModel(xPoints);
boundaryPoints{ind} = vehicleToImage(algObj.MonoCamera, [xPoints, yPoints]);
end
% Package up the results in a table
autoLabels = table(...
boundaryPoints',...
repmat(labelType.Line, [numDetectedLanes,1]),...
repmat(algObj.SelectedLabelDefinitions.Name, [numDetectedLanes,1]));
autoLabels.Properties.VariableNames = {'Position','Type','Name'};
end
Наконец, terminate функция обрабатывает любую очистку или разрыв, необходимые после выполнения автоматизации. Этот алгоритм не требует никакой очистки, поэтому функция пуста.
function terminate(~)
end
Упакованная версия алгоритма обнаружения полосы теперь готова к использованию в AutoLaneMarking класс. Чтобы использовать этот класс в приложении:
Создайте структуру папок, необходимую для текущей папки, и скопируйте в нее класс автоматизации.
mkdir('+vision/+labeler');
copyfile(fullfile(matlabroot,'toolbox','driving','drivingdemos','AutoLaneMarking.m'),'+vision/+labeler');
Загрузить monoCamera информация в рабочую область.
configData = load('birdsEyeConfig');
sensor = configData.birdsEyeConfig.Sensor;
Откройте приложение Ground Truth Labeler.
groundTruthLabeler caltech_cordova1.avi
На левой панели нажмите кнопку Define new ROI label и определите отображаемый стиль строки ROI. Затем нажмите кнопку ОК.

Щелкните Алгоритм > Выбрать алгоритм > Обновить список.
Щелкните Алгоритм (Algorithm) > Автоматическое определение полосы движения (Auto Lane Detection). Если этот параметр не отображается, убедитесь, что текущая рабочая папка содержит папку с именем +vision/+labeler, с именем файла AutoLaneMarking.m в этом.

Щелкните Автоматизировать (Automate). Откроется новая вкладка, отображающая направления использования алгоритма.
Нажмите «Параметры» и в открывшемся диалоговом окне введите sensor в первом текстовом поле. При необходимости измените другие параметры, прежде чем нажать кнопку ОК.

Щелкните Выполнить (Run). Алгоритм обнаружения полосы продвигается на видео. Обратите внимание, что результаты в некоторых кадрах неудовлетворительны.
После завершения выполнения используйте ползунок или клавиши со стрелками для прокрутки видео, чтобы найти кадры, в которых произошел сбой алгоритма.

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

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