本讲展示了如何在Ground Truth Labeler应用程序中开发自动标记车道边界的算法。
良好的地面真实数据对于开发驾驶算法和评估其性能至关重要。然而,创建一套丰富多样的标注驾驶数据需要大量的时间和资源。Ground Truth Labeler应用程序使这一过程变得高效。可以将该应用作为一个完全手动的标注工具,为视觉系统标注车道边界、车辆边界框和其他感兴趣的对象。然而,手动标注需要大量的时间和资源。这款应用程序还提供了一个框架来创建算法,以扩展和自动化标签过程。可以使用创建的算法来快速标记整个数据集,然后用更高效、更短的手动验证步骤进行跟进。还可以编辑自动化步骤的结果,以说明自动化算法可能遗漏的挑战性场景。本示例介绍了如何将车道检测算法插入到应用程序的自动化工作流程中。
3.1 创建车道检测算法
首先,创建一个车道检测算法。使用单目摄像头的视觉感知示例描述了检测车道边界的过程,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('DetectedLeft Lane BoundaryModel');
3.2 标记边界点
上一步中检测到的车道是一个模型,必须转换为一组离散的点。这些点类似于用户可能手动放置在图像上的点。在摄像机视图中,车道边界中更靠近车辆的部分(摄像机图像的下部)将比更远的部分跨越更多的像素。因此,用户会将更多的点以更高的置信度放置在相机图像的较低部分。为了复制这种行为,从边界模型中确定车道边界位置,在更靠近车辆的点上更加密集。
ROI = [3 30];
xPoints = [3 3.5 4 5 7 12 30]'; % Moredense closer to the vehicle
yPoints = lb.computeBoundaryModel(xPoints);
% Findcorresponding image locations
boundaryPointsOnImage= vehicleToImage(sensor, [xPoints, yPoints]);
imshow(I)
hold on
plot(boundaryPointsOnImage(:,1),boundaryPointsOnImage(:,2),...
'o',...
'MarkerEdgeColor','b',...
'MarkerFaceColor','b',...
'MarkerSize',10)
title('AutomaticallyMarked Lane Boundary Points');
hold off
3.3 准备车道检测自动化类
要将这个车道检测算法纳入到应用程序的自动化工作流程中,请构造一个继承自抽象基类 vision.labeleler.AutomationAlgorithm的类。这个基类为应用程序用于配置和运行自定义算法的方法定义了属性和签名。GroundTruth Labeler 应用程序提供了一种获取初始自动化类模板的便捷方法。AutoLaneMarking类基于该模板,提供了一个用于车道检测的即用型自动化类。该类的注释概述了实现每个API调用所需的基本步骤。 步骤1包含定义算法名称和描述的属性,以及使用算法的方向。
%----------------------------------------------------------------------
% Step 1: Define required propertiesdescribing the algorithm. This
% includes Name, Description, and UserDirections.
properties(Constant)
% Name: Give a name for your algorithm.
Name = 'LaneDetector';
% Description: Provide a one-linedescription for your algorithm.
Description = 'Automatically detect lane-like features';
% UserDirections: Provide a set of directions that are displayed
% when this algorithm isinvoked. The directions
% are to be provided as a cellarray of character
% vectors, with each element of the cell array
% representing a step in thelist of directions.
UserDirections = {...
'Load a MonoCamera configurationobject from the workspace using the settings panel',...
'Specify additional parameters in thesettings panel',...
'Run the algorithm',...
'Manually inspect and modify resultsif needed'};
end
步骤2包含核心算法所需的自定义属性。必要的属性由上面的车道检测和车道点创建部分确定。
%---------------------------------------------------------------------
% Step 2: Defineproperties to be used during the algorithm. These are
% user-definedproperties that can be defined to manage algorithm
% execution.
properties
%MonoCamera
% The monoCamera object associated with thisvideo
MonoCamera = [];
%MonoCameraVarname
% The workspace variable name of the monoCamera object
MonoCameraVarname = '';
%BirdsEyeConfig
% The birdsEyeView object needed to create thebird's-eye view
BirdsEyeConfig = [];
%MaxNumLanes
% The maximum number of lanes the algorithmtries to annotate
MaxNumLanes = 2;
%ROI
% The region ofinterest around the vehicle used to search for
% lanes
ROI = [3, 30, -3, 3];
%LaneMaskSensitivity
% The sensitivity parameter used in thesegmentLaneMarkerRidge function
LaneMaskSensitivity= 0.25;
%LaneBoundaryWidth
% The laneboundary width, used infindParabolicLaneBoundaries
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的标签,所以这个版本的函数检查标签的类型:
function TF = checkLabelDefinition(~,labelDef)
% Lanedetection only works with Line type labels
TF =labelDef.Type == labelType.Line;
end
The next functionis checkSetup. Note that this algorithm requires a monoCamera sensor configuration to be available.All other properties have defined reasonable defaults.
function TF = checkSetup(algObj, ~)
% This is the only required input
TF = ~isempty(algObj.MonoCamera);
end
接下来,settingsDialog函数将获取并修改步骤2中定义的属性。通过该 API 调用,您可以创建一个对话框,当用户点击自动选项卡中的设置按钮时,该对话框就会打开。要创建这个对话框,请使用 inputdlg 函数快速创建一个简单的模态窗口,要求用户指定 monoCamera 对象。以下代码片段概述了基本语法。完整的AutoLaneMarking代码扩展了这一逻辑,还增加了输入验证步骤。
% Describethe 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};
第四步指定执行函数。一些自动化算法需要实现一个初始化例程,根据应用中现有的标签来填充初始算法状态。这个车道检测算法在每一帧上都是独立工作的,所以默认版本的模板已经被修剪成不采取任何行动:
function initialize(~,~, ~)
end
接下来,run函数定义了这个自动化类的核心车道检测算法,每个视频帧都会调用run,并期望自动化类返回一组标签。AutoLaneMarking中的run函数包含了之前介绍的车道检测和转换为点的逻辑。helperMonoSensor中的代码也被折叠进来,以便更紧凑的参考。
functionautoLabels = run(algObj, I)
Ig = rgb2gray(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 boundariesto 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
最后,终止函数处理自动化完成后所需的任何清理或拆除。该算法不需要任何清理,所以该函数为空。
function terminate(~)
end
3.4 在App中使用AutoLaneMarking自动化类
车道检测算法的打包版本现在已经可以在AutoLaneMarking类中使用。要在应用中使用这个类。 --在当前文件夹下创建所需的文件夹结构,并将自动化类复制到其中。
mkdir('+vision/+labeler');
copyfile(fullfile(matlabroot,'toolbox','driving','drivingdemos','AutoLaneMarking.m'),'+vision/+labeler');
--将monoCamera信息加载到工作区。
configData =load('birdsEyeConfig');
sensor = configData.birdsEyeConfig.Sensor;
--打开 "地面真值标签机 "应用。
groundTruthLabelercaltech_cordova1.avi
在左侧窗格中,单击 "定义新的投资回报率标签 "按钮,并定义所示的投资回报率线样式。然后单击 "确定"。
- 点击算法 > 选择算法 > 刷新列表。- 点击 "算法">"自动车道检测"。如果没有看到这个选项,请确保当前工作文件夹中有一个名为+vision/+labeler的文件夹,其中有一个名为AutoLaneMarking.m的文件。
- 单击Automate(自动)。将打开一个新的标签,显示算法的使用方向。- 点击设置,在打开的对话框中,在第一个文本框中输入传感器。如果需要,请修改其他参数,然后再单击 "确定"。
- 单击 "运行"。车道检测算法在视频上进行。注意,在某些帧中,结果并不令人满意。- 运行完成后,使用滑块或方向键滚动整个视频,以定位算法失败的帧。
- 通过移动车道边界点或删除整个边界,手动调整结果。
- 一旦对整个视频的车道边界感到满意,请单击 "接受"。标记视频的自动车道检测部分已经完成。可以继续标记其他感兴趣的对象,保存会话,或导出本次标记运行的结果。
3.5 总结
这个例子展示了将车道检测算法纳入Ground Truth Labeler应用程序的步骤。可以将此概念扩展到其他自定义算法,以简化和扩展应用程序的功能。