主要内容

单目相机的视觉感知

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

概述

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

  • 车道边界检测

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

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

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

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

定义摄像机的配置

了解摄像机的内部和外部校准参数对于像素和车辆坐标之间的精确转换至关重要。

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

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

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

camIntrinsics = cameraIntrinsics(focalLength, principalPoint, imageSize);

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

高度=2.1798;%安装高度,以米为单位距= 14;%摄像机的俯仰角(以度为单位)

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

传感器= moncamera (camIntrinsics, height,“投球”,音高);

请注意,monoCamera对象设置一个非常特定的车辆坐标系,其中X-轴指向车辆前方Y-轴指向车辆的左侧,而Z-轴从地面指向上。

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

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

加载一帧视频

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

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

videoName =“加州理工学院科尔多瓦1.avi”;videoReader = videoReader (videoName);

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

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

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

创建鸟瞰图像

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

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

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

生成鸟瞰图像。

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

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

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

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

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

以下功能的大多数输入参数都是以世界单位指定的,例如,输入的车道标记宽度segmentLaneMarkerRidge.使用世界单位可以让你轻松地尝试新的传感器,即使当输入图像的大小改变。这是非常重要的,以使设计更加健壮和灵活的方面,不断变化的相机硬件和处理不同的标准,在许多国家。

%转换为灰度birdsEyeImage = im2gray (birdsEyeImage);以世界单位计算的车道标记分割ROI= outView - [- 1,2, - 3,3];%向左和向右看3米,在传感器前面看4米近似标记宽度车辆=0.25;%25厘米%检测车道特征laneSensitivity=0.25;birdsEyeViewBW=分段LaneMarkerridge(birdsEyeImage、birdsEyeConfig、approxLaneMarkerWidthVehicle、,...“投资回报”,vehicleROI,“敏感性”兰斯敏感度);图imshow(鸟眼视图BW)

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

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

在车辆坐标中获得车道候选点[imageX, imageY] = find(birdsEyeViewBW);xyBoundaryPoints = imageToVehicle(birdsEyeConfig, [imageY, imageX]);

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

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

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

请注意FindParabolicLaneBundaries取函数句柄,验证基础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;结束

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

%要计算最大强度,请假设ROI内的所有图像像素%是车道候选点birdsImageROI=车辆图像ROI(birdsEyeConfig,VehiclerRoi);[laneImageX,laneImageY]=网格(birdsImageROI(1):birdsImageROI(2),birdsImageROI(3):birdsImageROI(4));将图像点转换为车辆点vehiclePoints = imageToVehicle (birdsEyeConfig [laneImageX (:), laneImageY (:)));%查找任何车道可能的唯一x轴位置的最大数量%的边界maxPointsInOneLane =元素个数(独特(单(vehiclePoints (: 1)))));%设置车道边界的最大长度为ROI的长度maxLaneLength = diff (vehicleROI (1:2));%计算此图像大小/ROI大小的最大可能车道强度%规格maxStrength = maxPointsInOneLane / maxLaneLength;%拒绝短而弱的边界idx=0;strong边界=ParaboliclaneBundary(零(nnz(isOfMinLength),3));i=1:尺寸(长度,2)如果(长度(i)=1)如果(边界(i)。强度> 0.4*maxStrength) idx = idx + 1;strongBoundaries (idx) =边界(我);结束结束结束

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

当边界点不是空的时候对车道标记类型进行分类如果isempty(strongBoundaries) strongBoundaries = repmat(strongBoundaries,1,2);strongBoundaries (1) = parabolicLaneBoundary(0(1、3));strongBoundaries (2) = parabolicLaneBoundary(0(1、3));其他的strong边界=ClassifyLanetype(strong边界、边界点);结束distancestobounders=coder.nullcopy(一个(大小(strongbounders,2),1));%寻找自我通道xOffset = 0;距离传感器% 0米i = 1: size(strongBoundaries, 2) distanceboundaries (i) = strongBoundaries(i).computeBoundaryModel(xOffset);结束找出应聘者的自我界限distancesToLeftBoundary=DistanceStoBounders>0;如果(numel(DistanceStoBounders(distancesToLeftBoundary)))minLeftDistance=min(DistanceStoBounders(distancesToLeftBoundary));其他的minLeftDistance = 0;结束DistanceToRightBoundary=(DistanceToBounders<=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: size(rightgoboundaryindex, 1)如果(rightgoboundaryindex (i) == 1)rightEgoBoundary (idx) = strongBoundaries(我);结束结束其他的rightEgoBoundary=parabolicLaneBoundary.empty();结束

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

xVehiclePoints = bottomOffset: distAheadOfSensor;birdsEyeWithEgoLane = insertLaneBoundary(birdsEyeImage, leftEgoBoundary, birdseeconfig, xVehiclePoints,“颜色”“红色”); birdsEyeWithEgoLane=插入LaneBoundary(birdsEyeWithEgoLane、右EgoBoundary、birdsEyeConfig、X车辆点、,“颜色”“绿色”);frameWithEgoLane=插入Lane基础(框架、左EgoBoundary、传感器、X车辆点、,“颜色”“红色”);frameWithEgoLane = insertLaneBoundary(frameWithEgoLane, rightgoboundary, sensor, xVehiclePoints,“颜色”“绿色”); 图形子地块(“位置”, [0, 0, 0.5, 1.0])%[左、下、宽、高]标准化单位imshow(带电子车道的鸟眼)子地块(“位置”, [0.5, 0, 0.5, 1.0]) imshow(framewiththegolane)

在车辆坐标中定位车辆

在前碰撞警告(FCW)和自动紧急制动(AEB)系统中,检测和跟踪车辆至关重要。

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

探测器= vehicleDetectorACF ();%普通车辆的宽度在1.5到2.5米之间车辆宽度=[1.5,2.5];

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

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

由于本示例仅演示如何处理单个帧,因此不能在原始检测之上应用跟踪。跟踪的添加使得返回车辆位置的结果更加稳健,因为即使车辆被部分遮挡,跟踪器仍会继续返回车辆的位置。有关更多信息,请参见使用摄像头跟踪多辆车的例子。

接下来,将车辆检测转换为车辆坐标。的computeVehicleLocations函数(包括在本例末尾)计算车辆在车辆坐标中的位置,给定检测算法在图像坐标中返回的边界框。它返回边界框底部在车辆坐标中的中心位置。因为我们使用的是单目摄像机传感器和简单的单应矩阵,所以只能精确计算沿道路表面的距离。计算三维空间中的任意位置需要使用立体相机或其他能够进行三角测量的传感器。

locations = computeVehicleLocations(bboxes, sensor);%将检测覆盖在视频帧上imgOut = insertVehicleDetections(frame, locations, bboxes);图;imshow (imgOut);

模拟一个完整的传感器与视频输入

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

将视频倒带到开头,然后处理视频。以下代码缩短,因为所有关键参数都是在前面的步骤中定义的。此处使用参数,无需进一步解释。

videoReader.CurrentTime=0;isPlayerOpen=true;快照=[];虽然hasFrame (videoReader) & & isPlayerOpen抓取一帧视频帧=读帧(视频阅读器);%计算birdsEyeView图像birdsEyeImage = transformImage(birdseeconfig, frame);birdsEyeImage = im2gray (birdsEyeImage);%检测车道边界特征birdsEyeViewBW=分段LaneMarkerRidge(birdsEyeImage,birdsEyeConfig,...approxLaneMarkerWidthVehicle,“投资回报”,vehicleROI,...“敏感性”兰斯敏感度);在车辆坐标中获得车道候选点[imageX, imageY] = find(birdsEyeViewBW);xyBoundaryPoints = imageToVehicle(birdsEyeConfig, [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;strong边界=ParaboliclaneBundary(零(nnz(isOfMinLength),3));i=1:尺寸(长度,2)如果(长度(i)=1)如果(边界(i)。强度> 0.2*maxStrength) idx = idx + 1;strongBoundaries (idx) =边界(我);结束结束结束边界=边界(isOfMinLength);isStrong=[Bounders.Strength]>0.2*maxStrength;边界=边界(isStrong);当边界点不是空的时候对车道标记类型进行分类如果isempty(strongBoundaries) strongBoundaries = repmat(strongBoundaries,1,2);strongBoundaries (1) = parabolicLaneBoundary(0(1、3));strongBoundaries (2) = parabolicLaneBoundary(0(1、3));其他的strong边界=ClassifyLanetype(strong边界、边界点);结束%寻找自我通道xOffset = 0;距离传感器% 0米distancestobounders=coder.nullcopy(一个(大小(strongbounders,2),1));i = 1: size(strongBoundaries, 2) distanceboundaries (i) = strongBoundaries(i).computeBoundaryModel(xOffset);结束找出应聘者的自我界限distancesToLeftBoundary=DistanceStoBounders>0;如果(numel(DistanceStoBounders(distancesToLeftBoundary)))minLeftDistance=min(DistanceStoBounders(distancesToLeftBoundary));其他的minLeftDistance = 0;结束DistanceToRightBoundary=(DistanceToBounders<=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: size(rightgoboundaryindex, 1)如果(rightgoboundaryindex (i) == 1)rightEgoBoundary (idx) = strongBoundaries(我);结束结束其他的rightEgoBoundary=parabolicLaneBoundary.empty();结束%检测车辆[bboxes, scores] = detect(monoDetector, frame);locations = computeVehicleLocations(bboxes, sensor);可视化传感器输出和中间结果。包的核心%传感器输出到结构中。sensorOut.leftEgoBoundary=leftEgoBoundary;sensorOut.rightEgoBoundary=rightEgoBoundary;sensorOut.vehicleLocations=locations;sensorOut.xVehiclePoints=Bottom偏移:距离传感器前端;sensorOut.VehicleBox=bboxes;%打包额外的可视化数据,包括中间结果intOut.birdsEyeImage=birdsEyeImage;intOut.birdseyconfig=birdseyconfig;intOut.vehicleScores=分数;intOut.vehicleROI=vehicleROI;intOut.birdseyeww=birdsEyeViewBW;ClosePlayer=~hasFrame(视频阅读器);isPlayerOpen=可视化传感器结果(帧、传感器、传感器输出、,...输入,近距离播放);时间戳=7.5333;%在时间戳秒处拍摄快照以进行发布如果abs (videoReader。CurrentTime - timeStamp) < 0.01 snapshot = takeSnapshot(frame, sensor, sensorOut);结束结束

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

如果~ isempty(快照)图imshow(快照)结束

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

helperMonoSensor类组装了设置和所有必要的步骤,以模拟单目摄像机传感器到一个完整的包,可以应用于任何视频。由于传感器设计中使用的大多数参数都是基于世界单位的,因此该设计对摄像机参数(包括图像大小)的变化具有鲁棒性。的代码helperMonoSensor类与上一节中用于说明基本概念的循环不同。

除了提供一个新的视频外,您还必须提供与该视频相对应的摄像机配置。流程如下所示。在你自己的视频中试试。

%传感器配置焦距=[309.4362344.2161];主点=[318.9034257.5352];imageSize=[480640];高度=2.1798;%安装高度,以米为单位距= 14;%摄像机的俯仰角(以度为单位)camIntrinsics = cameraIntrinsics(focalLength, principalPoint, imageSize);传感器= moncamera (camIntrinsics, height,“投球”,音高);视频阅读器=视频阅读器(“加州理工大学华盛顿分校1.avi”);

创建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;%在时间戳秒处拍摄快照以进行发布如果abs (videoReader。CurrentTime - timeStamp) < 0.01 snapshot = takeSnapshot(frame, sensor, sensorOut);结束结束

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

如果~ isempty(快照)图imshow(快照)结束

万博1manbetx辅助功能

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

作用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=插入LaneBoundary(birdsEyeViewImage、leftEgoBoundary、birdsEyeConfig、xVehiclePoints、,“颜色”“红色”); birdsEyeWithOverlays=嵌入LaneBoundary(birdsEyeWithOverlays,右边界,birdsEyeConfig,X车辆点,“颜色”“绿色”);%在摄像机视图中可视化自我通道边界frameWithOverlays = insertLaneBoundary(frame, leftEgoBoundary, sensor, xVehiclePoints,“颜色”“红色”); frameWithOverlays=插入LaneBondary(frameWithOverlays,右侧电子边界,传感器,X车辆点,“颜色”“绿色”);framewithoverlay = insertVehicleDetections(framewithoverlay, locations, bboxes);imageROI = vehicleToImageROI(birdsEyeConfig, vehicleeroi);ROI = [imageROI(1) imageROI(3) imageROI(2)-imageROI(1) imageROI(4)-imageROI(3)];突出包含异常值的候选车道点birdsEyeViewImage = insertShape (birdsEyeViewImage,“矩形”ROI);%显示检测ROI= 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,:)=图像到车辆(传感器,[xCenter,yBottom]);结束结束

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

作用imgOut = insertVehicleDetections(imgIn, locations, bboxes)I = 1:size(locations, 1) location = locations(I,:);Bbox = bboxes(i,:);标签= sprintf ('X=%0.2f,Y=%0.2f',位置(1),位置(2));imgOut=插入对象注释(imgOut,...“矩形”bbox,标签,“颜色”‘g’);结束结束

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

作用图像ROI=vehicleToImageROI(鸟眼配置,vehicleROI)vehicleROI=double(vehicleROI);loc2=abs(vehicleToImage(鸟眼配置,[vehicleROI(2)vehicleROI(4)]);loc1=abs(vehicleToImage(鸟眼配置,[vehicleROI(1)vehicleROI(4)];loc4=vehicleToImage(鸟眼配置,[vehicleROI(1)vehicleROI(4)];loc3=vehicleToImage(鸟眼配置,[vehicleROI(1)vehicleROI(3)];[minRoiX,maxRoiX,Minroy,Maxroy]=交易(loc4(1),loc3(1),loc2(2),loc1(2));图像ROI=圆形([minRoiX,maxRoiX,Minroy,Maxroy]);结束

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

作用isGood=ValidateBondaryFCN(参数)如果~isempty(params) a = params(1);拒绝任何“a”系数小的曲线,因为a系数高%弯曲的。isGood=abs(a)<0.003;% a从ax^2+bx+c其他的好= false;结束结束

分类类目确定车道标记类型为固体

作用边界= classifyLaneTypes(边界,边界点)绑定=1:大小(边界,2)车辆点=边界点{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;如果largeGaps > 1理想情况下,这些差距应该是一致的,但你不能依赖%,除非你知道ROI范围包括至少3破折号。边界。BoundaryType = LaneBoundaryType.Dashed;结束边界(bInd)=边界;结束结束

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

作用I=拍摄快照(帧、传感器、传感器输出)%打开输入leftEgoBoundary = sensorOut.leftEgoBoundary;rightEgoBoundary = sensorOut.rightEgoBoundary;位置= sensorOut.vehicleLocations;xVehiclePoints = sensorOut.xVehiclePoints;bboxes = sensorOut.vehicleBoxes;frameWithOverlays = insertLaneBoundary(frame, leftEgoBoundary, sensor, xVehiclePoints,“颜色”“红色”); frameWithOverlays=插入LaneBondary(frameWithOverlays,右侧电子边界,传感器,X车辆点,“颜色”“绿色”);framewithoverlay = insertVehicleDetections(framewithoverlay, locations, bboxes);我= frameWithOverlays;结束

另请参阅

应用程序

功能

对象

相关话题