主要内容

单目摄像机的视觉感知

这个例子展示了如何构建一个单目摄像机传感器仿真能够车道边界和车辆检测。传感器将在车辆坐标系中报告这些检测结果。在本例中,您将了解自动驾驶工具箱™使用的坐标系统,以及设计样本单目摄像机传感器所涉及的计算机视觉技术。

概述

包含ADAS功能或设计成完全自动驾驶的车辆依赖于多个传感器。这些传感器可以包括声纳、雷达、激光雷达和摄像机。这个例子说明了设计单目摄像机系统所涉及的一些概念。这种传感器可以完成许多任务,包括:

  • 车道边界检测

  • 车辆、人员和其他物体的检测

  • 估计自我车辆到障碍物的距离

随后,单目摄像头传感器返回的读数可用于发出车道偏离警告、碰撞警告,或设计车道保持辅助控制系统。与其他传感器一起,它也可以用来实现紧急制动系统和其他安全关键功能。

该示例实现了完全开发的单目相机系统上的功能子集。它检测车道边界和车辆后部,并报告它们在车辆坐标系中的位置。

定义摄像机的配置

了解相机的内部和外部标定参数对像素和车辆坐标的精确转换至关重要。

首先定义相机的内在参数。下面的参数是早先使用使用棋盘式校准模式的摄像机校准程序确定的。你可以使用相机校准器应用程序获取它们为您的相机。

focalLength = [309.4362, 344.2161];%[fx,fy]以像素为单位principalPoint = [318.9034, 257.5352];%[cx,cy]像素坐标中的光学中心imageSize = [480,640];% (nrows, mcols)

注意,透镜畸变系数被忽略了,因为在数据中有很小的畸变。参数存储在cameraIntrinsics对象

camIntrinsics=cameraIntrinsics(焦距、主点、图像大小);

接下来,定义相对于车辆底盘的摄像机方向。您将使用这些信息来建立摄像机外部信息,定义3d摄像机坐标系相对于车辆坐标系的位置。

身高= 2.1798;%安装高度,以米为单位距= 14;相机的角度百分比

的返回的旋转和平移矩阵可以推导出上述量外在函数。俯仰指定摄像机从水平位置的倾斜。对于本例中使用的摄像机,传感器的滚转和偏航均为零。定义intrinsics和extrinsics的整个配置存储在单眼对象

传感器= moncamera (camIntrinsics, height,“节”、沥青);

请注意单眼对象建立了一个非常特殊的车辆坐标系统X-轴指向车辆前方Y-轴指向车辆的左侧,而Z轴指向地面。

默认情况下,坐标系统的原点在地面上,直接位于由相机焦点定义的相机中心的下方。原点可以通过使用传感器定位财产的单眼反对。此外,单眼提供成像车vehicleToImage在图像和车辆坐标系统之间转换的方法。

注:坐标系之间的转换假定道路是平坦的。它基于建立一个单应矩阵,将成像平面上的位置映射到路面上的位置。非平坦道路会在距离计算中引入误差,特别是在远离车辆的位置。

加载一帧视频

在处理整个视频之前,先处理单个视频帧,以说明设计单目摄像机传感器所涉及的概念。

首先创建一个VideoReader对象打开视频文件。为了节省内存,VideoReader一次加载一个视频帧。

视频名称=“caltech_cordova1.avi”; videoReader=videoReader(videoName);

阅读包含车道标记和车辆的有趣框架。

时间戳=0.06667;%从视频开始的时间videoReader。CurrentTime =时间戳;指向选定的帧帧= readFrame (videoReader);%在时间戳秒读取帧imshow(框架)%显示帧

注意:这个例子忽略了镜头失真。如果你担心由透镜畸变引起的距离测量误差,此时你可以使用不失真图像功能,以消除镜头失真。

创建鸟瞰图图像

分割和检测车道标记的方法有很多。其中一种方法涉及使用鸟瞰图像变换。尽管这种变换会产生计算成本,但它提供了一个主要优势。鸟瞰视图中的车道标记具有均匀的厚度,从而简化了分割过程。车道标记属于同一车道也变得平行,从而使进一步分析更容易。

考虑到摄像头的设置birdsEyeView物体将原始图像转换为鸟瞰图。该对象允许您指定使用车辆坐标进行转换的区域。注意,车辆坐标单位是由单眼对象时,相机安装高度指定为米。例如,如果高度以毫米为单位指定,则模拟的其余部分将使用毫米。

使用车辆坐标,定义要变换的区域distAheadOfSensor = 30;%以米为单位,如之前在单摄像机高度输入中所规定spaceToOneSide=6;所有其他距离的单位也是米bottomOffset=3;outView=[bottomOffset,距离传感器前端,-SpaceToOnSide,SpaceToOnSide];%[xmin,xmax,ymin,ymax]imageSize=[NaN,250];输出图像宽度(像素)%;高度是自动选择的,以保持每像素的单位比例birdseeconfig = birdsEyeView(sensor, outView, imageSize);

生成鸟瞰图的形象。

birdsEyeImage=transformImage(birdsEyeConfig,帧);图imshow(birdsEyeImage)

距离传感器更远的区域更模糊,因为像素更少,因此需要更多的插值。

注意,您可以在不使用鸟瞰视图的情况下完成后面的处理步骤,只要您能够在车辆坐标中定位车道边界候选像素即可。

在车辆坐标中找到车道标记

有了鸟瞰图,您现在可以使用segmentLaneMarkerRidge用于将车道标记候选像素与路面分离的功能。选择该技术是因为其简单性和相对有效性。存在其他分割技术,包括语义分割(深度学习)和可控制的过滤器。你可以用下面的这些技术来获得下一阶段所需的二进制掩码。

下面函数的大多数输入参数都是用世界单位指定的,例如,输入的车道标记的宽度segmentLaneMarkerRidge。使用世界单位,您可以轻松尝试新的传感器,即使输入图像大小发生变化。这对于使设计在不断变化的摄像头硬件和处理许多国家不同的标准方面更加稳健和灵活非常重要。

%转换为灰度birdsEyeImage = im2gray (birdsEyeImage);以世界单位计算的车道标记分割ROIVehiclerRoi=视野-[-1,2,-3,3];向左和向右看3米,在传感器前面4米approxLaneMarkerWidthVehicle = 0.25;% 25厘米%检测车道特征laneSensitivity = 0.25;birdsEyeViewBW = segmentLaneMarkerRidge(birdsEyeImage, birdseeconfig, approxLaneMarkerWidthVehicle,...“投资回报”vehicleROI,“敏感性”, laneSensitivity);图imshow (birdsEyeViewBW)

在固定到摄像头传感器的车辆坐标中定位各个车道标记。此示例使用抛物线车道边界模型ax^2+bx+c表示车道标记。其他表示,如三次多项式或样条曲线,也是可能的。转换为车辆坐标是必要的,否则车道标记曲率不能正确地用抛物线表示,而它会受到透视畸变的影响。

车道模型适用于沿着车辆路径的车道标记。横穿道路的车道标志或涂在柏油路上的路标都被拒绝。

在车辆坐标中获得车道候选点[imageX,imageY]=查找(birdsEyeViewBW);xyBoundaryPoints=imageToVehicle(鸟眼配置,[imageY,imageX]);

由于分割后的点中包含了很多不属于实际车道标记的异常点,因此采用基于随机样本一致性(RANSAC)的鲁棒曲线拟合算法。

以数组的形式返回边界及其抛物线参数(a, b, c)抛物线基对象,边界

maxLanes=2;%查找最多两个车道标记boundaryWidth = 3 * approxLaneMarkerWidthVehicle;扩展边界宽度[边界,边界点]=FindParabolicLaneBundaries(xyBoundaryPoints,boundaryWidth,...“MaxNumBoundaries”,maxLanes,“validateBoundaryFcn”,@validateBondaryFCN);

请注意,findParabolicLaneBoundaries取函数句柄,验证基础FCN.这个示例函数列在本示例的末尾。使用这个额外的输入可以让您根据a、b、c参数的值拒绝一些曲线。它也可以用来利用一系列帧的时间信息,通过约束未来的a, b, c值基于以前的视频帧。

确定自我通道的边界

在上一步中找到的某些曲线可能仍然无效。例如,当一条曲线适合人行横道标记时。请使用其他启发式方法拒绝许多此类曲线。

%根据边界的长度确定拒绝边界的标准maxPossibleXLength = diff (vehicleROI (1:2));minXLength = maxPossibleXLength * 0.60;建立阈值找到短的界限如果(numel(boundaries) > 0) isOfMinLength = false(1, numel(boundaries));对于I = 1: numel(边界)如果(diff(界限(i).XExtent)>minXLength)isOfMinLength(i)=真;终止终止其他的isOfMinLength=false;终止

基于由计算的强度度量删除其他边界findParabolicLaneBoundaries功能。根据ROI和图像大小设置车道强度阈值。

%为了计算最大强度,假设ROI内的所有图像像素%是车道候选点birdsImageROI=车辆图像ROI(birdsEyeConfig,VehiclerRoi);[laneImageX,laneImageY]=网格(birdsImageROI(1):birdsImageROI(2),birdsImageROI(3):birdsImageROI(4));%将图像点转换为车辆点vehiclePoints=imageToVehicle(鸟眼配置,[laneImageX(:),laneImageY(:)];找到任意车道唯一x轴位置的最大数目%边界maxPointsInOneLane =元素个数(独特(单(vehiclePoints (: 1)))));%设置车道边界的最大长度为ROI的长度MaxLaneleLength=差异(车辆OI(1:2));%计算此图像大小/ROI大小的最大可能车道强度%的规范maxStrength = maxPointsInOneLane / maxLaneLength;拒绝短而弱的边界idx = 0;strongBoundaries = parabolicLaneBoundary(zeros(nnz(isOfMinLength), 3));对于i = 1: size(isOfMinLength,2)如果isOfMinLength(i) == 1如果(边界(i)。强度> 0.4*maxStrength) idx = idx + 1;strongBoundaries (idx) =边界(我);终止终止终止

将车道标记类型分类为实线/虚线的启发式方法包含在本例底部列出的辅助函数中。了解车道标志的类型对自动驾驶车辆至关重要。例如,禁止跨越实心标记。

当边界点不是空的时候对车道标记类型进行分类如果isempty(boundaryPoints)strongBounders=repmat(strongBounders,1,2);strong边界(1)=抛物线基数(零(1,3));strong边界(2)=抛物线基数(零(1,3));其他的strong边界=ClassifyLanetype(strong边界、边界点);终止distancestobounders=coder.nullcopy(一个(大小(strongbounders,2),1));%寻找自我通道xOffset = 0;距离传感器% 0米对于i=1:大小(strong边界,2)到边界的距离(i)=strong边界(i)。计算边界模型(xOffset);终止找出应聘者的自我界限distancesToLeftBoundary = distancesToBoundaries > 0;如果minLeftDistance = min(distanceobells (distanceoleftboundary));其他的minLeftDistance = 0;终止distanceorightboundary = (distanceborders <= 0);如果minRightDistance = max(distanceborders (distanceorightboundary));其他的minRightDistance = 0;终止找到左边的自我边界如果(minLeftDistance ~= 0) leftEgoBoundaryIndex = distanceborders == minLeftDistance;leftEgoBoundary = parabolicLaneBoundary(zeros(nnz(leftEgoBoundary index), 3));idx = 0;对于i=1:大小(leftEgoBoundaryIndex,1)如果(leftEgoBoundaryIndex(i)=1)idx=idx+1;leftEgoBoundary(idx)=strong边界(i);终止终止其他的leftEgoBoundary = parabolicLaneBoundary.empty ();终止%找到正确的自我边界如果(minRightDistance ~= 0)rightgoboundary = parabolicLaneBoundary(zeros(nnz(rightgoboundary index), 3));idx = 0;对于i=1:大小(rightEgoBoundaryIndex,1)如果(rightgoboundaryindex (i) == 1)rightEgoBoundary (idx) = strongBoundaries(我);终止终止其他的rightEgoBoundary = parabolicLaneBoundary.empty ();终止

在鸟瞰图和常规视图中显示检测到的车道标记。

xVehiclePoints = bottomOffset: distAheadOfSensor;birdsEyeWithEgoLane = insertLaneBoundary(birdsEyeImage, leftEgoBoundary, birdseeconfig, xVehiclePoints,“颜色”,“红色”);birdsEyeWithEgoLane = insertLaneBoundary(birdsEyeWithEgoLane, rightgoboundary, birdseeconfig, xVehiclePoints,“颜色”,“绿色”);frameWithEgoLane = insertLaneBoundary(frame, leftEgoBoundary, sensor, xVehiclePoints,“颜色”,“红色”);frameWithEgoLane = insertLaneBoundary(frameWithEgoLane, rightgoboundary, sensor, xVehiclePoints,“颜色”,“绿色”);图次要情节(“位置”, [0, 0, 0.5, 1.0])%[左,下,宽,高]为标准化单位imshow (birdsEyeWithEgoLane)次要情节(“位置”, [0.5, 0, 0.5, 1.0]) imshow(framewiththegolane)

在车辆坐标中定位车辆

车辆的检测和跟踪是车辆前方碰撞预警(FCW)和自动紧急制动(AEB)系统的关键。

加载一个集合通道特征(ACF)检测器,该检测器预先训练用于检测车辆的前后。像这样的检测器可以处理发出碰撞警告很重要的场景。例如,它还不足以探测到在自我车辆前面横穿马路的车辆。

检测器=车辆检测器ACF();%普通车辆的宽度在1.5 - 2.5米之间车辆宽度=[1.5,2.5];

使用configureDetectorMonoCamera功能将通用ACF检测器专门化,以考虑典型汽车应用的几何结构。通过采用此摄像头配置,此新检测器仅搜索道路表面上的车辆,因为没有点搜索高于消失点的车辆。这节省了计算时间和r得出误报的数量。

monoDetector = configuredetectormoncamera(检测器,传感器,车辆宽度);[bboxes, scores] = detect(monoDetector, frame);

由于此示例显示了如何仅处理单个帧进行演示,因此您无法在原始检测的基础上应用跟踪。添加跟踪使返回车辆位置的结果更加可靠,因为即使车辆部分遮挡,跟踪器也会继续返回车辆的位置。有关更多信息,请参阅有关详细信息,请参阅使用摄像头跟踪多辆车的例子。

接下来,将车辆检测转换为车辆坐标。这个computeVehicleLocations函数,包含在这个示例的最后,在给定一个由图像坐标检测算法返回的边界框时,计算车辆在车辆坐标中的位置。它以车辆坐标返回边界框底部的中心位置。因为我们使用的是单目摄像机传感器和简单的单应法,所以只能准确地计算出沿着道路表面的距离。计算三维空间中的任意位置需要使用立体相机或其他能够三角测量的传感器。

位置=计算车辆位置(B盒、传感器);%在视频帧上覆盖检测imgOut = insertVehicleDetections(frame, locations, bboxes);图;imshow (imgOut);

用视频输入模拟完整的传感器

现在您已经了解了各个步骤的内部工作原理,让我们将它们放在一起,并将它们应用到一个视频序列中,在这个序列中我们还可以利用时间信息。

将视频倒回开头,然后对视频进行处理。下面的代码被缩短了,因为所有关键参数都在前面的步骤中定义了。这里只使用参数,不作进一步说明。

videoReader.CurrentTime=0;isPlayerOpen=true;快照=[];虽然hasFrame (videoReader) & & isPlayerOpen抓取一帧视频帧= readFrame (videoReader);%计算鸟瞰图图像birdsEyeImage=transformImage(birdsEyeConfig,帧);birdsEyeImage=im2gray(birdsEyeImage);%检测车道边界特征birdsEyeViewBW=分段LaneMarkerRidge(birdsEyeImage,birdsEyeConfig,...approxLaneMarkerWidthVehicle,“投资回报”vehicleROI,...“敏感性”, laneSensitivity);在车辆坐标中获得车道候选点[imageX,imageY]=查找(birdsEyeViewBW);xyBoundaryPoints=imageToVehicle(鸟眼配置,[imageY,imageX]);找到车道边界候选者[边界,边界点]=FindParabolicLaneBundaries(xyBoundaryPoints,boundaryWidth,...“MaxNumBoundaries”,maxLanes,“validateBoundaryFcn”,@validateBondaryFCN);拒绝基于长度和强度的界限找到短的界限如果(numel(boundaries) > 0) isOfMinLength = false(1, numel(boundaries));对于I = 1: numel(边界)如果(diff(界限(i).XExtent)>minXLength)isOfMinLength(i)=真;终止终止其他的isOfMinLength=false;终止拒绝短而弱的边界idx = 0;strongBoundaries = parabolicLaneBoundary(zeros(nnz(isOfMinLength), 3));对于i = 1: size(isOfMinLength,2)如果isOfMinLength(i) == 1如果(边界(i).强度>0.2*maxStrength)idx=idx+1;strong边界(idx)=边界(i);终止终止终止边界=边界(isOfMinLength);强有力的=[边界。强度)> 0.2 * maxStrength;边界=边界(强有力的);当边界点不是空的时候对车道标记类型进行分类如果isempty(boundaryPoints)strongBounders=repmat(strongBounders,1,2);strong边界(1)=抛物线基数(零(1,3));strong边界(2)=抛物线基数(零(1,3));其他的strong边界=ClassifyLanetype(strong边界、边界点);终止%寻找自我通道xOffset = 0;距离传感器% 0米distancestobounders=coder.nullcopy(一个(大小(strongbounders,2),1));对于i=1:大小(strong边界,2)到边界的距离(i)=strong边界(i)。计算边界模型(xOffset);终止找出应聘者的自我界限distancesToLeftBoundary = distancesToBoundaries > 0;如果minLeftDistance = min(distanceobells (distanceoleftboundary));其他的minLeftDistance = 0;终止distanceorightboundary = (distanceborders <= 0);如果minRightDistance = max(distanceborders (distanceorightboundary));其他的minRightDistance = 0;终止找到左边的自我边界如果(minLeftDistance ~= 0) leftEgoBoundaryIndex = distanceborders == minLeftDistance;leftEgoBoundary = parabolicLaneBoundary(zeros(nnz(leftEgoBoundary index), 3));idx = 0;对于i=1:大小(leftEgoBoundaryIndex,1)如果(leftEgoBoundaryIndex(i)=1)idx=idx+1;leftEgoBoundary(idx)=strong边界(i);终止终止其他的leftEgoBoundary = parabolicLaneBoundary.empty ();终止%找到正确的自我边界如果(minRightDistance ~= 0)rightgoboundary = parabolicLaneBoundary(zeros(nnz(rightgoboundary index), 3));idx = 0;对于i=1:大小(rightEgoBoundaryIndex,1)如果(rightgoboundaryindex (i) == 1)rightEgoBoundary (idx) = strongBoundaries(我);终止终止其他的rightEgoBoundary = parabolicLaneBoundary.empty ();终止%检测车辆[b框,分数]=检测(单检测器,帧);位置=计算车辆位置(B盒、传感器);%可视化传感器输出和中间结果。包芯传感器输出到结构中。sensorOut。leftEgoBoundary = leftEgoBoundary;sensorOut。rightEgoBoundary = rightEgoBoundary;sensorOut。vehicleLocations =位置;sensorOut。xVehiclePoints = bottomOffset: distAheadOfSensor;sensorOut。vehicleBoxes = bboxes;%打包额外的可视化数据,包括中间结果intOut。birdsEyeImage = birdsEyeImage;intOut。birdsEyeConfig = birdsEyeConfig;intOut。vehicleScores =分数;intOut。vehicleROI = vehicleROI;intOut。birdsEyeBW = birdsEyeViewBW; closePlayers = ~hasFrame(videoReader); isPlayerOpen = visualizeSensorResults(frame, sensor, sensorOut,...intOut closePlayers);时间戳= 7.5333;%获取在timeStamp秒发布的快照如果abs (videoReader。CurrentTime - timeStamp) < 0.01 snapshot = takeSnapshot(frame, sensor, sensorOut);终止终止

显示视频帧。快照是在时间戳秒。

如果~ isempty(快照)图imshow(快照)终止

在不同的视频中尝试传感器设计

这个辅助传感器类将设置和所有必要步骤组装为一个完整的包,可以应用于任何视频。由于传感器设计使用的大多数参数都基于世界单位,因此设计对相机参数(包括图像大小)的更改具有鲁棒性。请注意辅助传感器类不同于前一节中用于说明基本概念的循环。

除了提供新视频外,您还必须提供与该视频对应的摄像头配置。此处显示了该过程。请在您自己的视频上尝试。

%的传感器配置focalLength = [309.4362, 344.2161];principalPoint = [318.9034, 257.5352];imageSize = [480,640];身高= 2.1798;%安装高度,以米为单位距= 14;相机的角度百分比camIntrinsics=cameraIntrinsics(焦距、主点、图像大小);传感器=单摄像机(camIntrinsics、高度、,“节”、沥青);videoReader = videoReader (“caltech_washington1.avi”);

创建辅助传感器对象,并将其应用到视频。

monoSensor = helperMonoSensor(传感器);monoSensor。LaneXExtentThreshold = 0.5;%在这个视频中,为了去除阴影中的错误检测,我们只返回%车辆检测与更高的分数。monoSensor.VehicleDetectionThreshold=20;isPlayerOpen=true;snapshot=[];虽然hasFrame(videoReader) && isPlayerOpen frame = readFrame(videoReader);%拍一帧sensorOut=processFrame(单传感器,帧);ClosePlayer=~hasFrame(视频阅读器);ISPlayerPerpen=DisplaySensorOuts(单传感器,帧,传感器输出,ClosePlayer);时间戳=11.1333;%获取在timeStamp秒发布的快照如果abs (videoReader。CurrentTime - timeStamp) < 0.01 snapshot = takeSnapshot(frame, sensor, sensorOut);终止终止

显示视频帧。快照是在时间戳秒。

如果~ isempty(快照)图imshow(快照)终止

金宝app支持功能

可视化结果显示来自单目摄像机传感器仿真的核心信息和中间结果。

作用isPlayerOpen = visualizeSensorResults(frame, sensor, sensorOut,...intOut closePlayers)拆开主要输入leftEgoBoundary = sensorOut.leftEgoBoundary;rightEgoBoundary = sensorOut.rightEgoBoundary;位置= sensorOut.vehicleLocations;xVehiclePoints = sensorOut.xVehiclePoints;bboxes = sensorOut.vehicleBoxes;%解包其他中间数据birdsEyeViewImage = intOut.birdsEyeImage;birdsEyeConfig = intOut.birdsEyeConfig;vehicleROI = intOut.vehicleROI;birdsEyeViewBW = intOut.birdsEyeBW;在鸟瞰视图中可视化左、右自我车道边界birdsEyeWithOverlays = insertLaneBoundary(birdsEyeViewImage, leftEgoBoundary, birdseeconfig, xVehiclePoints,“颜色”,“红色”);birdseyewiththoverlay = insertLaneBoundary(birdseyewiththoverlay, rightgoboundary, birdseeconfig, xVehiclePoints,“颜色”,“绿色”);%在摄影机视图中可视化车道边界frameWithOverlays = insertLaneBoundary(frame, leftEgoBoundary, sensor, xVehiclePoints,“颜色”,“红色”);framewiththoverlays = insertLaneBoundary(framewiththoverlays, rightgoboundary, sensor, xVehiclePoints,“颜色”,“绿色”);frameWithOverlays=插入车辆检测(frameWithOverlays、位置、B框);imageROI=车辆图像ROI(鸟眼配置、车辆ROI);ROI=[imageROI(1)imageROI(3)imageROI(2)-imageROI(1)imageROI(4)-imageROI(3)];突出包含异常值的候选车道点birdsEyeViewImage=insertShape(birdsEyeViewImage,“矩形”,投资回报率);显示检测ROIbirdsEyeViewImage=imoverlay(birdsEyeViewImage,birdsEyeViewBW,“蓝”);%显示结果frames = {framewiththoverlay, birdsEyeViewImage, birdseyewiththoverlay};持久的球员;如果isempty(players) frameames = {“行车标志及车辆侦测”,“原始分割”,“车道标记检测”};players=helperVideoPlayerSet(帧、帧名称);终止更新(球员,框架);%当第一个玩家关闭时终止循环isPlayerOpen=isOpen(玩家1);如果(~isPlayerOpen | | closePlayers)%关闭其他玩家清晰的球员;终止终止

computeVehicleLocations计算车辆的位置在车辆坐标,给定一个边界框返回的检测算法在图像坐标。它以车辆坐标返回边界框底部的中心位置。由于使用了单目摄像机传感器和简单的单应法,因此只能计算沿道路表面的距离。计算三维空间中的任意位置需要使用立体相机或其他能够三角测量的传感器。

作用location = computeVehicleLocations(bboxes, sensor) locations = 0 (size(bboxes,1),2);对于I = 1:size(bboxes, 1) bbox = bboxes(I,:);%获取下半部分中心的[x,y]位置%检测边界框,单位为米。Bbox是[x, y,宽度,高度]%图像坐标,其中[x,y]表示左上角。yBottom=bbox(2)+bbox(4)-1;xCenter=bbox(1)+(bbox(3)-1)/2;%近似中心位置(i,:) = imageToVehicle(sensor, [xCenter, yBottom]);终止终止

插入车辆检测插入边界框并显示与返回车辆检测相对应的[x,y]位置。

作用imgOut=插入车辆检测(imgIn、位置、B盒)imgOut=imgIn;对于I = 1:size(locations, 1) location = locations(I,:);Bbox = bboxes(i,:);标签= sprintf ('X=%0.2f,Y=%0.2f'、位置(1)、位置(2));imgOut = insertObjectAnnotation (imgOut,...“矩形”bbox,标签,“颜色”,‘g’);终止终止

汽车影像将车辆坐标中的ROI转换为鸟瞰图中的图像坐标。

作用imageROI = vehicleToImageROI(birdsEyeConfig, vehicleeroi)loc2 = abs(vehicleToImage(birdsEyeConfig, [vehicleeroi (2) vehicleeroi (4)]));loc1 = abs(vehicleToImage(birdsEyeConfig, [vehicleeroi (1) vehicleeroi (4)]));loc4 = vehicleToImage(birdsEyeConfig, [vehicleeroi (1) vehicleeroi (4)]);loc3 = vehicleToImage(birdsEyeConfig, [vehicleeroi (1) vehicleeroi (3)]);[minRoiX, maxRoiX, minRoiY, maxRoiY] = deal(loc4(1), loc3(1), loc2(2), loc1(2));imageROI = round([minRoiX, maxRoiX, minRoiY, maxRoiY]);终止

验证基础FCN拒绝使用RANSAC算法计算的一些车道边界曲线。

作用= validateBoundaryFcn短距离(params)如果~isempty(params) a = params(1);拒绝任何“a”系数小的曲线,因为a系数高%弯曲。isGood = abs(a) < 0.003;%a来自ax^2+bx+c其他的isGood=错误;终止终止

classifyLaneTypes确定车道标记类型为固体,

作用边界= classifyLaneTypes(边界,边界点)对于bInd = 1: size(boundary,2) vehiclePoints = boundary {bInd};%按x排序vehiclePoints = sortrows(vehiclePoints, 1);xVehicle = vehiclePoints (: 1);xVehicleUnique =独特(xVehicle);%虚线vs实线xdiff = diff (xVehicleUnique);设置阈值以删除实线中的间隙,但不删除空格%虚线。xdiffThreshold=mean(xdiff)+3*std(xdiff);largeGaps=xdiff(xdiff>xdiffThreshold);%安全默认边界=边界(绑定);%根据set/get方法改变boundary.BoundaryType=LaneBoundaryType.Solid;如果大间隙>1%理想情况下,这些差距应该是一致的,但你不能依赖这些差距%除非您知道ROI范围至少包含3个破折号。边界。BoundaryType = LaneBoundaryType.Dashed;终止边界(绑定)=边界;终止终止

takeSnapshot获取HTML发布报告的输出。

作用I=拍摄快照(帧、传感器、传感器输出)%打开输入leftEgoBoundary = sensorOut.leftEgoBoundary;rightEgoBoundary = sensorOut.rightEgoBoundary;位置= sensorOut.vehicleLocations;xVehiclePoints = sensorOut.xVehiclePoints;bboxes = sensorOut.vehicleBoxes;frameWithOverlays = insertLaneBoundary(frame, leftEgoBoundary, sensor, xVehiclePoints,“颜色”,“红色”);framewiththoverlays = insertLaneBoundary(framewiththoverlays, rightgoboundary, sensor, xVehiclePoints,“颜色”,“绿色”);framewithoverlay = insertVehicleDetections(framewithoverlay, locations, bboxes);我= frameWithOverlays;终止

另见

应用程序

功能

物体

相关话题