主要内容

使用激光雷达检测、分类和跟踪车辆

这个例子展示了如何通过使用安装在车辆上的激光雷达传感器捕获的激光雷达点云数据来检测、分类和跟踪车辆。本例中使用的激光雷达数据记录自高速公路驾驶场景。方法对点云数据进行分段,以确定对象的类别PointSeg网络。采用联合概率数据关联(JPDA)跟踪器和交互式多模型滤波器对被检测车辆进行跟踪。

概述

感知模块在实现ADAS系统车辆的完全自动驾驶方面发挥着重要作用。激光雷达和摄像机是感知工作流程中必不可少的传感器。激光雷达善于提取精确的物体深度信息,而相机能提供丰富而详细的环境信息,有助于对物体进行分类。

本例主要包括以下几个部分:

  • 地平面分割

  • 语义分割

  • 定向包围盒配件

  • 跟踪定向包围框

流程图提供了整个系统的概述。

加载数据

激光雷达传感器以有组织的格式或无组织的格式生成点云数据。本例中使用的数据是使用Ouster OS1激光雷达传感器收集的。该激光雷达产生一个有组织的点云与64个水平扫描线。点云数据由三个通道组成,分别表示x-,y- - - - - -,z-点的坐标。每个通道的大小为64 × 1024。使用helper函数helperDownloadData下载数据并将其加载到MATLAB®工作空间中。

注意:这个下载过程可能需要几分钟。

[ptClouds,pretrainedModel] = helperDownloadData;

地平面分割

的混合方法segmentGroundFromLidarData(计算机视觉工具箱)而且pcfitplane(计算机视觉工具箱)功能。首先,估计地平面参数segmentGroundFromLidarData函数。估计的地面平面沿车辆方向被分成条状,以拟合平面,使用pcfitplane对每条都起作用。这种混合方法以分段方式稳健地拟合地平面,并处理点云中的变化。

负载点云%ptCloud = ptClouds{1};定义裁剪点云的ROIxLimit = [-30,30];yLimit = [-12,12];zLimit = [-3,15];roi = [xLimit,yLimit,zLimit];提取地平面[nonGround,ground] = helperExtractGround(ptCloud,roi);图;pcshowpair (nonGround、地面);传奇({{白}Nonground \颜色的“地面颜色\{白}”},“位置”“northeastoutside”);

语义分割

本例使用预训练的PointSeg网络模型。PointSeg是一个端到端的实时语义分割网络,用于训练对象类,如汽车、卡车和背景。来自网络的输出是一个被屏蔽的图像,每个像素按其类标记。此掩码用于过滤点云中不同类型的对象。网络的输入是五通道图像,即X y z,强度和范围。有关网络或如何训练网络的更多信息,请参阅基于PointSeg深度学习网络的激光雷达点云语义分割(激光雷达工具箱)的例子。

准备输入数据

helperPrepareData函数从加载的点云数据生成五通道数据。

加载并可视化一个样本帧frame = helppreparedata (ptCloud);图;次要情节(5、1、1);显示亮度图像(帧(:,:1));标题(“X频道”);次要情节(5、1、2);显示亮度图像(帧(::2));标题(“Y”频道);次要情节(5、1,3);显示亮度图像(帧(:,:,3));标题(“Z频道”);次要情节(5、1、4);显示亮度图像(帧(::4));标题(“强度通道”);次要情节(5、1、5);显示亮度图像(帧(::5));标题(“范围通道”);

对加载的预训练网络中的一帧进行正向推理。

如果~ (“净”“var”) net = pretrainedModel.net;结束定义类类= [“背景”“汽车”“卡车”];定义颜色地图lidarColorMap = [0.98 0.98 0.00 .%未知0.01 0.98 0.01%绿色汽车0.01 0.01 0.98%蓝色为摩托车];%前进速度pxdsResults = semanticseg(帧,网络);带有分段输出的覆盖强度图像segmentedImage = labeloverlay(uint8(frame(:,:,4)),pxdsResults,“Colormap”lidarColorMap,“透明”, 0.5);%显示结果图;imshow (segmentedImage);helperPixelLabelColorbar (lidarColorMap、类);

使用生成的语义掩码来过滤包含卡车的点云。类似地,为其他类过滤点云。

truckIndices = pxdsResults ==“卡车”;truckPointCloud = select(non - ground,truckIndices,“OutputSize”“全部”);%裁剪点云以获得更好的显示croppdtcloud = select(ptCloud,findPointsInROI(ptCloud,roi));croppedTruckPtCloud = select(truckPointCloud,findPointsInROI(truckPointCloud,roi));显示接地点和非接地点图;pcshowpair (croppedPtCloud croppedTruckPtCloud);传奇({{白}Nonvehicle \颜色的“{白}\颜色车”},“位置”“northeastoutside”);

聚类和包围框拟合

在提取出不同对象类别的点云后,采用欧氏聚类方法对目标进行聚类pcsegdist(计算机视觉工具箱)函数。为了将所有属于单一聚类的点进行分组,将作为聚类获得的点云作为非地点中生长区域的种子点。使用findNearestNeighbors(计算机视觉工具箱)函数遍历所有点以增长区域。方法将提取的聚类拟合在l形包围框中pcfitcuboid(激光雷达工具箱)函数。从自上而下的角度看,这些车辆群的形状类似字母L。这一特征有助于估计车辆的方向。有向包围盒拟合有助于估计目标的航向角,在路径规划和交通操纵等应用中具有重要意义。

簇的长方体边界也可以通过寻找每个方向上的最小和最大空间范围来计算。但是,该方法无法估计被探测车辆的方向。两种方法的区别如图所示。

[labels,numClusters] = pcsegdist(croppedTruckPtCloud,1);定义长方体参数参数= 0 (0,9);clusterIndex = 1:numClusters ptsInCluster = labels == clusterIndex;pc = select(croppedTruckPtCloud,ptsInCluster);location = pc.Location;Xl = (max(location(:,1)) - min(location(:,1)));Yl = (max(location(:,2)) - min(location(:,2)));Zl = (max(location(:,3)) - min(location(:,3)));过滤小包围框如果size(location,1)*size(location,2) > 20 && any(any(pc.Location)) && xl > 1 && yl > 1索引= 0 (0,1);objectPtCloud = pointCloud(位置);i = 1:size(location,1) seedPoint = location(i,:);indexes (end+1) = findNearestNeighbors(nonGround,seedPoint,1);结束删除重叠索引索引=唯一的(索引);适合定向包围框model = pcfitcuboid(select(non - ground, indexes));params(end+1,:) = model.Parameters;结束结束显示点云和检测到的包围框图;pcshow (croppedPtCloud.Location croppedPtCloud.Location (:, 3));showShape (“长方体”参数,“颜色”“红色”“标签”“卡车”);

可视化设置

使用helperLidarObjectDetectionDisplay类以在一个窗口中可视化完整的工作流。可视化窗口的布局分为以下几个部分:

  1. 激光雷达距离图:点云二维图像作为距离图

  2. 分割图像:将语义分割网络生成的检测标签与强度图像或数据的第四通道叠加

  3. 定向包围盒检测:具有定向包围盒的三维点云

  4. 俯视图:带有定向包围框的点云的俯视图

display = helperLidarObjectDetectionDisplay;

循环数据

helperLidarObjectDetection类是封装了上面小节中提到的所有分割、聚类和包围框拟合步骤的包装器。使用findDetections函数提取检测到的对象。

初始化激光雷达目标检测器lidarDetector = helperLidarObjecDetector(“模型”净,“XLimits”xLimit,...“YLimit”yLimit,“ZLimit”, zLimit);准备5维激光雷达数据inputData = helperPrepareData(ptClouds);为可重复的结果设置随机数生成器S = rng(2018);初始化显示initializeDisplay(显示);numFrames = nummel (inputData);count = 1:numFrames获取当前数据input = inputData{count};rangeImage = input(:,:,5);从激光雷达数据中提取边界框[boundingBox,coloredPtCloud,pointLabels] = detectBbox(lidarDetector,input);%使用彩色点云更新显示updatePointCloud(显示、coloredPtCloud);%更新边界框updateBoundingBox()边界框(显示、大小);更新分段图像updateSegmentedImage(显示、pointLabels rangeImage);drawnow (“limitrate”);结束

跟踪定向包围框

在本例中,您使用联合概率数据关联(JPDA)跟踪器。时间步长dt设置为0.1秒,因为数据集以10 Hz捕获。跟踪器中使用的状态空间模型是基于一个带参数的长方体模型, x y z ϕ l w h .有关如何在激光雷达数据中跟踪包围框的详细信息,请参见使用激光雷达跟踪车辆:从点云到跟踪列表的例子。类提供了类信息ObjectAttributes的属性objectDetection对象.创建新音轨时,过滤器初始化函数,使用helper函数定义helperMultiClassInitIMMFilter使用检测的类来设置对象的初始尺寸。这有助于跟踪器根据轨道的尺寸调整边界盒测量模型。

使用这些参数设置一个JPDA跟踪器对象。

assignmentGate = [10 100];%分配阈值;confThreshold = [7 10];%历史日志的确认阈值delThreshold = [2 3];%历史逻辑删除阈值Kc = 1e-5;单位卷误报率%IMM过滤器初始化函数filterInitFcn = @ helpermulticlassinitmfilter;带有IMM滤波器的联合概率数据关联跟踪器追踪器=追踪器“FilterInitializationFcn”filterInitFcn,...“TrackLogic”“历史”...“AssignmentThreshold”assignmentGate,...“ClutterDensity”Kc,...“ConfirmationThreshold”confThreshold,...“DeletionThreshold”delThreshold,“InitializationThreshold”, 0);allTracks = struct([]);时间= 0;Dt = 0.1;定义测量噪声measNoise = blkdiag(0.25*eye(3),25,eye(3));numTracks =零(numFrames,2);

的单元格数组组合被检测到的对象objectDetection(自动驾驶工具箱)对象使用helperAssembleDetections函数。

display = helperLidarObjectDetectionDisplay;initializeDisplay(显示);count = 1:numFrames time = time + dt;获取当前数据input = inputData{count};rangeImage = input(:,:,5);从激光雷达数据中提取边界框[boundingBox,coloredPtCloud,pointLabels] = detectBbox(lidarDetector,input);将包围框组装到objectDetections中detections = helperAssembleDetections(boundingBox,measNoise,time);将检测传递给跟踪器如果~ isempty(检测)更新跟踪器[confirmedTracks,tentativeTracks,allTracks,info] =跟踪器(检测,时间);numTracks(count,1) =数字(confirmedTracks);结束%使用彩色点云更新显示updatePointCloud(显示、coloredPtCloud);更新分段图像updateSegmentedImage(显示、pointLabels rangeImage);如果轨道不为空,则更新显示如果~ isempty (confirmedTracks) updateTracks(显示、confirmedTracks);结束drawnow (“limitrate”);结束

总结

通过实例说明了如何在激光雷达数据上对装有定向包围盒的车辆进行检测和分类。您还学习了如何使用IMM筛选器跟踪具有多个类信息的对象。通过添加更多的训练数据,可以进一步改善语义分割结果。

金宝app支持功能

helperPrepareData

函数multiChannelData = helperPrepareData(input)%创建5通道数据x, y, z,强度和范围%的大小64 × 1024 × 5从pointCloud。如果isa(输入,“细胞”) numFrames = nummel(输入);multiChannelData = cell(1, numFrames);i = 1:numFrames inputData = input{i};x = inputData.Location(:,:,1);y = inputData.Location(:,:,2);z = inputData.Location(:,:,3);强度= inputData.Intensity;范围=根号x。²+ y.²+ z.²);multiChannelData{i} = cat(3, x, y, z,强度,范围);结束其他的x = input.Location(:,:,1);y = input.Location(:,:,2);z = input.Location(:,:,3);强度=输入。范围=根号x。²+ y.²+ z.²);multiChannelData = cat(3, x, y, z,强度,范围);结束结束

pixelLabelColorbar

函数一会helperPixelLabelColorbar(提出)在当前轴上添加一个颜色条。颜色条被格式化%显示带有颜色的类名。甘氨胆酸colormap(提出)将色条添加到当前图形。C = colorbar(“对等”甘氨胆酸,);使用类名作为标记。c.TickLabels = classNames;numClasses = size(cmap,1);%中心打勾标签。c.Ticks = 1/(numClasses*2):1/numClasses:1;删除标记。c.TickLength = 0;结束

helperExtractGround

函数[ptCloudNonGround,ptCloudGround] = helperExtractGround(ptCloudIn,roi)裁剪点云idx = findPointsInROI(ptCloudIn,roi);pc = select(ptCloudIn,idx,“OutputSize”“全部”);利用分段平面拟合得到指标的地平面[ptCloudGround,idx] = piecewiseplanefiting (pc,roi);nongrounddidx = true(size(pc.Location,[1,2]));nongrounddidx (idx) = false;ptCloudNonGround = select(pc, nongrounddidx,“OutputSize”“全部”);结束函数[groundPlane,idx] = piecewiseplanefiting (ptCloudIn,roi) groundPtsIdx =...segmentGroundFromLidarData (ptCloudIn...“ElevationAngleDelta”5,“InitialElevationAngle”15);groundPC = select(ptCloudIn,groundPtsIdx,“OutputSize”“全部”);将x轴分成3个区域segmentLength = (roi(2) - roi(1))/3;x1 = [roi(1),roi(1) + segmentLength];x2 = [x1(2),x1(2) + segmentLength];x3 = [x2(2),x2(2) + segmentLength];Roi1 = [x1,roi(3:end)];Roi2 = [x2,roi(3:end)];Roi3 = [x3,roi(3:end)];idxBack = findPointsInROI(groundPC,roi1);idxCenter = findPointsInROI(groundPC,roi2);idxForward = findPointsInROI(groundPC,roi3);%打破点云在前面和后面ptBack = select(groundPC,idxBack,“OutputSize”“全部”);ptForward = select(groundPC,idxForward,“OutputSize”“全部”);[~,inliersForward] = planeFit(ptForward);[~,inliersBack] = planeFit(ptBack);idx = [inliersForward;idxCenter;inliersBack];groundPlane = select(ptCloudIn, idx,“OutputSize”“全部”);结束函数[plane,inlinersIdx] = planeFit(ptCloudIn) [~,inlinersIdx, ~] = pcfitplane(ptCloudIn,1,[0,0,1]);plane = select(ptCloudIn,inlinersIdx,“OutputSize”“全部”);结束

helperAssembleDetections

函数mydetections = helperAssembleDetections(bboxes,measNoise,timestamp)组装包围框作为objectDetection的单元格数组Mydetections = cell(size(bboxes,1),1);I = 1:size(bboxes,1) classid = bboxes(I,end);lidarModel = [bboxes(i,1:3), bboxes(i,end-1), bboxes(i,4:6)];为了避免被跟踪器直接确认,ClassID被传递为% ObjectAttributes。mydetections{i} = objectDetection(时间戳,...lidarModel’,“MeasurementNoise”...measNoise,“ObjectAttributes”结构(“ClassID”classid));结束结束

helperDownloadData

函数[lidarData, pretrainedModel] = helperDownloadData outputFolder = fullfile(tempdir, pretrainedModel)批发价格指数的);url =“https://ssd.mathworks.com/金宝appsupportfiles/lidar/data/lidarSegmentationAndTrackingData.tar.gz”;lidarDataTarFile = fullfile(输出文件夹,“lidarSegmentationAndTrackingData.tar.gz”);如果~存在(lidarDataTarFile“文件”mkdir (outputFolder);websave (lidarDataTarFile、url);解压(lidarDataTarFile outputFolder);结束检查tar.gz文件是否已下载,但未解压如果~ (fullfile (outputFolder,存在“WPI_LidarData.mat”),“文件”)解压(lidarDataTarFile outputFolder);结束加载激光雷达数据data = load(fullfile(outputFolder)“highwayData.mat”));lidarData = data.ptCloudData;下载预训练模型url =“https://ssd.mathworks.com/金宝appsupportfiles/lidar/data/pretrainedPointSegModel.mat”;modelFile = fullfile(输出文件夹,“pretrainedPointSegModel.mat”);如果~存在(modelFile“文件”) websave (modelFile url);结束pretrainedModel = load(fullfile(outputFolder)“pretrainedPointSegModel.mat”));结束

参考文献

[1]张晓,徐文达,董驰宇,John M. Dolan,“基于激光扫描仪的高效l型拟合车辆检测”,IEEE智能车辆研讨会,2017年6月

[2]王勇,石涛,云P., Tai L.,刘敏,“Pointseg:基于三维激光雷达点云的实时语义分割”,arXiv预印本:1807.06288,2018。