主要内容

评估和可视化Lane Boundary detection Against Ground Truth

这个例子展示了如何评估车道边界检测的性能与已知的地面真值。在本例中,您将通过计算拟合度度量来描述每帧车道边界检测算法的性能。此度量可用于查明、可视化和理解底层算法中的故障模式。

概述

随着人们对基于视觉的自动驾驶问题解决方案越来越感兴趣,能够评估和验证检测算法的准确金宝搏官方网站性变得非常重要。对于具有多个参数的检测算法,验证准确性尤其重要,这些参数可以通过调整来实现满足预定义质量要求的结果。本例将介绍一个这样的工作流,其中可以测量车道边界的精度水平。这个工作流有助于在每帧的基础上确定这些算法中的故障模式,以及描述其总体性能。这个工作流还可以帮助您直观地和定量地理解算法的性能。然后,您可以使用这种理解来优化底层算法,以提高其性能。

负载地面真实数据

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

%加载MAT文件与地面真实数据。加载=负载(“caltech_cordova1_laneAndVehicleGroundTruth.mat”);

加载Structure包含三个字段:

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

  2. 传感器,一个monoCamera物体带有关于安装在车辆上的校准摄像机的属性。这个物体可以让你估计真实世界中车辆和前面物体之间的距离。

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

从该结构中的数据中,使用VideoReader循环遍历帧。的VideoReader对象使用一个helperMonoSensor物体检测车道和物体在视频帧,利用摄像机设置存储传感器.一个时间表变量存储在gtdata持有地面真实数据。这个变量包含稍后用于分析的每帧数据。

%创建一个VideoReader对象来读取视频帧。videoName = loaded.videoName;fileReader = VideoReader (videoName);地面真实数据被组织在一个时间表中。gtdata = loaded.groundTruthData;%显示地面真实数据的前几行。头(gtdata)
车辆LaneBoundaries ans = 8 x2时间表时间  ____________ ____________ ______________ 0秒{6 x4双}}{2 x1细胞0.033333秒{6 x4双}}{2 x1细胞0.066667秒{6 x4双}}{2 x1细胞0.1秒{6 x4双}}{2 x1细胞0.13333秒{6 x4双}}{2 x1细胞0.16667秒{6 x4双}}{2 x1细胞0.2秒{6 x4双}}{2 x1细胞0.23333秒{5 x4双}{2 x1细胞}

gtdata时间表有以下几列车辆LaneBoundaries.在每个时间戳中车辆列包含一个m × 4的车辆包围盒数组和LaneBoundaries列包含一个由左、右车道边界点组成的二元单元数组。

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

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

运行车道边界检测算法

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

%设置monoSensorHelper处理视频。monoCameraSensor = loaded.sensor;monoSensorHelper = helperMonoSensor (monoCameraSensor);用相同的时间矢量为测量创建新的时间表。测量=时间表(gtdata.Time);为保持车道边界和车辆数据设置时间表列。numFrames =地板(fileReader.FrameRate * fileReader.Duration);测量。LaneBoundaries = cell(numFrames, 2);测量。车辆检测= cell(numFrames, 1);gtdata。LanesInVehicleCoord = cell(numFrames, 2);%将视频倒带到t = 0,并创建一个帧索引来保持电流%框架。fileReader。CurrentTime = 0;frameIndex = 0;%循环播放视频文件,直到没有新的帧。hasFrame(fileReader) frameIndex = frameIndex+1;帧= readFrame (fileReader);%使用processFrame方法计算检测。%这个方法可以被一个自定义的车道检测方法代替。detections = processFrame(monoSensorHelper,帧);%存储估计的车道边界和车辆检测。测量。(detections.leftEgoBoundary LaneBoundaries {frameIndex} =...detections.rightEgoBoundary];测量。VehicleDetections {frameIndex} = detections.vehicleBoxes;%为了便于比较,转换地面真线指向%车辆坐标系。gtPointsThisFrame = gtdata.LaneBoundaries {frameIndex};车辆点数= cell(1, numel(gtpointthisframe));ii = 1:numel(gtPointsThisFrame) vehiclePoints{ii} = imageToVehicle(monocamerassensor, gtPointsThisFrame{ii});结束%存储以车辆坐标表示的地面真值点。gtdata。LanesInVehicleCoord {frameIndex} = vehiclePoints;结束

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

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

测量检测错误

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

你可以通过测量拟合的优度来估计这个精度。随着地面真值点和估计的计算,你现在可以比较和可视化它们,以找出检测算法的表现如何。

适合度可以在每帧水平或整个视频测量。每帧统计数据提供了关于特定场景的详细信息,比如在弯道处的行为,在这里检测算法的性能可能会有所不同。全球统计数据提供了错过检测的车道数量的大致估计。

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

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

阈值= 0.25;%在米[numMatches, numMisses, numFalsePositives, assignments] =...evaluateLaneBoundaries(测量。LaneBoundaries,...gtdata。LanesInVehicleCoord,...阈值);disp (['匹配数:'num2str (numMatches)]);disp ([“失误次数:”num2str (numMisses)]);disp ([“误报次数:”num2str (numFalsePositives)]);
匹配次数:409失败次数:36误报次数:27

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

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

可视化和回顾地面真相和你的算法之间的差异

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

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

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

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

%使用单相机计算估计的点位置。[estVehiclePoints, estImagePoints] = helpergetcordingpoints (monocamerassensor,...测量。LaneBoundaries,...gtdata。LanesInVehicleCoord,...作业);在测量时间表中增加估计车道。测量。EstimatedLanes = estImagePoints;测量。LanesInVehicleCoord = estVehiclePoints;%创建一个新的时间表,包含可视化所需的所有变量。名称= {“LanePoints”“DetectedLanePoints”};类型= labelType ({“行”“行”});= table(名称,类型,“VariableNames”, {“名字”“类型”});(gtdata visualizeInFrame =时间表。时间,...gtdata。LaneBoundaries,...测量。EstimatedLanes,...“VariableNames”、名称);创建groundTruth对象。数据源= groundTruthDataSource (videoName);dataToVisualize = groundTruth(dataSource, labelDefs, visualizeInFrame);%将上一节的所有结果保存到distanceData中。垫在%的临时文件夹。dataToLoad = [tempdir“distanceData.mat”];保存(dataToLoad,“monoSensorHelper”“videoName”“测量”“gtdata”“averageDistance”);

helperCustomUI类使用从MAT文件加载的数据创建绘图和鸟瞰视图,就像您刚才创建的那个。Ground Truth Labeler应用程序的Connector接口与helperCustomUI类通过helperUIConnector类同步视频与平均距离图和鸟瞰视图。这种同步使您能够分析每帧结果的分析和可视化。

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

  • 进入临时目录distanceData.mat,并打开Ground Truth Labeler应用程序。然后启动Ground Truth Labeler应用程序,连接器手柄指定为helperUIConnector使用以下命令:

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

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

> > cd (origdir)

从这个可视化中,您可以对算法和地面真实数据的质量做出几个推论。

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

  • 2.3秒和4秒左右的检测间隔对应于道路上有人行横道的十字路口。这表明该算法在存在人行横道的情况下性能不佳。

  • 大约6.8秒后,当车辆驶近第三个十字路口时,“自我车道”变成了只允许左转的车道和一条直道。在这里,算法也未能准确捕捉到左车道,地面真值数据也有5帧没有包含任何信息。

结论

这个例子展示了如何测量精度的车道边界检测算法和可视化它使用地面实况贴标签机你可以将这个概念扩展到其他自定义算法,以简化这些工作流程,并扩展应用程序的功能,用于自定义测量。

金宝app支持功能

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(1,1); / /设置帧长度idx = 1:长度(estModels {frameInd})%忽略假阳性分配。如果作业{frameInd} (idx) = = 0继续结束% estModelInFrame中的第k个边界匹配第k个边界%元素在gtPointsInFrame中被赋值索引。这种模式下= estModels {frameInd} (idx);thisGT = gtPoints {frameInd}{作业{frameInd} (idx)};thisGTModel = driving.internal.piecewiseLinearBoundary (thisGT);如果意味着(thisGTModel.Points (:, 2)) > 0%左车道xPoints = thisGTModel.Points (: 1);yDist = 0(大小(xPoints));index = 1:numel(xPoints) gtYPoints = thisGTModel.computeBoundaryModel(xPoints(index));testYPoints = thisModel.computeBoundaryModel (xPoints(指数));yDist(指数)= abs (testYPoints-gtYPoints);结束stat(frameInd, 1) = fcnHandle(yDist); / /删除帧其他的%右车道xPoints = thisGTModel.Points (: 1);yDist = 0(大小(xPoints));index = 1:numel(xPoints) gtYPoints = thisGTModel.computeBoundaryModel(xPoints(index));testYPoints = thisModel.computeBoundaryModel (xPoints(指数));yDist(指数)= abs (testYPoints-gtYPoints);结束stat(frameInd, 2) = fcnHandle(yDist); / /删除帧结束结束结束结束

helperGetCorrespondingPoints

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

函数[vehiclePoints, imagePoints] = helpergetcordingpoints (monocamerassensor, 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);vehiclePointsInFrame = cell(length(estModelInFrame), 1);idx = 1:长度(estModelInFrame)%忽略假阳性分配。如果imagePointsInFrame{idx} = [NaN NaN];继续结束% estModelInFrame中的第k个边界匹配第k个边界%元素在gtPointsInFrame中被赋值索引。这种模式下= estModelInFrame (idx);thisGT = gtPointsInFrame{作业{frameInd} (idx)};xPoints = thisGT(:, 1); / /点击这里yPoints = thisModel.computeBoundaryModel (xPoints);vehiclePointsInFrame{idx} = [xPoints, yPoints];imagePointsInFrame{idx} = vehicleToImage(monocamerassensor, [xPoints yPoints]);结束结束vehiclePoints {frameInd} = vehiclePointsInFrame;imagePoints {frameInd} = imagePointsInFrame;%使imagePoints[]而不是{}遵守groundTruth对象。如果isempty(imagePoints{frameInd}) imagePoints{frameInd} = [];结束如果isempty(vehiclePoints{frameInd}) vehiclePoints{frameInd} = [];结束结束结束

另请参阅

应用程序

功能

对象

相关的话题