动手学无人驾驶(3):基于激光雷达3D多目标追踪

上一篇博客介绍了无人驾驶中的车辆检测算法(YOLO模型),该检测是基于图像进行的2D目标检测。在无人驾驶环境感知传感器中还有另一种重要的传感器:激光雷达。今天就介绍一篇无人驾驶中基于激光雷达目标检测的3D多目标追踪论文,使用的数据集也是KITTI数据集,使用的目标检测算法是PointRCNN。该3D多目标追踪系统不需要使用GPU且取得了最快的处理速度(214.7FPS)。

论文地址:A Baseline for 3D Multi-Object Tracking

Github地址:https://github.com/xinshuoweng/AB3DMOT


大家有时间可以看看这个视频,这是论文作者此前分享的一个3D多目标追踪报告,视频地址:https://www.bilibili.com/video/BV1DD4y1Q7JG/

3D Multi-Object Tracking: A Baseline and New Evaluation Metrics

文章目录

      • 1.概述
      • 2.方法
        • A. 3D 目标检测
        • B. 3D 卡尔曼滤波---状态预测
        • C. 数据关联
        • D. 3D卡尔曼滤波-状态更新
        • E. Birth and Death内存
      • 3. 测试结果

1.概述

无论是在自动驾驶或辅助机器人等实时应用中,3D多目标追踪(MOT)都是非常重要的技术环节。然而,在近期的一些3D多目标追踪研究当中更多的都是关注于追踪系统的准确率而忽略了其计算成本和复杂性。

在本文中作者提出了一种简单而又准确的实时3D MOT基线系统。本文使用了现成的3D目标检测器从LiDAR点云数据中获取对应目标3D bounding box。 然后,将3D卡尔曼滤波器和匈牙利算法结合起来进行目标状态估计和数据关联。为了评估提出的基线系统,论文在原有的KITTI官方2D MOT评价指标上进行了扩展,提出了三个新的3D MOT评价指标,本文主要贡献有:

  • 设计了一种简单而又准确的实时3D MOT系统;
  • 对KITTI官方2D MOT评价指标进行扩展,提出了新的3D MOT评价指标;
  • 在KITTI评价工具上获得了最优的3D MOT性能,在2D MOT评价工具上获得了最快的处理速度(如下图所示)。

在这里插入图片描述


2.方法

3D MOT的目的是对一段连续数据中的3D 检测目标进行关联。在本系统中,需要使用当前帧中的检测结果以及上一帧中的关联轨迹。系统结构如下图所示,由5个部分组成:

(A)3D检测模块用于对LiDAR点云数据进行目标检测;

(B)3D卡尔曼滤波模块用于预测关联轨迹当前帧的状态;

(C)数据关联模块用于对检测模块输出结果和卡尔曼滤波模块输出的轨迹进行匹配关联;

(D)3D卡尔曼滤波根据检测结果更新匹配轨迹的状态

(E)birth和death内存模块用于生成新的轨迹和删除未匹配的目标轨迹。

在这里插入图片描述
除了3D目标检测块以外,3D MOT系统不需要进行训练,可直接使用。


A. 3D 目标检测

在这里,直接使用在KITTI 3D数据及上训练好的3D 检测模型(即:PointRCNN)作为目标检测模块。

下面是一些术语规定,假设当前为ttt时刻,3D检测模块输出是:Dt={Dt1,Dt2,...,Dtnt}D_{t}=\{{D_{t}^{1}, D_{t}^{2}, ...,D_{t}^{n_{t}}}\}Dt={Dt1,Dt2,...,Dtnt},(ntn_tntttt时刻中检测目标数量)。每一个检测目标向量表示形式为:(x,y,z,θ,l,w,h,s)(x, y, z,\theta, l, w, h, s)(x,y,z,θ,l,w,h,s),即目标中心坐标(x,y,z)(x,y,z)(x,y,z),目标尺寸(l,w,h)(l,w,h)(l,w,h),偏航角θ\thetaθ以及置信度sss


B. 3D 卡尔曼滤波—状态预测

为了预测目标从上一帧到当前帧的轨迹状态,这里选择使用的运动模型为恒速运动模型,忽略了相邻帧内的目标位置移动。

具体地,我们使用11维向量来表示目标轨迹的状态T=(x,y,z,θ,l,w,h,s,vx,vy,vz)T=(x, y, z, \theta, l, w, h, s, v_{x}, v_{y,} v_{z})T=(x,y,z,θ,l,w,h,s,vx,vy,vz),附加的3个变量表示目标在3个维度上的运动速度。

在每一帧,所有t-1帧的关联轨迹为Tt−1={Tt−11,Tt−12,⋯,Tt−1mt−1}T_{t-1}=\left\{T_{t-1}^{1}, T_{t-1}^{2}, \cdots, T_{t-1}^{m_{t-1}}\right\}Tt1={Tt11,Tt12,,Tt1mt1}mt−1m_{t-1}mt1是t-1时刻的轨迹数量)将会被传播到下一帧ttt,用TestT_{est}Test表示。由恒速运动模型可以推出:
xest=x+vxyest=y+vyzest=z+vzx_{est}=x+v_x \quad y_{est}=y+v_y \quad z_{est}=z+v_z xest=x+vxyest=y+vyzest=z+vz
因此,Tt−1T_{t-1}Tt1中的每个轨迹Tt−1iT^i_{t-1}Tt1i传播到t帧中的预测状态将是Testi=(xest,yest,zest,θ,l,w,h,s,vx,vy,vz)T_{\mathrm{est}}^{i}=\left(x_{\mathrm{est}}, y_{\mathrm{est}}, z_{\mathrm{est}}, \theta, l, w, h, s, v_{x}, v_{y}, v_{z}\right)Testi=(xest,yest,zest,θ,l,w,h,s,vx,vy,vz),轨迹数据将会用于之后的关联模块。

3D 卡尔曼滤波的代码如下:

class KalmanBoxTracker(object):"""This class represents the internel state of individual tracked objects observed as bbox."""count = 0def __init__(self, bbox3D, info):"""Initialises a tracker using initial bounding box."""# define constant velocity modelself.kf = KalmanFilter(dim_x=10, dim_z=7)       self.kf.F = np.array([[1,0,0,0,0,0,0,1,0,0],      # state transition matrix[0,1,0,0,0,0,0,0,1,0],[0,0,1,0,0,0,0,0,0,1],[0,0,0,1,0,0,0,0,0,0],  [0,0,0,0,1,0,0,0,0,0],[0,0,0,0,0,1,0,0,0,0],[0,0,0,0,0,0,1,0,0,0],[0,0,0,0,0,0,0,1,0,0],[0,0,0,0,0,0,0,0,1,0],[0,0,0,0,0,0,0,0,0,1]])     self.kf.H = np.array([[1,0,0,0,0,0,0,0,0,0],      # measurement function,[0,1,0,0,0,0,0,0,0,0],[0,0,1,0,0,0,0,0,0,0],[0,0,0,1,0,0,0,0,0,0],[0,0,0,0,1,0,0,0,0,0],[0,0,0,0,0,1,0,0,0,0],[0,0,0,0,0,0,1,0,0,0]])# # with angular velocity# self.kf = KalmanFilter(dim_x=11, dim_z=7)       # self.kf.F = np.array([[1,0,0,0,0,0,0,1,0,0,0],      # state transition matrix#                       [0,1,0,0,0,0,0,0,1,0,0],#                       [0,0,1,0,0,0,0,0,0,1,0],#                       [0,0,0,1,0,0,0,0,0,0,1],  #                       [0,0,0,0,1,0,0,0,0,0,0],#                       [0,0,0,0,0,1,0,0,0,0,0],#                       [0,0,0,0,0,0,1,0,0,0,0],#                       [0,0,0,0,0,0,0,1,0,0,0],#                       [0,0,0,0,0,0,0,0,1,0,0],#                       [0,0,0,0,0,0,0,0,0,1,0],#                       [0,0,0,0,0,0,0,0,0,0,1]])     # self.kf.H = np.array([[1,0,0,0,0,0,0,0,0,0,0],      # measurement function,#                       [0,1,0,0,0,0,0,0,0,0,0],#                       [0,0,1,0,0,0,0,0,0,0,0],#                       [0,0,0,1,0,0,0,0,0,0,0],#                       [0,0,0,0,1,0,0,0,0,0,0],#                       [0,0,0,0,0,1,0,0,0,0,0],#                       [0,0,0,0,0,0,1,0,0,0,0]])# self.kf.R[0:,0:] *= 10.   # measurement uncertainty# state uncertainty, give high uncertainty to the unobservable initial velocities, covariance matrixself.kf.P[7:, 7:] *= 1000. 	                     self.kf.P *= 10.# self.kf.Q[-1,-1] *= 0.01    # process uncertaintyself.kf.Q[7:, 7:] *= 0.01self.kf.x[:7] = bbox3D.reshape((7, 1))self.time_since_update = 0self.id = KalmanBoxTracker.countKalmanBoxTracker.count += 1self.history = []self.hits = 1           # number of total hits including the first detectionself.hit_streak = 1     # number of continuing hit considering the first detectionself.first_continuing_hit = 1self.still_first = Trueself.age = 0self.info = info        # other info associateddef update(self, bbox3D, info): """ Updates the state vector with observed bbox."""self.time_since_update = 0self.history = []self.hits += 1self.hit_streak += 1          # number of continuing hitif self.still_first:self.first_continuing_hit += 1      # number of continuing hit in the fist time######################### orientation correctionif self.kf.x[3] >= np.pi: self.kf.x[3] -= np.pi * 2    # make the theta still in the rangeif self.kf.x[3] < -np.pi: self.kf.x[3] += np.pi * 2new_theta = bbox3D[3]if new_theta >= np.pi: new_theta -= np.pi * 2    # make the theta still in the rangeif new_theta < -np.pi: new_theta += np.pi * 2bbox3D[3] = new_thetapredicted_theta = self.kf.x[3]if abs(new_theta - predicted_theta) > np.pi / 2.0 and abs(new_theta - predicted_theta) < np.pi * 3 / 2.0:     			# if the angle of two theta is not acute angleself.kf.x[3] += np.pi       if self.kf.x[3] > np.pi: self.kf.x[3] -= np.pi * 2    # make the theta still in the rangeif self.kf.x[3] < -np.pi: self.kf.x[3] += np.pi * 2# now the angle is acute: < 90 or > 270, convert the case of > 270 to < 90if abs(new_theta - self.kf.x[3]) >= np.pi * 3 / 2.0:if new_theta > 0: self.kf.x[3] += np.pi * 2else: self.kf.x[3] -= np.pi * 2#########################     # flipself.kf.update(bbox3D)if self.kf.x[3] >= np.pi: self.kf.x[3] -= np.pi * 2    # make the theta still in the rageif self.kf.x[3] < -np.pi: self.kf.x[3] += np.pi * 2self.info = infodef predict(self):       """Advances the state vector and returns the predicted bounding box estimate."""self.kf.predict()      if self.kf.x[3] >= np.pi: self.kf.x[3] -= np.pi * 2if self.kf.x[3] < -np.pi: self.kf.x[3] += np.pi * 2self.age += 1if (self.time_since_update > 0):self.hit_streak = 0self.still_first = Falseself.time_since_update += 1self.history.append(self.kf.x)return self.history[-1]def get_state(self):"""Returns the current bounding box estimate."""return self.kf.x[:7].reshape((7, ))

C. 数据关联

为了将检测结果DtD_tDt与预测轨迹TestT_{est}Test进行匹配,我们将使用匈牙利算法。

维度为(mt−1,nt)(m_{t-1}, n_t)(mt1,nt)的矩阵将用来计算每对DtD_tDtTestT_{est}Test3DIoU3D IoU3DIoU或目标中心距离。然后,使用匈牙利算法来处理二分图匹配问题。除此之外,当3DIoU3D IoU3DIoU小于IoUminIoU_{min}IoUmin时或目标中心距离大于distmaxdist_{max}distmax时,将拒绝进行匹配。数据关联模块的输出将分为4类:

Tmatch={Tmatch1,Tmatch2,..,Tmatchwt}Dmatch={Dmatch1,Dmatch2,..,Dmatchwt}Tunmatch={Tunmatch1,Tunmatch2,..,Tunmatchmt−1−wt}Dunmatch={Dunmatch1,Dunmatch2,..,Dunmatchnt−wt}T_{match}=\{{T^1_{match},T^2_{match},..,T^{wt}_{match}}\}\\ D_{match}=\{{D^1_{match},D^2_{match},..,D^{wt}_{match}}\}\\ T_{unmatch}=\{{T^1_{unmatch},T^2_{unmatch},..,T^{m_{t-1}-wt}_{unmatch}}\}\\ D_{unmatch}=\{{D^1_{unmatch},D^2_{unmatch},..,D^{nt-wt}_{unmatch}}\}Tmatch={Tmatch1,Tmatch2,..,Tmatchwt}Dmatch={Dmatch1,Dmatch2,..,Dmatchwt}Tunmatch={Tunmatch1,Tunmatch2,..,Tunmatchmt1wt}Dunmatch={Dunmatch1,Dunmatch2,..,Dunmatchntwt}
这里wtw_twt是匹配目标数量。

def associate_detections_to_trackers(detections, trackers, iou_threshold=0.01):   """Assigns detections to tracked object (both represented as bounding boxes)detections:  N x 8 x 3trackers:    M x 8 x 3Returns 3 lists of matches, unmatched_detections and unmatched_trackers"""if (len(trackers)==0): return np.empty((0, 2), dtype=int), np.arange(len(detections)), np.empty((0, 8, 3), dtype=int)    iou_matrix = np.zeros((len(detections), len(trackers)), dtype=np.float32)for d, det in enumerate(detections):for t, trk in enumerate(trackers):iou_matrix[d, t] = iou3d(det, trk)[0]             # det: 8 x 3, trk: 8 x 3# matched_indices = linear_assignment(-iou_matrix)      # hougarian algorithm, compatible to linear_assignment in sklearn.utilsrow_ind, col_ind = linear_sum_assignment(-iou_matrix)      # hougarian algorithmmatched_indices = np.stack((row_ind, col_ind), axis=1)unmatched_detections = []for d, det in enumerate(detections):if (d not in matched_indices[:, 0]): unmatched_detections.append(d)unmatched_trackers = []for t, trk in enumerate(trackers):if (t not in matched_indices[:, 1]): unmatched_trackers.append(t)#filter out matched with low IOUmatches = []for m in matched_indices:if (iou_matrix[m[0], m[1]] < iou_threshold):unmatched_detections.append(m[0])unmatched_trackers.append(m[1])else: matches.append(m.reshape(1, 2))if (len(matches) == 0): matches = np.empty((0, 2),dtype=int)else: matches = np.concatenate(matches, axis=0)return matches, np.array(unmatched_detections), np.array(unmatched_trackers)

D. 3D卡尔曼滤波-状态更新

由于TmatchT_{match}Tmatch的不确定性,我们根据检测结果DmatchD_{match}DmatchTmatchT_{match}Tmatch整个状态空间的每个轨迹进行更新,最后获得ttt帧时刻的关联轨迹Tt={Tt1,Tt2,⋯,Ttwt}T_{t}=\left\{T_{t}^{1}, T_{t}^{2}, \cdots, T_{t}^{w_{t}}\right\}Tt={Tt1,Tt2,,Ttwt}

根据贝叶斯规则,更新后的每一条轨迹Ttk=(x′,y′,z′,θ′,l′,w′,h′,s′,vx′,vy,′vz′)T_{t}^k=(x', y', z', \theta', l', w', h',s', v_{x}', v_{y,}' v_{z}')Ttk=(x,y,z,θ,l,w,h,s,vx,vy,vz)是状态空间TmatchkT_{match}^kTmatchkDmatchkD_{match}^kDmatchk的加权和,这的权重是由轨迹和检测的不确定性所决定的。

除此之外,我们发现原始的加权和对确定目标方向效果一般。对于匹配目标TtkT_{t}^kTtk,其检测结果上的方向和运动轨迹方向可能完全相反,相差π\piπ个相位。但事实上,目标都是平缓移动,不可能在一帧中改变移动方向。从结果上来看,TtkT_t^kTtk目标的加权轨迹方向应该位于DmatchkD_{match}^kDmatchkTmatchkT_{match}^kTmatchk之间。这往往将会导致比较低的3DIoU3D IoU3DIoU值。为此,我们提出一个方向修正技术,当两者相位相差超过π/2\pi/2π/2时,我们在TmatchkT_{match}^kTmatchk上添加π\piπ个相位,以便TmatchkT_{match}^kTmatchkDmatchkD_{match}^kDmatchk方向能大致一致。


E. Birth and Death内存

因为现存的目标可能会消失以及新的目标可能会进入画面,因此需要一个新的模块来管理出现和消失的轨迹。一方面,我们认为所有不匹配的检测可能会进入帧中,为了避免假阳性追踪,当在BirminBir_{min}Birmin中持续检测到DunmatchpD_{unmatch}^pDunmatchp时,将会生成 一条新的轨迹TnewpT_{new}^pTnewp。一旦新的轨迹产生,我们将初始化TnewpT_{new}^pTnewp作为最新的测量DunmatchpD_{unmatch}^pDunmatchp,三个方向的速度初始化为0。

另一方面,我们认为所有不匹配的轨迹可能会离开,为了避免删除真阳性的轨迹,我们在AgemaxAge_{max}Agemax帧中持续追踪不匹配轨迹TunmatchqT_{unmatch}^qTunmatchq直到从关联轨迹删除。


3. 测试结果

在KITTI上的追踪结果如下,这里只给出了可视化结果,详细结果可查阅论文。

在这里插入图片描述在这里插入图片描述在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/439757.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

换种方法学操作系统,轻松入门Linux内核

计算机已成为现代人日常工作、学习和生活中必不可少的工具。操作系统是计算机之魂&#xff0c;作为用户使用计算机的接口&#xff0c;它负责调度执行各个用户程序&#xff0c;使计算机完成特定的任务&#xff1b;作为计算机硬件资源的管理者&#xff0c;它负责协调计算机中各类…

Apollo进阶课程㊶丨Apollo实战——本机演示实战

原文链接&#xff1a;进阶课程㊶丨Apollo实战——本机演示实战 Apollo是一个开放的、完整的、安全的平台&#xff0c;将帮助汽车行业及自动驾驶领域的合作伙伴结合车辆和硬件系统&#xff0c;快速搭建一套属于自己的自动驾驶系统。 上周阿波君为大家详细介绍了「进阶课程㊵丨A…

java常见异常类图(分类了Error/RuntimeExecption、check Exception)

Error&#xff1a;表示由JVM所侦测到的无法预期的错误&#xff0c;由于这是属于JVM层次的严重错误&#xff0c;导致JVM无法继续执行&#xff0c;因此&#xff0c;这是不可捕捉到的&#xff0c;无法采取任何恢复的操作&#xff0c;顶多只能显示错误信息。Exception&#xff1a;表…

Apollo进阶课程㊷丨Apollo实战——车辆与循迹驾驶能力实战

原文链接&#xff1a;进阶课程㊷丨Apollo实战——车辆与循迹驾驶能力实战 循迹自动驾驶是指让车辆按照录制好的轨迹线进行自动驾驶&#xff0c;其涉及到自动驾驶中最基本的底盘线控能力、定位能力、控制能力&#xff0c;是自动驾驶系统的一个最小子集。 上周阿波君为大家详细介…

【HDU - 5961】传递(图,思维,暴力,枚举点)

题干&#xff1a; 我们称一个有向图G是传递的&#xff0c;当且仅当对任意三个不同的顶点a,,若G中有 一条边从a到b且有一条边从b到c ,则G中同样有一条边从a到c。 我们称图G是一个竞赛图&#xff0c;当且仅当它是一个有向图且它的基图是完全图。换句 话说&#xff0c;将完全图每…

Java--对象内存布局

在HotSpot虚拟机中&#xff0c;对象在内存中的存储布局可以分为3块区域&#xff1a;对象头部、实例数据、对齐填充。 一、对象头部Header的布局 Mark WordClass 指针在32位系统下&#xff0c;上面两部分各占4B; 在64位系统中&#xff0c;Mark Work占4B&#xff0c;class指针在…

Apollo进阶课程㊸丨Apollo实战——障碍物感知和路径规划能力实战

原文链接;进阶课程㊸丨Apollo实战——障碍物感知和路径规划能力实战 环境感知在自动驾驶汽车应用中占据了核心地位。一辆车要实现自动驾驶&#xff0c;障碍物感知是最基础也是最核心的功能。 上周阿波君为大家详细介绍了「进阶课程㊷丨Apollo实战——车辆与循迹驾驶能力实战」…

3.1)深度学习笔记:机器学习策略(1)

目录 1&#xff09;Why ML Strategy 2&#xff09;Orthogonalization 3&#xff09;Single number evaluation metric 4&#xff09;Satisficing and optimizing metrics 5&#xff09;训练/开发/测试集划分&#xff08;Train/dev/test distributions&#xff09; 6&…

接口和抽象类是否继承了Object

我们先看一下Java的帮助文档对于Object的描述&#xff1a; Class Object is the root of the class hierarchy. Every class has Object as a superclass. All objects, including arrays, implement the methods of this class. Object 类是类层次结构的根类。每个类都使用 …

3.2)深度学习笔记:机器学习策略(2)

目录 1&#xff09;Carrying out error analysis 2&#xff09;Cleaning up Incorrectly labeled data 3&#xff09;Build your first system quickly then iterate 4&#xff09;Training and testing on different distributios 5&#xff09;Bias and Variance with m…

4.1)深度卷积网络:卷积神经网络基础

目录 1&#xff09;Computer vision 2&#xff09;Edge detection example&#xff08;理解&#xff09; 3&#xff09;More edge detection 4&#xff09;Padding&#xff08;重点&#xff09; 5&#xff09;Strided convolutions&#xff08;重点&#xff09; 6&#x…

4.2)深度卷积网络:实例研究

目录 1&#xff09;Why look at case studies? 2&#xff09;Classic networks&#xff08;理解&#xff09; 3&#xff09;ResNets&#xff08;理解&#xff09; 4&#xff09;Why ResNets work?&#xff08;经典&#xff09; 5&#xff09;Networks in Networks and 1…

10种常见的软件架构模式

有没有想过要设计多大的企业规模系统&#xff1f;在主要的软件开发开始之前&#xff0c;我们必须选择一个合适的体系结构&#xff0c;它将为我们提供所需的功能和质量属性。因此&#xff0c;在将它们应用到我们的设计之前&#xff0c;我们应该了解不同的体系结构。 什么是架构模…

4.3)深度卷积网络:目标检测

目录 1&#xff09;Object localization&#xff08;重点&#xff09; 2&#xff09;Landmark detection 3&#xff09;Object detection 4&#xff09;Convolutional implementation of sliding windows 5&#xff09;Bounding box prediction&#xff08;重点&#xff0…

4.4)深度卷积网络:人脸识别和神经风格转换

目录 1&#xff09;What is face recognition? 2&#xff09;One-shot learning 3&#xff09;Siamese network 4&#xff09;Triplet Loss&#xff08;重点&#xff09; 5&#xff09;Face Verification and Binary Classification 6&#xff09;What is neural style …

一步步编写操作系统 35 内存为何要分页

一直以来我们都直接在内存分段机制下工作&#xff0c;目前未出问题看似良好&#xff0c;的确目前咱们的应用过于简单了&#xff0c;就一个loader在跑&#xff0c;能出什么问题呢。可是想像一下&#xff0c;当我们物理内存不足时会怎么办呢&#xff1f;比如系统里的应用程序过多…

《python深度学习》代码中文注释

《python深度学习》由Keras之父、现任Google人工智能研究员的弗朗索瓦•肖莱&#xff08;François Chollet&#xff09;执笔&#xff0c;详尽介绍了用Python和Keras进行深度学习的探索实践&#xff0c;包括计算机视觉、自然语言处理、生成式模型等应用。书中包含30多个代码示…

【BZOJ - 4754】独特的树叶(树哈希)

题干&#xff1a; JYY有两棵树A和B&#xff1a;树A有N个点&#xff0c;编号为1到N&#xff1b;树B有N1个点&#xff0c;编号为1到N1。JYY知道树B恰好是由树A加上一个叶 节点&#xff0c;然后将节点的编号打乱后得到的。他想知道&#xff0c;这个多余的叶子到底是树B中的哪一个…

一步步编写操作系统 36 一级页表与虚拟地址1

为了给大家说清楚分页机制&#xff0c;我们先在宏观上说下cpu地址变换过程&#xff0c;先让大家有个直观的印象&#xff0c;如果有不明白的地方也不要着急&#xff0c;适时地不求甚解&#xff0c;有助于从全局上将知识融会贯通&#xff08;这句话是我即兴说的&#xff0c;说得多…

动手学无人驾驶(4):基于激光雷达点云数据3D目标检测

上一篇文章《动手学无人驾驶&#xff08;3&#xff09;&#xff1a;基于激光雷达3D多目标追踪》介绍了3D多目标追踪&#xff0c;多目标追踪里使用的传感器数据为激光雷达Lidar检测到的数据&#xff0c;本文就介绍如何基于激光雷达点云数据进行3D目标检测。 论文地址&#xff1a…