主要内容

评估车道边界检测与地面真实数据

这个例子展示了如何比较地面真实数据与车道边界检测算法的结果。它还说明了如何使用这种比较来调整算法参数,以获得最佳的检测结果。

概述

地面真实数据通常在图像坐标中可用,而边界是在车辆坐标系统中建模的。比较两者涉及坐标转换,因此在解释结果时需要格外小心。驾驶决策是基于车辆坐标系统中的距离。因此,使用车辆坐标中的物理单位而不是像素坐标来表达和理解精度要求更有用。

MonoCameraExample介绍了单目摄像机传感器的内部结构和车道边界建模的过程。这个例子展示了如何评估这些模型的准确性与人工验证的地面真实数据。在建立了比较框架后,将该框架扩展到对边界检测算法的参数进行微调以获得最优性能。

装载和准备地面真实数据

你可以使用地面实况贴标签机在视频中标记和标记车道边界的应用程序。这些带注释的车道边界表示为沿着感兴趣的边界放置的点集。在评估和微调自动车道边界检测算法时,拥有一套丰富的人工注释车道边界用于各种驾驶场景是至关重要的。为caltech_cordova1.avi视频文件是可用的工具箱。

加载在图像坐标中指定的预定义的左和右自我车道边界。每个边界由一组M × 2的数字表示,这些数字表示沿边界的M个像素位置。每个视频帧最多有两个这样的集合,代表左车道和右车道。

加载=负载(“caltech_cordova1_EgoBoundaries.mat”);传感器= loaded.sensor;关联的moncamera对象gtImageBoundaryPoints = loaded.groundTruthData.EgoLaneBoundaries;在此帧索引处显示一个地面真实值的样本frameInd = 36;%加载视频帧frameTimeStamp =秒(loaded.groundTruthData (frameInd:) .Time);videoReader = videoReader (loaded.videoName);videoReader。CurrentTime = frameTimeStamp;帧= videoReader.readFrame ();%获得这一帧的左车道点boundaryPoints = gtImageBoundaryPoints {frameInd};leftLanePoints = boundaryPoints {1};图imshow(帧)情节(leftLanePoints (: 1) leftLanePoints (:, 2),“+”“MarkerSize”10“线宽”4);标题(“左车道边界地面真实数据样本”);

将地面真值点从图像坐标转换为车辆坐标,以便与边界模型进行直接比较。要执行此转换,请使用imageToVehicle函数与关联的monoCamera对象以执行此转换。

gtVehicleBoundaryPoints =细胞(元素个数(gtImageBoundaryPoints), 1);frameInd = 1:numel(gtImageBoundaryPoints);如果ptsinvevehicle = cell(1, numel(boundaryPoints));ptsvehicle {cInd} = imageToVehicle(sensor, boundaryPoints{cInd});结束gtVehicleBoundaryPoints {frameInd} = ptsInVehicle;结束结束

使用单目传感器模型车道边界

对样本视频运行车道边界建模算法,获取测试数据进行对比。在这里,重用helperMonoSensor模块中引入的单目相机的视觉感知的例子。在处理视频时,需要额外的一步来返回检测到的边界模型。这个逻辑被包装在一个辅助函数中,detectBoundaries,在本例的最后定义。

monoSensor = helperMonoSensor(传感器);边界= detectBoundaries(加载。videoName monoSensor);

评价车道边界模型

使用evaluateLaneBoundaries函数查找与地面真理中边界匹配的边界数。只有当地面真值的所有点都在与相应的测试边界的指定距离内时,地面真值才被分配到测试边界。如果多个地面真值边界满足此准则,则选择横向距离最大的最小边界。其他的被标记为假阳性。

阈值= 0.25;%(车辆坐标)(米)[numMatches, numMisses, numFalsePositives, assignments] =...evaluateLaneBoundaries(边界,gtVehicleBoundaryPoints,阈值);disp (['匹配数:'num2str (numMatches)]);disp ([“失误次数:”num2str (numMisses)]);disp ([“误报次数:”num2str (numFalsePositives)]);
匹配次数:409失败次数:36误报次数:27

您可以使用这些原始计数来计算其他统计数据,如精度、召回率和F1分数:

精度= numMatches / (numMatches + numFalsePositives);disp ([的精度:num2str(精密)]);回忆= numMatches / (numMatches + numMisses);disp ([的灵敏度/回忆:num2str(召回)]);f1Score = 2 *(精度*召回)/(精度+回忆);disp ([的F1分数:num2str (f1Score)]);
准确度:0.93807灵敏度/召回:0.9191 F1评分:0.92849

使用鸟瞰图可视化结果

evaluateLaneBoundaries另外,返回地面真实值和测试边界之间每一次成功匹配的赋值索引。这可以用来可视化检测和地面真实边界,以更好地理解失效模式。

找到一个有一个匹配边界和一个假阳性的帧。每一帧的地面真值数据都有两个边界。因此,一个候选框架将有两个赋值指标,其中一个为0表示假阳性。

hasMatch = cellfun(@(x)numel(x)==2,赋值);hasfalse = cellfun(@(x)nnz(x)==1,赋值);frameInd =找到(hasMatch&hasFalsePositive 1“第一”);frameVehiclePoints = gtVehicleBoundaryPoints {frameInd};frameImagePoints = gtImageBoundaryPoints {frameInd};frameModels = {frameInd}边界;

使用作业的输出evaluateLaneBoundaries找到匹配(真阳性)的模型和不匹配(假阳性)的模型。

matchedModels = frameModels(作业{frameInd} ~ = 0);fpModels = frameModels(作业{frameInd} = = 0);

建立一个鸟瞰图,并在上面可视化地面真实点和模型。

cep = birdsEyePlot ();gtPlotter = laneBoundaryPlotter (cep),“DisplayName的”“地面实况”...“颜色”“蓝”);tpPlotter = laneBoundaryPlotter (cep),“DisplayName的”“真阳性”...“颜色”“绿色”);fpPlotter = laneBoundaryPlotter (cep),“DisplayName的”“假阳性”...“颜色”“红色”);plotLaneBoundary (gtPlotter frameVehiclePoints);plotLaneBoundary (tpPlotter matchedModels);plotLaneBoundary (fpPlotter fpModels);标题(“鸟眼对比结果图”);

可视化结果在摄像机和鸟瞰图的视频

为了获得更好的结果背景,您还可以在视频上可视化地面真值点和边界模型。

得到与感兴趣的坐标系对应的坐标系。

videoReader = videoReader (loaded.videoName);videoReader。CurrentTime =秒(loaded.groundTruthData.Time (frameInd));帧= videoReader.readFrame ();

将边界模型考虑为实线(不管传感器如何对其进行分类)以实现可视化。

fpModels。BoundaryType =“固体”;matchedModels。BoundaryType =“固体”

插入匹配的模型,假阳性和地面真值点。这幅图有助于推断人行横道的存在给边界建模算法带来了挑战。

xVehicle = 3;frame = insertLaneBoundary(frame, fpModels, sensor, xVehicle,“颜色”“红色”);frame = insertLaneBoundary(frame, matchedModels, sensor, xVehicle,“颜色”“绿色”);图ha =轴;imshow(帧,“父”,哈);%合并左右边界点boundaryPoints = [frameImagePoints {1}; frameImagePoints {2});持有情节(哈,boundaryPoints (: 1), boundaryPoints (:, 2),“+”“MarkerSize”10“线宽”4);标题(“对比结果的相机视图”);

你也可以在这个框架的鸟瞰视图中可视化结果。

birdsEyeImage = transformImage (monoSensor.BirdsEyeConfig,框架);xVehicle = 3;birdsEyeImage = insertLaneBoundary(birdsEyeImage, fpModels, monoSensor。BirdsEyeConfig xVehicle,“颜色”“红色”);birdsEyeImage = insertLaneBoundary(birdsEyeImage, matchedModels, monoSensor.)BirdsEyeConfig xVehicle,“颜色”“绿色”);%合并左右边界点ptsInVehicle = [frameVehiclePoints {1}; frameVehiclePoints {2});gtPointsInBEV = vehicleToImage (monoSensor。BirdsEyeConfig ptsInVehicle);图imshow (birdsEyeImage);持有情节(gtPointsInBEV (: 1) gtPointsInBEV (:, 2),“+”“MarkerSize”10“线宽”4);标题(“对比结果的鸟瞰图”);

Tune边界建模参数

您可以使用前面描述的评估框架来微调车道边界检测算法的参数。helperMonoSensor公开了控制寻道算法结果的三个参数。

  • LaneSegmentationSensitivity-控制的灵敏度segmentLaneMarkerRidge函数。这个函数以二进制车道特征掩码的形式返回车道候选点。灵敏度值从0到1不等,默认值为0.25。增加这个数字会导致更多的车道候选点和潜在的更多的错误检测。

  • LaneXExtentThreshold—指定车道的最小范围(长度)。它表示为检测到的车道长度与指定摄像头配置的最大车道长度的比值。默认值为0.4。增加这个数字以拒绝更短的车道边界。

  • LaneStrengthThreshold-指定接受检测到的车道边界的最小标准化强度。

LaneXExtentThresholdLaneStrengthThreshold都是由XExtent强度的属性parabolicLaneBoundary对象。这些属性是如何对边界建模算法施加额外约束以获得可接受结果的一个例子。变化的影响LaneStrengthThreshold有额外的细微差别值得探索。典型的车道边界是用实线或虚线标记的。当与实线相比,虚线有更少的嵌入点,导致更低的强度值。这使得设定一个共同的力量阈值变得很有挑战性。要检查此参数的影响,首先通过设置生成所有边界LaneStrengthThreshold为0。此设置确保它不会对输出产生影响。

monoSensor。LaneStrengthThreshold = 0;边界= detectBoundaries (“caltech_cordova1.avi”, monoSensor);

LaneStrengthThreshold的属性helperMonoSensor控制规范化强度参数的parabolicLaneBoundary模型。归一化因子,MaxLaneStrength,是一个虚拟车道的强度,它运行到鸟瞰图的全部范围。该值仅由birdsEyeView的配置helperMonoSensor.评估…的影响LaneStrengthThreshold,首先计算样本视频中所有检测到的边界归一化车道强度的分布。注意到有两个明显的峰,一个在归一化强度为0.3,一个在0.7。这两个峰值分别对应虚线和实线边界。从这个情节中,您可以凭经验确定,为了确保检测到虚线车道边界,LaneStrengthThreshold应低于0.3。

优势= cellfun (@ (b) (b。强度),边界,“UniformOutput”、假);优势=(优势{:});normalizedStrengths = / monoSensor.MaxLaneStrength优势;图;嘘(normalizedStrengths);标题(“归一化车道强度直方图”);

您可以使用比较框架进一步评估的影响LaneStrengthThreshold参数对建模算法的检测性能的影响。请注意,阈值控制模型与地面真实之间最大物理距离的值保持不变。该值由ADAS系统的精度要求决定,通常不会改变。

阈值=升至;[~, ~, ~, assignments] =...evaluateLaneBoundaries(边界,gtVehicleBoundaryPoints,阈值);

根据其归一化强度对每个边界进行分类。的作业信息有助于将每个边界划分为真阳性(匹配)或假阳性。LaneStrengthThreshold是一个“最小”阈值,因此在给定值被分类为真正的边界对于所有更低的阈值仍然是真正的。

nMatch = 0 (1100);归一化车道强度被装入100个桶中nFP = 0 (1100);%,范围为0.01 ~ 1.00。frameInd = 1:numel(boundaries) frameBoundaries = boundaries{frameInd};frameAssignment =作业{frameInd};bInd = 1:numel(frameBoundaries) normalizedStrength = frameBoundaries(bInd).Strength/ monosensor . maxlaneststrength;strengthBucket =地板(normalizedStrength * 100);如果frameAssignment(绑定)这个边界与地面真理边界相匹配,%记录为以上所有力量值的真正值%它的强度值。nMatch (1: strengthBucket) = nMatch (1: strengthBucket) + 1;其他的这是误报nFP临界多边形求解(1:strengthBucket) = (1: strengthBucket) + 1;结束结束结束

使用此信息来计算“错过”边界的数量,即算法在指定位置未能检测到的地面真值边界LaneStrengthThreshold价值。有了这些信息,计算出精确度和召回指标。

gtTotal =总和(cellfun (@ (x)元素个数(x) gtVehicleBoundaryPoints));nMiss = gtTotal - nMatch;precisionPlot = nMatch。/(临界多边形求解nMatch +);recallPlot = nMatch。/ (nMatch + nMiss);

根据车道强度阈值参数的不同值绘制精度和召回指标。此图可用于确定巷道强度参数的最优值。对于这个视频剪辑,为了最大限度地提高召回率和精确度,LaneStrengthThreshold应该在0.20 - 0.25的范围内。

图;情节(precisionPlot);持有;情节(recallPlot);包含(“LaneStrengthThreshold * 100”);ylabel (的精度和召回);传奇(“精度”“回忆”);标题(“laneststrength阈值对精度和召回指标的影响”);

金宝app支持函数

检测视频中的边界。

detectBoundaries使用一个预先配置的helperMonoSensor对象来检测视频中的边界。

函数边界= detectBoundaries(videoName, monoSensor) videreader = videoReader (videoName);hwb = waitbar (0,“在视频中检测和建模边界……”);closeBar = onCleanup(@()删除(hwb));frameInd = 0;边界= {};hasFrame(videreader) frameInd = frameInd+1; / /设置帧id帧= readFrame (videoReader);sensorOut = processFrame(monoSensor, frame);%保存边界模型{结束+ 1}=边界...[sensorOut。leftEgoBoundary sensorOut.rightEgoBoundary);% #好< AGROW >waitbar (frameInd / (videoReader.Duration * videoReader.FrameRate), hwb);结束结束

另请参阅

应用程序

功能

相关的话题