主要内容

视觉感知使用单眼相机

这个例子展示了如何构建一个单眼相机传感器模拟车道边界和车辆检测的能力。传感器将报告这些检测车辆坐标系。在这个例子中,您将学习使用的坐标系统自动驾驶工具箱™,和计算机视觉技术参与的设计样例单眼相机传感器。

概述

车辆包含ADAS特性或被设计为全自动依靠多个传感器。这些传感器可以包括声纳、雷达、激光雷达和摄像头。这个例子说明了所涉及的一些概念设计中一个单眼相机系统。这种传感器可以完成许多任务,包括:

  • 车道边界检测

  • 检测车辆,人,和其他对象

  • 距离估计从自我车辆障碍

随后,单眼相机传感器返回的数据可以用来发布车道偏离警告,碰撞警告,或设计一个车道保持辅助控制系统。与其他传感器,同时它也可以用于实现紧急制动系统和其他安全性至关重要的功能。

示例实现功能的一个子集上发现一个发育完全的单眼相机系统。它检测车道边界和支持的车辆,车辆坐标系和报告他们的位置。

定义摄像机的配置

了解相机的内在动力和外在的校准参数精确的像素和车辆坐标之间的转换的关键。

首先定义相机的内部参数。下面的参数测定早些时候使用相机校正过程,用棋盘校准模式。您可以使用相机校准器应用程序来获取你的相机。

focalLength = [309.4362, 344.2161];%(外汇、财政年度)在像素单元principalPoint = [318.9034, 257.5352];% (cx, cy)光学中心的像素坐标图象尺寸= (480、640);% (nrows, mcols)

注意,镜头畸变系数被忽略了,因为几乎没有变形数据。参数存储在一个cameraIntrinsics对象。

camIntrinsics = cameraIntrinsics (focalLength principalPoint图象尺寸);

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

身高= 2.1798;%安装高度从地面米距= 14;%相机在距度

上面的数量可以从返回的旋转和转换矩阵estimateExtrinsics函数。节指定了倾斜相机的水平位置。在这个示例中,使用的相机的辊和偏航传感器都是零。整个配置定义intrinsic并存储在外部monoCamera对象。

传感器= monoCamera (camIntrinsics、身高、“节”、沥青);

请注意,monoCamera对象设置一个非常具体的车辆坐标系,在那里X设在指向前方的车辆,Y设在点左边的车,和Z设在从地面点。

默认情况下,坐标系统的起源是在地面上,直接下面相机中心定义的相机的焦点。当你想使用另一个起源,SensorLocation属性的monoCamera对象可以用来给相机的X和Y位置相对于它。此外,monoCamera提供了imageToVehiclevehicleToImage图像和车辆坐标系统之间的转换的方法。

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

加载一个帧的视频

整个视频处理,过程之前单个视频帧来说明所涉及的概念一个单眼相机传感器的设计。

首先创建一个VideoReader对象,打开一个视频文件。记忆效率,VideoReader一次加载一个视频帧。

videoName =“caltech_cordova1.avi”;videoReader = videoReader (videoName);

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

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

注意:这个例子忽略透镜畸变。如果你是担心错误引入的距离测量透镜畸变,此时可以使用undistortImage函数来消除镜头畸变。

创建鸟瞰图图像

有很多方法可以检测车道标记。一种方法包括使用鸟瞰图图像变换。尽管它会引入计算成本,这个转换提供了一个主要的优势。鸟瞰的车道标记均匀厚度,从而简化分割过程。车道标记也属于同一个巷成为平行,从而使进一步分析更容易。

考虑到相机设置,birdsEyeView对象转换原始图像的鸟瞰图。该对象允许您指定的区域要使用车辆坐标变换。注意车辆坐标单位建立的monoCamera中指定的对象,当摄像机安装高度是米。例如,如果指定的高度是毫米,其余的模拟会使用毫米。

%使用车辆坐标系,定义区域变换distAheadOfSensor = 30;%的米,正如前面monoCamera高度中指定的输入spaceToOneSide = 6;%所有其他数量也在米的距离bottomOffset = 3;官样文章= [bottomOffset distAheadOfSensor、-spaceToOneSide spaceToOneSide);% (xmin xmax、ymin ymax]图象尺寸=(南,250年);%输出图像像素宽度;高度选择自动保存单位每像素比例birdsEyeConfig = birdsEyeView(传感器、官样文章、图象尺寸);

生成鸟瞰图的形象。

birdsEyeImage = transformImage (birdsEyeConfig,框架);图imshow (birdsEyeImage)

地区远离传感器更模糊,由于像素较少,因此需要更大数量的插值。

注意,您可以完成后者处理步骤没有使用鸟瞰图,只要你可以在车辆的车道边界候选像素坐标。

在车辆坐标找到车道标记

鸟瞰图的形象,您现在可以使用segmentLaneMarkerRidge函数单独的车道标志候选像素从路面。这种技术为简单起见,选择了和相对有效性。选择分割技术存在包括语义分割(深度学习)和可操纵的过滤器。你可以用下面这些技巧来获得一个二进制下一阶段所需的面具。

大多数输入参数的函数中指定以下是世界上单位,例如,车道宽度送入标志segmentLaneMarkerRidge。世界的使用单位允许您轻松尝试新的传感器,即使输入图像大小的变化。这是非常重要的,使设计更健壮且灵活改变相机硬件和处理不同标准在许多国家。

%转换为灰度图birdsEyeImage = im2gray (birdsEyeImage);在世界单位%车道标志分割ROIvehicleROI =官样文章- (1、2、3、3);%看3米左右,4米的传感器approxLaneMarkerWidthVehicle = 0.25;% 25厘米%检测车道功能laneSensitivity = 0.25;birdsEyeViewBW = segmentLaneMarkerRidge (birdsEyeImage birdsEyeConfig approxLaneMarkerWidthVehicle,“投资回报”vehicleROI,“敏感”,laneSensitivity);图imshow (birdsEyeViewBW)

定位单个车道标记发生在车辆固定在相机传感器的坐标。这个示例使用一个抛物线车道边界模型,ax ^ 2 + bx + c,代表车道标记。其他表示,如三度多项式或样条函数,是可能的。转换为车辆坐标是必要的,否则无法正确车道标记曲率由抛物线虽然受到透视畸变的影响。

沿着车道模型适用于车道标记车辆的路径。穿过车道标记的路径或路标漆成沥青被拒绝。

%获得巷候选点车辆坐标[imageX, imageY] =找到(birdsEyeViewBW);xyBoundaryPoints = imageToVehicle (birdsEyeConfig[或]imageY,);

由于分段点包含许多局外人不属于实际的车道标记,使用健壮的曲线拟合的算法基于随机样本一致(RANSAC)。

返回边界和抛物线参数(a, b, c)的数组parabolicLaneBoundary对象,边界

maxLanes = 2;%寻找最多两个车道标记boundaryWidth = 3 * approxLaneMarkerWidthVehicle;%扩大边界宽度(边界,boundaryPoints) = findParabolicLaneBoundaries (xyBoundaryPoints boundaryWidth,“MaxNumBoundaries”maxLanes,“validateBoundaryFcn”,@validateBoundaryFcn);

请注意,findParabolicLaneBoundaries接受一个函数处理,validateBoundaryFcn。这个例子函数列在这个例子的结束。使用这个额外的输入允许您拒绝一些曲线基于的值,b, c参数。它也可以用来利用时间信息在一系列帧通过约束未来,b、c值基于之前的视频帧。

确定自我的边界的车道

前一步骤中发现的一些曲线仍然可能是无效的。例如,当一个曲线符合人行横道标记。使用其他启发式拒绝许多这样的曲线。

%建立标准拒绝边界基于它们的长度maxPossibleXLength = diff (vehicleROI (1:2));minXLength = maxPossibleXLength * 0.60;%建立一个阈值%找到短边界如果(元素个数(边界)> 0)isOfMinLength = false(1,元素个数(边界));i = 1:元素个数(边界)如果(diff(边界(我).XExtent) > minXLength) isOfMinLength (i) = true;结束结束其他的isOfMinLength = false;结束

删除额外的基于强度指标计算的边界findParabolicLaneBoundaries函数。设置一个车道强度阈值基于ROI和图像大小。

%计算出最大的力量,承担所有在ROI图像像素%巷候选点birdsImageROI = vehicleToImageROI (birdsEyeConfig vehicleROI);[laneImageX, laneImageY] = meshgrid (birdsImageROI (1): birdsImageROI (2), birdsImageROI (3): birdsImageROI (4));%转换车点的像点vehiclePoints = imageToVehicle (birdsEyeConfig [laneImageX (:), laneImageY (:)));%找到独特的轴位置的最大数量可能为任何的车道%的边界maxPointsInOneLane =元素个数(独特(单(vehiclePoints (: 1)))));%设置车道边界的最大长度的ROI长度maxLaneLength = diff (vehicleROI (1:2));%计算出最大可能的车道强度图像大小/ ROI的大小%的规范maxStrength = maxPointsInOneLane / maxLaneLength;%拒绝短和弱边界idx = 0;strongBoundaries = parabolicLaneBoundary (0 (nnz (isOfMinLength), 3));i = 1:尺寸(isOfMinLength, 2)如果(isOfMinLength (i) = = 1)如果(边界(i)。强度> 0.4 * maxStrength) idx = idx + 1;strongBoundaries (idx) =边界(我);结束结束结束

启发式分类车道标记类型作为固体/冲都包含在一个helper函数列底部的这个例子。知道车道标记类型自动对车辆转向,至关重要。例如,穿越固体标记是被禁止的。

%分类车道标记类型当boundaryPoints不是空的如果isempty (boundaryPoints) strongBoundaries = repmat (strongBoundaries 1 2);strongBoundaries (1) = parabolicLaneBoundary (0 (1、3));strongBoundaries (2) = parabolicLaneBoundary (0 (1、3));其他的strongBoundaries = classifyLaneTypes (strongBoundaries boundaryPoints);结束distancesToBoundaries = coder.nullcopy(的(大小(strongBoundaries, 2), 1));%找到自我道xOffset = 0;从传感器% 0米i = 1:尺寸(strongBoundaries, 2) distancesToBoundaries (i) = strongBoundaries (i) .computeBoundaryModel (xOffset);结束%找到候选人自我界限distancesToLeftBoundary = distancesToBoundaries > 0;如果(元素个数(distancesToBoundaries (distancesToLeftBoundary))) minLeftDistance = min (distancesToBoundaries (distancesToLeftBoundary));其他的minLeftDistance = 0;结束distancesToRightBoundary = (distancesToBoundaries < = 0);如果(元素个数(distancesToBoundaries (distancesToRightBoundary))) minRightDistance = max (distancesToBoundaries (distancesToRightBoundary));其他的minRightDistance = 0;结束%找到了自我边界如果(minLeftDistance ~ = 0) leftEgoBoundaryIndex = distancesToBoundaries = = minLeftDistance;leftEgoBoundary = parabolicLaneBoundary (0 (nnz (leftEgoBoundaryIndex), 3));idx = 0;i = 1:尺寸(leftEgoBoundaryIndex, 1)如果(leftEgoBoundaryIndex (i) = = 1) idx = idx + 1;leftEgoBoundary (idx) = strongBoundaries(我);结束结束其他的leftEgoBoundary = parabolicLaneBoundary.empty ();结束%找到正确的自我边界如果(minRightDistance ~ = 0) rightEgoBoundaryIndex = distancesToBoundaries = = minRightDistance;rightEgoBoundary = parabolicLaneBoundary (0 (nnz (rightEgoBoundaryIndex), 3));idx = 0;i = 1:尺寸(rightEgoBoundaryIndex, 1)如果(rightEgoBoundaryIndex (i) = = 1) idx = idx + 1;rightEgoBoundary (idx) = strongBoundaries(我);结束结束其他的rightEgoBoundary = parabolicLaneBoundary.empty ();结束

在鸟瞰图显示检测到的车道标记图像和在普通视图中。

xVehiclePoints = bottomOffset: distAheadOfSensor;birdsEyeWithEgoLane = insertLaneBoundary (birdsEyeImage leftEgoBoundary、birdsEyeConfig xVehiclePoints,“颜色”,“红色”);birdsEyeWithEgoLane = insertLaneBoundary (birdsEyeWithEgoLane rightEgoBoundary、birdsEyeConfig xVehiclePoints,“颜色”,“绿色”);frameWithEgoLane = insertLaneBoundary(框架、leftEgoBoundary、传感器、xVehiclePoints“颜色”,“红色”);frameWithEgoLane = insertLaneBoundary (xVehiclePoints frameWithEgoLane rightEgoBoundary,传感器,“颜色”,“绿色”);图次要情节(“位置”,(0,0,0.5,1.0))%(左、底部宽度、高度)归一化单位imshow (birdsEyeWithEgoLane)次要情节(“位置”,0.5,0、0.5、1.0)imshow (frameWithEgoLane)

定位车辆在车辆坐标系

检测和跟踪车辆前方碰撞预警至关重要(结合)和自动紧急制动(AEB)系统。

加载一个聚合通道特性(ACF)检测器,pretrained检测车辆的前方和后方。这种检测器可以处理场景发出碰撞警告很重要。它是不够的,例如,对于检测车辆行驶在道路车辆前的自我。

探测器= vehicleDetectorACF ();%常见车辆的宽度是1.5到2.5米之间vehicleWidth = [1.5, 2.5];

使用configureDetectorMonoCamera功能专门化常规ACF探测器考虑几何的典型汽车应用程序。通过在这个相机配置中,这种新的检测器只搜索车辆沿着路的表面,因为没有点寻找车辆上方的消失点。这可以节省计算时间和减少假阳性的数量。

monoDetector = configureDetectorMonoCamera(探测器、传感器、vehicleWidth);[bboxes,分数]=检测(monoDetector框架);

只因为这个例子展示了如何处理一个帧出于演示的目的,你不能申请跟踪原始检测。添加跟踪使返回的结果车辆位置更加健壮,因为即使车辆部分闭塞,追踪继续返回车辆的位置。有关更多信息,请参见跟踪多个车辆使用相机的例子。

接下来,将车辆检测车辆坐标。的computeVehicleLocations功能,包括在这个例子中,计算车辆在车辆的位置坐标给定一个边界框返回的检测算法在图像坐标。它返回边界框的底部的中心位置的坐标。因为我们使用的是单眼相机传感器和一个简单的单应性,只有距离表面的路上可以计算准确。在三维空间任意位置的计算需要使用立体相机或另一个传感器三角测量的能力。

位置= computeVehicleLocations (bboxes、传感器);%叠加在视频帧的检测imgOut = insertVehicleDetections(框架、位置bboxes);图;imshow (imgOut);

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

现在你有一个想法的内部是如何运作的各个步骤,让我们把它们放在一起,它们应用到一个视频序列,我们还可以利用时间信息。

回放视频一开始,然后处理视频。下面的代码是缩短,因为在前面的步骤中定义的所有关键参数。在这里,没有进一步的解释使用的参数。

videoReader。CurrentTime = 0;isPlayerOpen = true;快照= [];hasFrame (videoReader) & & isPlayerOpen%抓取一帧的视频帧= readFrame (videoReader);%计算birdsEyeView形象birdsEyeImage = transformImage (birdsEyeConfig,框架);birdsEyeImage = im2gray (birdsEyeImage);%检测车道边界特征birdsEyeViewBW = segmentLaneMarkerRidge (birdsEyeImage birdsEyeConfig,approxLaneMarkerWidthVehicle,“投资回报”vehicleROI,“敏感”,laneSensitivity);%获得巷候选点车辆坐标[imageX, imageY] =找到(birdsEyeViewBW);xyBoundaryPoints = imageToVehicle (birdsEyeConfig[或]imageY,);%找到车道边界的候选人(边界,boundaryPoints) = findParabolicLaneBoundaries (xyBoundaryPoints boundaryWidth,“MaxNumBoundaries”maxLanes,“validateBoundaryFcn”,@validateBoundaryFcn);%拒绝边界基于它们的长度和强度%找到短边界如果(元素个数(边界)> 0)isOfMinLength = false(1,元素个数(边界));i = 1:元素个数(边界)如果(diff(边界(我).XExtent) > minXLength) isOfMinLength (i) = true;结束结束其他的isOfMinLength = false;结束%拒绝短和弱边界idx = 0;strongBoundaries = parabolicLaneBoundary (0 (nnz (isOfMinLength), 3));i = 1:尺寸(isOfMinLength, 2)如果(isOfMinLength (i) = = 1)如果(边界(i)。强度> 0.2 * maxStrength) idx = idx + 1;strongBoundaries (idx) =边界(我);结束结束结束边界=边界(isOfMinLength);强有力的=[边界。力量]> 0.2 * maxStrength;边界=边界(强有力的);%分类车道标记类型当boundaryPoints不是空的如果isempty (boundaryPoints) strongBoundaries = repmat (strongBoundaries 1 2);strongBoundaries (1) = parabolicLaneBoundary (0 (1、3));strongBoundaries (2) = parabolicLaneBoundary (0 (1、3));其他的strongBoundaries = classifyLaneTypes (strongBoundaries boundaryPoints);结束%找到自我道xOffset = 0;从传感器% 0米distancesToBoundaries = coder.nullcopy(的(大小(strongBoundaries, 2), 1));i = 1:尺寸(strongBoundaries, 2) distancesToBoundaries (i) = strongBoundaries (i) .computeBoundaryModel (xOffset);结束%找到候选人自我界限distancesToLeftBoundary = distancesToBoundaries > 0;如果(元素个数(distancesToBoundaries (distancesToLeftBoundary))) minLeftDistance = min (distancesToBoundaries (distancesToLeftBoundary));其他的minLeftDistance = 0;结束distancesToRightBoundary = (distancesToBoundaries < = 0);如果(元素个数(distancesToBoundaries (distancesToRightBoundary))) minRightDistance = max (distancesToBoundaries (distancesToRightBoundary));其他的minRightDistance = 0;结束%找到了自我边界如果(minLeftDistance ~ = 0) leftEgoBoundaryIndex = distancesToBoundaries = = minLeftDistance;leftEgoBoundary = parabolicLaneBoundary (0 (nnz (leftEgoBoundaryIndex), 3));idx = 0;i = 1:尺寸(leftEgoBoundaryIndex, 1)如果(leftEgoBoundaryIndex (i) = = 1) idx = idx + 1;leftEgoBoundary (idx) = strongBoundaries(我);结束结束其他的leftEgoBoundary = parabolicLaneBoundary.empty ();结束%找到正确的自我边界如果(minRightDistance ~ = 0) rightEgoBoundaryIndex = distancesToBoundaries = = minRightDistance;rightEgoBoundary = parabolicLaneBoundary (0 (nnz (rightEgoBoundaryIndex), 3));idx = 0;i = 1:尺寸(rightEgoBoundaryIndex, 1)如果(rightEgoBoundaryIndex (i) = = 1) idx = idx + 1;rightEgoBoundary (idx) = strongBoundaries(我);结束结束其他的rightEgoBoundary = parabolicLaneBoundary.empty ();结束%检测车辆[bboxes,分数]=检测(monoDetector框架);位置= computeVehicleLocations (bboxes、传感器);%可视化传感器输出和中间结果。包的核心%传感器输出成一个结构体。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;%对快照发布时间戳秒如果abs (videoReader。CurrentTime -时间戳)< 0.01 = takeSnapshot快照(框架、传感器、sensorOut);结束结束

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

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

传感器设计在不同的视频

helperMonoSensor类组装设置和所有必要的步骤来模拟单眼相机传感器到一个完整的包,可以应用于任何视频。因为大多数传感器所使用的参数设计是基于世界单位,设计健壮的相机参数的变化,包括图像大小。注意,代码内部helperMonoSensor类是不同的循环在前面的小节中,用来说明基本概念。

除了提供一个新的视频,你必须提供一个摄像头配置相应的视频。这里显示的过程。试着在你自己的视频。

%的传感器配置focalLength = [309.4362, 344.2161];principalPoint = [318.9034, 257.5352];图象尺寸= (480、640);身高= 2.1798;%安装高度从地面米距= 14;%相机在距度camIntrinsics = cameraIntrinsics (focalLength principalPoint图象尺寸);传感器= monoCamera (camIntrinsics、身高、“节”、沥青);videoReader = videoReader (“caltech_washington1.avi”);

创建helperMonoSensor对象,并将其应用到视频。

monoSensor = helperMonoSensor(传感器);monoSensor。LaneXExtentThreshold = 0.5;%从阴影删除错误的检测在这个视频中,我们只返回%车辆检测得分越高。monoSensor。VehicleDetectionThreshold = 20;isPlayerOpen = true;快照= [];hasFrame (videoReader) & & isPlayerOpen帧= readFrame (videoReader);%得到一个框架sensorOut = processFrame (monoSensor,框架);closePlayers = ~ hasFrame (videoReader);isPlayerOpen = displaySensorOutputs (monoSensor、框架、sensorOut closePlayers);时间戳= 11.1333;%对快照发布时间戳秒如果abs (videoReader。CurrentTime -时间戳)< 0.01 = takeSnapshot快照(框架、传感器、sensorOut);结束结束

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

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

金宝app支持功能

visualizeSensorResults显示核心信息和中间结果的单眼相机传感器模拟。

函数sensorOut isPlayerOpen = visualizeSensorResults(框架、传感器,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;%显示左和右ego-lane边界鸟瞰图birdsEyeWithOverlays = insertLaneBoundary (birdsEyeViewImage leftEgoBoundary、birdsEyeConfig xVehiclePoints,“颜色”,“红色”);birdsEyeWithOverlays = insertLaneBoundary (birdsEyeWithOverlays rightEgoBoundary、birdsEyeConfig xVehiclePoints,“颜色”,“绿色”);%显示ego-lane边界在相机视图中frameWithOverlays = insertLaneBoundary(框架、leftEgoBoundary、传感器、xVehiclePoints“颜色”,“红色”);frameWithOverlays = insertLaneBoundary (xVehiclePoints frameWithOverlays rightEgoBoundary,传感器,“颜色”,“绿色”);frameWithOverlays = insertVehicleDetections (frameWithOverlays、位置bboxes);imageROI = vehicleToImageROI (birdsEyeConfig vehicleROI);投资回报率= [imageROI (1) imageROI (3) imageROI (2) -imageROI (1) imageROI (4) -imageROI (3)];%强调候选人巷点,包括离群值birdsEyeViewImage = insertShape (birdsEyeViewImage,“矩形”ROI);%显示检测ROIbirdsEyeViewImage = imoverlay (birdsEyeViewImage birdsEyeViewBW,“蓝”);%显示结果帧= {frameWithOverlays, birdsEyeViewImage birdsEyeWithOverlays};持续的球员;如果isempty(球员)frameNames = {车道标志和车辆检测,“原始分割”,“车道标记检测”};玩家= helperVideoPlayerSet(帧,frameNames);结束更新(球员,框架);%终止循环当第一个球员是关闭的isPlayerOpen = isOpen(球员,1);如果(~ isPlayerOpen | | closePlayers)%关闭其他球员清晰的球员;结束结束

computeVehicleLocations计算车辆在车辆的位置坐标,给定一个边界框返回的检测算法在图像坐标。它返回边界框的底部的中心位置的坐标。因为一个单眼相机传感器和一个简单的单应性,只有距离表面的路上可以计算。在三维空间任意位置的计算需要使用立体相机或另一个传感器三角测量的能力。

函数位置= computeVehicleLocations (bboxes、传感器)位置= 0(大小(bboxes, 1), 2);i = 1:尺寸(bboxes 1) bbox = bboxes(我:);%得到(x, y)的中心位置较低的部分%检测边界框在米。bbox是(x, y,宽度、高度)%的图像坐标,(x, y)表示左上角。bbox yBottom = bbox (2) + (4) - 1;xCenter = bbox (1) + (bbox (3) 1) / 2;%近似中心位置(我:)= imageToVehicle(传感器、[xCenter yBottom]);结束结束

insertVehicleDetections插入边界框并显示(x, y)位置对应于返回车辆检测。

函数imgOut = insertVehicleDetections (imgIn、位置bboxes) imgOut = imgIn;i = 1:尺寸(位置1)位置=位置(我:);bbox = bboxes(我);标签= sprintf (“X = % 0.2 f, Y = % 0.2 f '、位置(1)、位置(2));imgOut = insertObjectAnnotation (imgOut,“矩形”bbox,标签,“颜色”,‘g’);结束结束

vehicleToImageROIROI在车辆坐标系转换到图像坐标在鸟瞰图的形象。

函数imageROI = vehicleToImageROI (birdsEyeConfig vehicleROI) vehicleROI =双(vehicleROI);loc2 = abs (vehicleToImage (birdsEyeConfig [vehicleROI (2) vehicleROI (4))));loc1 = abs (vehicleToImage (birdsEyeConfig [vehicleROI (1) vehicleROI (4))));loc4 = vehicleToImage (birdsEyeConfig [vehicleROI (1) vehicleROI (4)]);loc3 = vehicleToImage (birdsEyeConfig [vehicleROI (1) vehicleROI (3)));[minRoiX, maxRoiX minRoiY maxRoiY] =交易(loc4 (1) loc3 (1) loc2 (2), loc1 (2));imageROI =圆([minRoiX、maxRoiX minRoiY, maxRoiY]);结束

validateBoundaryFcn拒绝一些车道边界曲线计算使用RANSAC算法。

函数= validateBoundaryFcn短距离(params)如果~ isempty (params) = params (1);%拒绝任何与小a系数曲线,这使得它的高度%弯曲。短距离= abs (a) < 0.003;%从ax ^ 2 + bx + c其他的好= false;结束结束

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

函数boundaryPoints边界= classifyLaneTypes(边界)绑定= 1:尺寸(边界,2)vehiclePoints = boundaryPoints{绑定};用x %排序vehiclePoints = sortrows (vehiclePoints, 1);xVehicle = vehiclePoints (: 1);xVehicleUnique =独特(xVehicle);%破灭与固体xdiff = diff (xVehicleUnique);%设置一个阈值来消除差距在实线而不是空间%虚线。xdiffThreshold =意味着(xdiff) + 3 *性病(xdiff);largeGaps = xdiff (xdiff > xdiffThreshold);%安全默认边界=边界(绑定);%根据get / set方法改变边界。BoundaryType = LaneBoundaryType.Solid;如果largeGaps > 1%在理想情况下,这些差距应该是一致的,但你不能依赖%,除非你知道ROI程度包括至少三个破折号。边界。BoundaryType = LaneBoundaryType.Dashed;结束边界(绑定)=边界;结束结束

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

函数我= takeSnapshot(框架、传感器、sensorOut)%解压输入leftEgoBoundary = sensorOut.leftEgoBoundary;rightEgoBoundary = sensorOut.rightEgoBoundary;位置= sensorOut.vehicleLocations;xVehiclePoints = sensorOut.xVehiclePoints;bboxes = sensorOut.vehicleBoxes;frameWithOverlays = insertLaneBoundary(框架、leftEgoBoundary、传感器、xVehiclePoints“颜色”,“红色”);frameWithOverlays = insertLaneBoundary (xVehiclePoints frameWithOverlays rightEgoBoundary,传感器,“颜色”,“绿色”);frameWithOverlays = insertVehicleDetections (frameWithOverlays、位置bboxes);我= frameWithOverlays;结束

另请参阅

应用程序

功能

对象

相关的话题