主要内容

评估和可视化车道边界检测与地面真相

这个例子展示了如何根据已知的地面真相来评估车道边界检测的性能。在本例中,您将通过计算拟合优度度量,以每帧为基础描述车道边界检测算法的性能。这种度量可以用于精确定位、可视化和理解底层算法中的故障模式。

概述

随着人们对基于视觉的自动驾驶问题解决方案的兴趣日益浓厚,能够评估和验证检测算法的准确性变得非常重要。验证精度在检测算法中特别重要,检测算法有几个参数,可以调整以达到满足预定义质量要求的结果。该示例将介绍一个这样的工作流,其中可以测量车道边界的准确性水平。该工作流程有助于在每帧的基础上确定这些算法中的故障模式,并描述其总体性能。这个工作流程还可以帮助您直观和定量地理解算法的性能。然后,您可以使用这种理解来调优底层算法,以提高其性能。

加载地面真实数据

本例中使用的数据集是一个视频文件,来自一辆行驶在街道上的车辆的前置摄像头。车道边界的地面真相已经在视频上用地面真相标签应用程序手动标记,使用标记为“车道边界”的线ROI。这个视频是8秒,或250帧长。它有三个十字路口,几辆车(停车和行驶)和车道边界(双线,单线和虚线)。方法可为自己的视频创建地面实况车道边界数据集地面真相标签应用程序。

装载MAT文件与地面真相数据。装载的“caltech_cordova1_laneAndVehicleGroundTruth.mat”);

加载结构包含三个字段:

  1. groundTruthData,有两栏的时间表:LaneBoundaries而且车辆LaneBoundaries包含自我车道边界(左和右)的地面真值点,表示为XY点组成的单元格数组,形成一条poly线。车辆包含相机视图中车辆的地面真理边界框,表示为[x,y,宽度,高度]的m × 4数组。

  2. 传感器,一个monoCamera带有有关安装在车辆上的标定相机的属性的对象。这个物体可以让你估算车辆和前方物体之间的真实距离。

  3. videoName,一个字符数组,包含存储帧的视频的文件名。

从这个结构中的数据,通过使用打开视频文件VideoReader在帧之间循环。的VideoReader对象使用helperMonoSensor对象来检测视频帧中的车道和对象,使用存储在传感器.一个时间表存储在gtdata保存地面真相数据。此变量包含稍后用于分析的每帧数据。

创建一个VideoReader对象来读取视频的帧。videoName = loaded.videoName;fileReader = videereader (videoName);基本真相数据以时间表的形式组织。。gtdata = loaded.groundTruthData;显示地面真相数据的前几行。。头(gtdata)
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时间表有列车辆而且LaneBoundaries.在每个时间戳上,车辆列包含m × 4的车辆边界框数组和LaneBoundaries列包含左、右车道边界点的双元素单元格数组。

首先,可视化加载的图像帧的地面真相数据。

阅读视频的第一帧。frame = readFrame(fileReader);提取第一帧中的所有车道点。lanePoints = gtdata. laneborders {1};在第一帧提取车辆的包围盒。= gtdata.Vehicles{1};叠加右车道点和车辆边界框。帧= insertMarker(frame, lanePoints{2},“X”);帧= insertObjectAnnotation(帧,“矩形”vehicleBBox,“汽车”);显示第一帧的地面真实数据。图imshow(框架)

车道边界检测算法

使用视频帧和monoCamera参数,可以自动估计车道边界的位置。为了说明问题,processFrame的方法helperMonoSensor类在此用于检测车道边界(如parabolicLaneBoundary对象)和车辆(作为[x, y,宽度,高度]边界框矩阵)。就本例而言,这是测试中的车道边界检测“算法”。您可以使用相同的模式来评估自定义车道边界检测算法,其中processFrame替换为自定义检测功能。车辆坐标中的地面真值点也存储在LanesInVehicleCoord的列gtdata时间表。这样,它们就可以在随后的鸟瞰视图显示中可视化。首先,配置helperMonoSensor对象。传感器.的helperMonoSensor类组装运行车道边界检测算法所需的所有必要步骤。

设置monoSensorHelper来处理视频。monocamersensor = loaded.sensor;monoSensorHelper = helperMonoSensor(moncamersensor);为测量创建具有相同时间向量的新时间表。。measurements =时间表(gtdata.Time);设置时间表列,以保存车道边界和车辆数据。numFrames = floor(fileReader.FrameRate*fileReader.Duration);测量。laneborders = cell(numFrames, 2);测量。= cell(numFrames, 1);gtdata。LanesInVehicleCoord = cell(numFrames, 2);倒回视频到t = 0,并创建一个帧索引来保持当前%框架。fileReader。CurrentTime = 0;frameIndex = 0;循环视频文件,直到没有新的帧。hasFrame(fileReader) frameIndex = frameIndex+1;frame = readFrame(fileReader);使用processFrame方法计算检测。此方法可以替换为自定义车道检测方法。。检测= processFrame(monoSensorHelper, frame);存储估计的车道边界和车辆检测。。测量。laneborders {frameIndex} = [tests . leftegoboundary ....detections.rightEgoBoundary];测量。VehicleDetections{frameIndex} = tests . vehicleboxes;为便于比较,将地面真道点转换为%车辆坐标系统。gtPointsThisFrame = gtdata. laneborders {frameIndex};vehiclePoints = cell(1, numel(gtPointsThisFrame));ii = 1:numel(gtPointsThisFrame) vehiclePoints{ii} = imageToVehicle(monocamersensor, gtPointsThisFrame{ii});结束存储以车辆坐标表示的地面真值点。gtdata。LanesInVehicleCoord{frameIndex} = vehiclePoints;结束

现在,您已经使用车道检测算法处理了视频,验证地面真值点已正确转换为车辆坐标系。的第一个条目LanesInVehicleCoord的列gtdata时间表包含第一帧的车辆坐标。在鸟瞰视图的第一帧上绘制这些地面真相点。

倒回视频到t = 0。fileReader。CurrentTime = 0;阅读视频的第一帧。frame = readFrame(fileReader);birdsEyeImage = transformImage(monoSensorHelper.)BirdsEyeConfig,框架);在鸟瞰图中提取第一帧的右车道点。。firstFrameVehiclePoints = gtdata.LanesInVehicleCoord{1};pointsInBEV = vehicleToImage(monoSensorHelper.)BirdsEyeConfig, firstFrameVehiclePoints {2});在框架上叠加点。插入标记(birdsEyeImage, pointsInBEV,“X”“大小”6);%在鸟瞰视图中显示转换的点。图imshow (birdsEyeImage)

测量检测误差

车道边界检测误差的计算是验证多个下游子系统性能的重要步骤。这些子系统包括车道偏离预警系统,依赖于车道检测子系统的准确性。

你可以通过测量拟合优度来估计精确度。通过计算出的基本真值点和估计值,您现在可以对它们进行比较和可视化,以了解检测算法的性能如何。

拟合优度可以在每帧水平或整个视频中测量。每帧统计数据提供了关于特定场景的详细信息,例如在道路拐弯处的行为,在那里检测算法的性能可能会有所不同。全局统计数据提供了漏检车道数量的概貌估计。

使用evaluateLaneBoundaries函数返回全局检测统计信息作业数组中。该数组将估计的车道边界对象与相应的地面真值点进行匹配。

中的阈值参数evaluateLaneBoundaries函数表示车辆坐标中与估计抛物线车道边界匹配的最大横向距离。

阈值= 0.25;米%[numMatches, numMisses, numfalse positive, assignments] =...evaluateLaneBoundaries(测量。LaneBoundaries,...gtdata。LanesInVehicleCoord,...阈值);disp ([“比赛次数:”num2str (numMatches)]);disp ([“失误次数:”num2str (numMisses)]);disp ([“误报数量:”num2str (numFalsePositives)]);
匹配次数:402失误次数:43误报次数:30

使用作业数组中,您可以计算有用的每车道度量,例如估计值和地面真值点之间的平均横向距离。这些指标表明算法的执行情况。要计算平均距离度量,可以使用helper函数helperComputeLaneStatistics,在本例的最后定义。

averageDistance = helperComputeLaneStatistics(测量。LaneBoundaries,...gtdata。LanesInVehicleCoord,...作业,@mean);绘制估算值和实际情况之间的平均距离。。图阻止(gtdata。时间,averageDistance) title(“估算值与实际情况之间的平均距离”网格)ylabel (“以米为单位的距离”)传说(的左边界“右边界”)

可视化和回顾基本事实和你的算法之间的差异

现在,您对车道检测算法的准确性有了一个定量的了解。然而,仅根据前一节中的情节是不可能完全理解失败的。因此,查看视频并以每帧为基础可视化错误对于识别特定的故障模式是至关重要的,可以通过改进算法进行改进。

您可以使用Ground Truth Labeler应用程序作为可视化工具来查看包含地面真相数据和估计车道边界的视频。的driving.connector.Connector类提供了一个接口来将自定义可视化工具附加到Ground Truth Labeler。

使用parabolicLaneBoundary阵列和地面真实数据计算出车辆坐标位置的估计值点。的parabolicLaneBoundary数组定义一条线,地面真相数据有离散点标记在道路上。的helperGetCorrespondingPoints函数估计估计线上的点,这些点对应于与车辆相同的y轴距离。这个helper函数在示例的最后定义。

地面真值点和估计值点现在包含在一个新的时间表将在Ground Truth Labeler应用程序中可视化groundTruth对象然后存储为MAT文件。

使用monoCamera计算估计的点位置。[estVehiclePoints, estImagePoints] = helperget对应点(monocamersensor,...测量。LaneBoundaries,...gtdata。LanesInVehicleCoord,...作业);将估计的车道添加到测量时间表。。测量。EstimatedLanes = estImagePoints;测量。LanesInVehicleCoord = estVehiclePoints;用可视化所需的所有变量创建一个新的时间表。。Names = {“LanePoints”“DetectedLanePoints”};类型= labelType({“行”“行”});标签defs =表(名称,类型,“VariableNames”, {“名字”“类型”});visualizeInFrame = schedule (gtdata. visualizeInFrame)时间,...gtdata。LaneBoundaries,...测量。EstimatedLanes,...“VariableNames”、名称);创建groundTruth对象。数据源= groundTruthDataSource(videoName);datatovisualization = groundTruth(数据源,labelDefs, visualizeInFrame);将前一节的所有结果保存在distanceData中。垫子临时文件夹。dataToLoad = [tempdir .“distanceData.mat”];保存(dataToLoad,“monoSensorHelper”“videoName”“测量”“gtdata”“averageDistance”);

helperCustomUI类使用从MAT文件加载的数据创建情节和鸟瞰图,就像您刚刚创建的那个文件一样。地面真相标签应用程序的连接器接口与helperCustomUI类通过helperUIConnector类将视频与平均距离图和鸟瞰图同步。这种同步使您能够分析和可视化地分析每帧结果。

按照以下步骤将结果可视化,如下图所示:

  • 进入临时目录distanceData.mat然后启动Ground Truth Labeler应用程序,其中连接器句柄指定为helperUIConnector使用如下命令:

>> origdir = pwd;>> cd(tempdir) >> groundTruthLabeler(dataSource, >)“ConnectorTargetHandle”, @helperUIConnector);
  • 导入标签:在图像坐标中可视化地面真实车道标记和估计车道。在应用程序工具条中,单击进口标签.然后选择从工作空间选项并加载dataToVisualize应用程序的主窗口现在包含车道标记的注释。

现在您可以浏览视频并检查错误。要返回到原始目录,可以输入:

> > cd (origdir)

从这个可视化中,您可以对算法和地面真相数据的质量做出一些推断。

  • 左车道的准确性始终比右车道的准确性差。在鸟瞰图显示中仔细观察,地面真相数据被标记为双线的外边界,而估计的车道边界一般位于双线标记的中心。这表明左车道估计可能比数字描述的更准确,明确定义的地面真相数据集对这样的观察是至关重要的。

  • 2.3秒和4秒左右的检测间隔对应于前面有人行横道的十字路口。这表明算法在人行横道存在的情况下不能很好地执行。

  • 大约6.8秒后,当车辆驶近第三个十字路口时,自我车道分叉为一条左行车道和一条直行车道。在这里,算法也不能准确地捕获左车道,地面真相数据也不包含任何信息的五帧。

结论

该示例演示了如何测量车道边界检测算法的准确性,并使用地面真相标签您可以将这个概念扩展到其他自定义算法,以简化这些工作流,并扩展应用程序的自定义测量功能。

支持功能

helperComputeLaneStatistics

这个辅助函数计算车道边界检测的统计信息,与地面真值点进行比较。它接受一个函数句柄,可用于泛化需要计算的统计数据,包括@mean和@median。

函数stat = helperComputeLaneStatistics(estModels, gtPoints, assignments, fcnHandle) numFrames = length(estModels);默认情况下使左右估计NaN表示缺乏%的数据。stat = NaN*ones(numFrames, 2);frameInd = 1:numFrames%默认使左右估计NaN。stat(frameInd,:) = NaN*ones(2,1);idx = 1:length(estModels{frameInd})忽略假阳性作业。如果分配{frameInd}(idx) == 0继续结束estModelInFrame中的第k个边界与第k个边界匹配元素在gtPointsInFrame中被赋值索引。thisModel = estModels{frameInd}(idx);thisGT = getpoints {frameInd}{assignments{frameInd}(idx)};thisGT model = driving. inner . piecewiselinearboundary (thisGT);如果mean(thisGTModel.Points(:,2)) > 0左车道%xPoints = thisGTModel.Points(:,1);yDist = 0 (size(xPoints));index = 1:numel(xPoints) gtYPoints = thisGTModel.computeBoundaryModel(xPoints(index));testYPoints = thisModel.computeBoundaryModel(xPoints(index));yDist(index) = abs(testYPoints-gtYPoints);结束stat(frameInd, 1) = fcnHandle(yDist);其他的右车道%xPoints = thisGTModel.Points(:,1);yDist = 0 (size(xPoints));index = 1:numel(xPoints) gtYPoints = thisGTModel.computeBoundaryModel(xPoints(index));testYPoints = thisModel.computeBoundaryModel(xPoints(index));yDist(index) = abs(testYPoints-gtYPoints);结束stat(frameInd, 2) = fcnHandle(yDist);结束结束结束结束

helperGetCorrespondingPoints

这个辅助函数在x轴位置上创建匹配地面真值点的车辆和图像坐标点。

函数[vehiclePoints, imagePoints] = helperget对应点(monocamersensor, estModels, gtPoints, assignments) numFrames = length(estModels);imagePoints = cell(numFrames, 1);= cell(numFrames, 1);frameInd = 1:numFrames如果isempty(assignments{frameInd}) imagePointsInFrame = [];vehiclePointsInFrame = [];其他的estModelInFrame = estModels{frameInd};gtPointsInFrame = gtPoints{frameInd};imagePointsInFrame = cell(length(estModelInFrame), 1);= cell(length(estModelInFrame), 1);idx = 1:length(estModelInFrame)忽略假阳性作业。如果分配{frameInd}(idx) == 0 imagePointsInFrame{idx} = [NaN NaN];继续结束estModelInFrame中的第k个边界与第k个边界匹配元素在gtPointsInFrame中被赋值索引。thisModel = estModelInFrame(idx);thisGT = gtPointsInFrame{assignments{frameInd}(idx)};xPoints = thisGT(:, 1);yPoints = thisModel.computeBoundaryModel(xPoints);vehiclePointsInFrame{idx} = [xPoints, yPoints];imagePointsInFrame{idx} = vehicleToImage(monocamersensor, [xPoints yPoints]);结束结束vehiclePoints{frameInd} = vehiclePointsInFrame;imagePoints{frameInd} = imagePointsInFrame;使用imagePoints[]而不是{}来遵从groundTruth对象。如果isempty(imagePoints{frameInd}) imagePoints{frameInd} = [];结束如果isempty(vehiclePoints{frameInd}) vehiclePoints{frameInd} = [];结束结束结束

另请参阅

应用程序

功能

对象

相关的话题

Baidu
map