如何在LiDAR点云上进行3D对象检测

该项目将借助kv260上的pynq-dpu覆盖,从而能够使我们在lidar点云上进行3d对象检测比以往任何时候都更加高效!
背景
在构建自动驾驶汽车、自动导航机器人和其他现实世界的应用程序时,环境感知起着不可或缺的作用。
为什么要在点云上进行3d对象检测?
虽然基于深度学习的相机数据二维对象检测显示出很高的准确性,但它可能不是有效的活动,如定位、测量对象之间的距离和计算深度信息。
lidar传感器生成的点云提供对象的3d信息,以更有效地定位对象并表征形状。因此,点云上的3d对象检测正在各种应用中出现,尤其是在自动驾驶方面。
尽管如此,设计基于lidar的3d对象检测系统仍具有挑战性。首先,此类系统需要在模型推理中进行大量计算。其次,由于点云数据是不规则的,处理管道需要预处理和后处理才能提供端到端的感知结果。
kv260与3d物体检测系统完美匹配。模型推理的昂贵计算可以卸载到kv260的可编程逻辑部分并由其加速,而kv260强大的arm内核能够处理预处理和后处理任务。
设计概述
我们现在讨论选择的用于点云上3d对象检测的深度学习模型以及包括软件和硬件的系统概述。
网络架构
作为对现有工作的完整性检查,我们选择了基于resnet的关键点特征金字塔网络(kfpn),这是第一个在kitti基准上具有最先进性能的单目3d检测实时系统。特别是,我们采用了它在点云上的开源pytorch实现,称为sfa3d。
kv260 上的 pynq-dpu
之所以我们使用xilinx 开发板的 ubuntu desktop 20.04.3 lts而不是 petalinux 作为 kv260 上的操作系统,是因为 ubuntu 是一个很好的开发环境,用于安装预处理点云和后处理结果所需的软件包。另一方面,kv260 对 pynq 和 dpu 覆盖的支持避免了从头设计高效的 dpu,使我们能够在 python 环境下工作。这在很大程度上简化了基于 cpu/gpu 的深度学习实现向 kv260 的迁移。
设置环境
按照官方指南将ubuntu镜像安装到kv260,然后参考github在ubuntu操作系统中安装pynq 。git 通过执行以下命令克隆所有必需的文件并将所需的包安装到板上。
git clone https://github.com/soldierchen/dpu-accelerated-3d-object-detection-on-point-clouds.git
cd dpu-accelerated-3d-object-detection-on-point-clouds
pip install -r requirements.txt
在这里,我们需要 pytorch 1.4,因为 pynq dpu 的 vart 是 v1.4。
数据准备
需要下载的数据包括:
velodyne 点云(29 gb)
对象数据集的训练标签(5 mb)
对象数据集的相机校准矩阵(16 mb)
对象数据集的左侧彩色图像(12 gb) (仅用于可视化目的)
要使用 3d 框可视化 3d 点云,让我们执行:
cd model_quant_compile/data_process/
python kitti_dataset.py
模型训练
python train.py --gpu_idx 0
该命令使用一个 gpu 进行训练,但它支持分布式训练。此外,您可以选择 fpn_resnet 或 resnet 作为目标模型。训练后的模型将存储在名为“model_restnet/fpn_resnet_epoch_#”的检查点文件夹中。根据您的硬件,epoch 可以从 10 到 300,精度越高越好。
模型量化和编译
同样,由于 pynq 的 vart 是 v1.4,我们需要 vitis ai v1.4 而不是最新版本(v2.0)来进行模型量化。
# install the docker at first (if not stalled)
docker pull xilinx/vitis-ai-cpu:1.4.1.978  
# run the docker
./docker_run.sh xilinx/vitis-ai-cpu:1.4.1.978
然后我们使用以下命令量化模型:
# activate the pytorch environment
conda activate vitis-ai-pytorch 
# install required packages
pip install -r requirements.txt
# configure the quant_mode to calib
ap.add_argument('-q',  '--quant_mode', type=str, default='calib',    choices=['calib','test'], help='quantization mode (calib or test). default is calib')
# here, it quantize the example model: model_resnet_18_epoch_10.pth
python quantize.py 
# configure the quant_mode to test
ap.add_argument('-q',  '--quant_mode', type=str, default='test',    choices=['calib','test'], help='quantization mode (calib or test). default is calib')
# here, it outputs the quantized model.
python quantize.py
接下来,我们将编译模型:
./compile.sh zcu102 build/
不要介意 zcu102 与 kv260 共享相同的 dpu 架构。您将看到成功编译的以下消息:
到目前为止,我们得到了可以在 dpu 上执行的编译 xmodel,在 kv260 上过度执行。接下来,我们将其部署在板上并开发应用程序代码。
kv260部署
按照官方指南,我们先在kv260上搭建好ubuntu操作系统。然后,我们按照pynq-dpu github在板上安装 python 。
搭建好板子后,我们需要安装git,将代码克隆到板子上,并将编译好的xmodel复制到文件夹中。
应用程序代码设计
这里我们将介绍如何调用并与 dpu 接口进行推理。
我们首先加载 dpu 覆盖和自定义的 xmodel。然后,重要的是,必须知道输入和输出张量信息才能与数据集协调。在这里,我们只有一个张量作为输入,五个张量作为输出。相应地分配输入和输出缓冲区。
# load model and overly 
overlay = dpuoverlay(dpu.bit)
overlay.load_model(./cnn_zcu102.xmodel)
dpu = overlay.runner
# get tensor information
inputtensors = dpu.get_input_tensors()
outputtensors = dpu.get_output_tensors()
shapein = tuple(inputtensors[0].dims)
outputsize = int(outputtensors[0].get_data_size() / shapein[0])
shapeout = tuple(outputtensors[0].dims)
shapeout1 = tuple(outputtensors[1].dims)
shapeout2 = tuple(outputtensors[2].dims)
shapeout3 = tuple(outputtensors[3].dims)
shapeout4 = tuple(outputtensors[4].dims)
# allocate input and output buffers. 
# note the output is a list of five tensors.
output_data = [np.empty(shapeout, dtype=np.float32, order=c),
np.empty(shapeout1, dtype=np.float32, order=c),
np.empty(shapeout2, dtype=np.float32, order=c),
np.empty(shapeout3, dtype=np.float32, order=c),
np.empty(shapeout4, dtype=np.float32, order=c)]
# the input is only one tensor.
input_data = [np.empty(shapein, dtype=np.float32, order=c)]
image = input_data[0]
一次性推理的过程封装在下面的函数中。在这里,我们将输入张量置换为 dpu 输入张量的形状,并将张量置换为后处理所需的形状。这对于正确的结果至关重要。
def do_detect(dpu, shapein, image, input_data, output_data, configs, bevmap, is_front):
if not is_front:
    bevmap = torch.flip(bevmap, [1, 2])
input_bev_maps = bevmap.unsqueeze(0).to(cpu, non_blocking=true).float()
# do permutation
input_bev_maps = input_bev_maps.permute(0, 2, 3, 1)
image[0,...] = input_bev_maps[0,...] #.reshape(shapein[1:])
job_id = dpu.execute_async(input_data, output_data)
dpu.wait(job_id)
# convert the output arrays to tensors for the following post-processing.
outputs0 = torch.tensor(output_data[0])
outputs1 = torch.tensor(output_data[1])
outputs2 = torch.tensor(output_data[2])
outputs3 = torch.tensor(output_data[3])
outputs4 = torch.tensor(output_data[4])
# do permutation
outputs0 = outputs0.permute(0, 3, 1, 2)
outputs1 = outputs1.permute(0, 3, 1, 2)
outputs2 = outputs2.permute(0, 3, 1, 2)
outputs3 = outputs3.permute(0, 3, 1, 2)
outputs4 = outputs4.permute(0, 3, 1, 2)
outputs0 = _sigmoid(outputs0)
outputs1 = _sigmoid(outputs1)
# post-processing
detections = decode(
                    outputs0,
                    outputs1,
                    outputs2,
                    outputs3,
                    outputs4, k=configs.k)
detections = detections.cpu().numpy().astype(np.float32)
detections = post_processing(detections, configs.num_classes, configs.down_ratio, configs.peak_thresh)
return detections[0], bevmap
在 kv260 上执行
通过运行以下命令,将在 dpu 上执行演示数据的推理:
python demo_2_sides-dpu.py
然后运行以下命令:
pythondemo_front-dpu.py
性能范围从10到20fps,比在服务器级cpu(intelxeongold6226r)上的执行速度快100到200倍。
结论
总之,我们展示了在kv260上使用amd-xilinxdpu来加速基于点云的3d对象检测是多么容易。为了进一步提升性能,我们计划通过使用多个dpu实例来优化模型推理阶段,以及通过使用多线程和批处理来优化预处理和后处理阶段。

SMART 200中拆分提取字符串内数据
ARM发布新的CPU架构A78C正面intel
使用NVIDIA DGX SuperPOD训练SOTA大规模视觉模型
派拓网络创建Cortex XSOAR高级检测和分析平台
高视半导体纳米级图形晶圆缺陷检测量产设备出口马来西亚客户
如何在LiDAR点云上进行3D对象检测
XilinxCEDStore项目介绍
苹果加强硬件能力,研发新3D传感器或用于未来iPhone机
导致醛类分子缺少ESPIT荧光发射带的原因分析
特斯拉财务数据与华尔街预期比较分析
中环股份与天合光能签订单晶硅片销售框架合同
网球迷福音!巴克莱ATP世界巡回赛总决赛将用VR进行直播
联通和电信的5G SA共建共享商用站点,带来更好的用户体验
新版本CUDA 11.6工具包的功能
任天堂Switch成功运行《赛博朋克2077》
电信运营业一味地追求发展速度和用户规模,是跑得越快就离成功越近吗?
城市内涝监测预警一体机-道桥积水监测预警系统-旭华智能
联发科P23舰级芯片来袭,似乎可以和高通骁龙660一决高下
iPad销量下滑 苹果第四财季财报公布
如何分辨智能家居品牌厂家是否可靠