硬件加速 3D 实时感知 (HARP-3D)
使用在 ULTRA96V2 上运行的深度神经网络在 LiDAR 点云中进行 3D 对象检测的端到端演示。
本项目用到的东西
Ultra96-V2
绪论
理念
--
感知是自动驾驶中的一项关键任务,并且可能是当今技术界讨论最多的话题之一。
简单来说,感知是理解数据的任务。这些数据通常由各种传感器生成,例如相机、雷达、激光雷达等。
最常用的感知任务是对象检测和语义分割。
对象检测是在传感器数据中定位和分类感兴趣的对象的任务。
语义分割是将传感器数据的每个像素/元素标记为属于一组感兴趣类别中的一个类别的任务。
深度神经网络 (DNN) 已经发展成为复杂感知算法的支柱,否则使用传统的计算机视觉算法几乎不可能进行设计。
任何类型的 DNN 的基本数学运算都是矩阵乘法。
事实证明,矩阵乘法是一种可以高度并行化的运算。这就是 GPU 对深度学习有用的根本原因。
这就是硬件加速可以作为加速深度学习算法的一种手段。
本项目旨在演示这一点,使用 Ultra96v2 开发板作为硬件加速平台。
Ultra96v2 基于 Xilinx Zynq MPSoC 平台,开发板具有除 FPGA 之外的其他几个外设。
该项目演示了如何使用 Ultra96v2 作为硬件加速平台和 Vitis-AI 作为软件平台在 LiDAR 点云中执行对象检测。它还以端到端的方式演示了带有对象检测模型的 Ultra96v2 如何作为边缘 AI 应用程序工作。
传感器数据
该项目使用 LiDAR 传感器数据作为输入。现在,由于传感器的状态非常昂贵,该项目使用来自最先进的 LiDAR 传感器的预先记录的数据。这是KITTI数据集(http://www.cvlibs.net/dataset...)。
传感器的典型扫描,称为点云如下所示。
点云中的每个点都由至少 3 个数字表示,这些数字对应于 3D 空间中该点相对于传感器的 x、y 和 z 坐标。
目标
--
我们试图确定汽车和其他物体在上述点云中的位置,并在它们周围放置一个边界框。
这如下所示。
神经网络
使用的神经网络是称为U-Net的语义分割网络。
https://arxiv.org/abs/1505.04597
它被修改为预测关键点,其中关键点是范围图像中的对象中心。
一旦我们有了关键点,一个简单的后处理步骤将它们转换回 3D 坐标 - x、y、z。
根据每个关键点的类别完成基于模型的框拟合。
这是通过获取 KITTI 训练数据集中不同对象类别的框的平均尺寸来发现的。
例如,汽车通常具有长度、宽度和高度分别为 3.6、1.5、1.8 的盒子尺寸。
下图显示了网络的架构。
数据预处理
3D 点云首先被转换为称为距离图像的 2D 表示,然后使用上面显示的 U-Net 架构进行处理。
转换过程的详细信息可以在SqueezeSeg论文中(https://arxiv.org/abs/1710.07368)找到。
作者还提供了一个预先转换的数据集(https://www.dropbox.com/s/pnz...\_2d.tgz?dl=0)。
更多详细信息,请参考他们的github页面(https://github.com/BichenWuUC...)。
预测
--
为每个对象预测关键点,其中关键点是对象在其分割掩码中的中心。下图展示了一些预测的关键点。
一旦检测到关键点并将每个对象过滤为 1 个关键点,然后将球坐标转换回 3D 笛卡尔坐标以获得关键点在 3D 空间中的位置(在 3D PCL 中)。
公式可以在这里找到(https://mathinsight.org/spher...\_coordinates)。
上文中附上了将 2D 关键点转换为 3D 的代码。
上图显示了预测的 2D 关键点如何映射到点云中的 3D 位置。
一旦知道了对象位置,就完成了基于模型的框拟合,即,对于每个对象类,从训练集中找到的平均框尺寸用于放置 3D 边界框,如下所示。
使用 Vitis-AI-1.2 将训练好的模型转换为.elf
原始模型是使用 keras 训练的。
可以在附件中找到经过训练的模型。
第 1 步:获取 Ultra96V2 的系统镜像
(https://www.hackster.io/Alber...)教程中的系统镜像可以使用。也可以为 Ultra96v2 构建自己的板映像。
镜像中包含实例化 DPU IP 所需的所有组件。
将镜像中文件安装到 SD 卡。
然后,将 .dcf 文件从 SD 卡复制到本地文件系统。
下一步在 github 代码库中创建了一个文件夹 - Ultra96v2,并将 dcf 文件复制到其中。
然后在同一文件夹中创建一个arch.json文件(http://arch.json/)。
两者都可以在附件中找到。
给开发板加电,连接到 Web 服务器并配置 WiFi。
SSH 进入开发板并从根文件夹验证 DPU 确实存在
dexporer --whoami
应该看到类似于以下内容的输出:
[DPU Core Configuration List]
DPU Core : #0
DPU Enabled : Yes
DPU Arch : B4096
DPU Target Version : v1.4.1
DPU Freqency : 300 MHz
Ram Usage : High
DepthwiseConv : Enabled
DepthwiseConv+Relu6 : Enabled
Conv+Leakyrelu : Enabled
Conv+Relu6 : Enabled
Channel Augmentation : Enabled
Average Pool : Enabled
DPU Core : #1
DPU Enabled : Yes
DPU Arch : B4096
DPU Target Version : v1.4.1
DPU Freqency : 300 MHz
Ram Usage : High
DepthwiseConv : Enabled
DepthwiseConv+Relu6 : Enabled
Conv+Leakyrelu : Enabled
Conv+Relu6 : Enabled
Channel Augmentation : Enabled
Average Pool : Enabled
[DPU Extension List]
Extension Softmax
Enabled : Yes
`
第二步:将.h5模型量化编译为.elf
使用 Vitis-AI 设置为本地系统
从github 的 Vitis-AI 克隆 DenseNet 示例
https://github.com/Xilinx/Vit...
本教程包含将.h5 训练的 keras 模型转换、量化和编译为要部署在 Ultra96V2 上的.elf 所需的所有文件。
克隆后,将 files/build/keras_model 文件夹中的 k_model.h5 文件替换为附加的训练模型。或者,替换为自己的自定义模型。名称必须为 k_model.h5。这确保了在后续步骤中所需的更改更少。
现在,根据您的本地系统更改 0_setenv.sh 脚本中的以下参数。
# network parameters
export INPUT_HEIGHT=64
export INPUT_WIDTH=256
export INPUT_CHAN=1
export INPUT_SHAPE=?,${INPUT_HEIGHT},${INPUT_WIDTH},${INPUT_CHAN}
export INPUT_NODE=input_1
export OUTPUT_NODE=conv2d_23/BiasAdd
export NET_NAME=u3d_kp
# training parameters
export EPOCHS=200
export BATCHSIZE=150
export LEARNRATE=0.001
# target board
sudo mkdir /opt/vitis_ai/compiler/arch/DPUCZDX8G/ULTRA96V2
sudo cp ./ULTRA96V2/arch.json /opt/vitis_ai/compiler/arch/DPUCZDX8G/ULTRA96V2
sudo cp ./ULTRA96V2/ULTRA96V2.dcf /opt/vitis_ai/compiler/arch/DPUCZDX8G/ULTRA96V2
export ARCH=/opt/vitis_ai/compiler/arch/DPUCZDX8G/ULTRA96V2/arch.json
#export ARCH=/opt/vitis_ai/compiler/arch/DPUCZDX8G/ZCU102/arch.json
# DPU mode - best performance with DPU_MODE = normal
export DPU_MODE=normal
#export DPU_MODE=debug
上述更改会在我们启动 tensorflow 工作区时自动将 Ultra96 板文件复制到工作区中。Ultra96 板文件应与此脚本位于同一文件夹中。
对于输出节点,如果是自定义模型,最好的方法是继续量化,然后查看错误消息并相应地修改参数。
继续获取有关如何获取输出节点名称的示例。
导航到克隆存储库的文件夹并键入:
`sh -x docker_run.sh xilinx/vitis-ai:latest
`
应该看到:
现在,在本地更改量化文件,如下所示,替换为自己的校准数据生成功能。这个函数基本上是一个简单的 python 脚本,它返回成批的训练数据,预处理方式与推理完全相同。
附上用于该项目的功能。
#!/bin/bash
# Copyright 2020 Xilinx Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# quantize
quantize() {
echo "Making calibration images.."
# python tf_gen_images.py \
# --dataset=train \
# --image_dir=${QUANT}/images \
# --calib_list=calib_list.txt \
# --max_images=${CALIB_IMAGES}
# log the quantizer version being used
vai_q_tensorflow --version
# quantize
# vai_q_tensorflow quantize \
# --input_frozen_graph ${FREEZE}/${FROZEN_GRAPH} \
# --input_fn image_input_fn.calib_input \
# --output_dir ${QUANT} \
# --input_nodes ${INPUT_NODE} \
# --output_nodes ${OUTPUT_NODE} \
# --input_shapes ${INPUT_SHAPE} \
# --calib_iter 10
vai_q_tensorflow quantize \
--input_frozen_graph ${FREEZE}/${FROZEN_GRAPH} \
--input_fn datagen.get_calib_data \
--output_dir ${QUANT} \
--input_nodes ${INPUT_NODE} \
--output_nodes ${OUTPUT_NODE} \
--input_shapes ${INPUT_SHAPE} \
--calib_iter 10
}
echo "-----------------------------------------"
echo "QUANTIZE STARTED.."
echo "-----------------------------------------"
rm -rf ${QUANT}
mkdir -p ${QUANT}/images
quantize 2>&1 | tee ${LOG}/${QUANT_LOG}
rm -rf ${QUANT}/images
echo "-----------------------------------------"
echo "QUANTIZE COMPLETED"
echo "-----------------------------------------"
在上面,datagen.py是 python 文件,get_calib_data 是函数。
键入以下命令并验证输出:
`source ./0_setenv.sh
source ./2_keras2tf.sh
`
输出的一部分应显示:
keras_2_tf command line arguments:
--keras_json:
--keras_hdf5: ./build/keras_model/k_model.h5
--tf_ckpt : ./build/tf_chkpt/tf_float.ckpt
-------------------------------------
Keras model information:
Input names : [<tf.Tensor 'input_1:0' shape=(?, 64, 256, 1) dtype=float32>]
Output names: [<tf.Tensor 'conv2d_23/BiasAdd:0' shape=(?, 64, 256, 2) dtype=float32>]
Checkpoint created : ./build/tf_chkpt/tf_float.ckpt
在上面,我们可以看到输出节点名称是:conv2d_23/BiasAdd。
注意:不要添加 ':0'
回到 0_setenv.sh 脚本,填写输出节点名称。
在这个阶段,一个名为 -frozen_graph.pb 的冻结图在 build/freeze 中生成
现在使用以下命令从工作区中执行量化脚本:
`source ./4_quant.sh
`
成功的量化应该产生:
我们可以看到使用的部分校准图像。
最后,编译
`source ./6_compile.sh
`
成功的编译应该产生:
现在应该在 /build/compile 中看到 .elf 文件
Ultra96v2 上的部署和应用执行
现在我们有了模型,下一步是将模型复制到 Ultra96,然后编写使用该模型的应用程序。
将.elf 复制到 /root 文件夹中选择的任何文件夹中。
下图显示了我如何放置它:
在上面,我使用了 VSCode 来 ssh 进入板子。它使应用程序开发变得非常简单。
虽然有多种方法可以设计用于推理的 IoT 应用程序,但对于该项目,使用了模拟传感器,因为获得产生数据的 Velodyne 传感器是不切实际的。
因此,再次使用 KITTI 测试/验证数据集,主机作为模拟传感器,通过 FTP 将数据发送到 Ultra96 进行推理。
整体应用架构如下图所示。
一个简单的 TCP 客户端/服务器套接字应用程序用于同步,Ultra96 上的一个共享文件夹用于数据交换。
具体来说,主机打开一个TCP套接字作为服务器,等待Ultra96客户端连接。
客户端是整个推理应用程序的一部分。
客户端然后通过套接字发送一个启动消息,主机 PC 通过 FTP 将第一批测试数据复制到 Ultra96 上的共享文件夹。
以下代码段显示了数据传输。
from ftpretty import ftpretty
import numpy as np
import os
import socket
def place_test_file_in_fpga(local_file_path, host_addr, remote_path):
"""
File copies the file at local_file_path to the remote_file_path on U96
"""
# Supply the credentisals
f = ftpretty(host_addr, "root", "root")
file = np.load(file_path) # read in the numpy file
# Get a file, save it locally
# f.get('someremote/file/on/server.txt', '/tmp/localcopy/server.txt')
# Put a local file to a remote location
# non-existent subdirectories will be created automatically
f.put(file_path, remote_file_path+'/')
主应用程序作为 jupyter notebook 附加。
检测到的关键点的一些预测结果如下所示。
下面显示了在批量大小为 1 的 50 帧上进行推理的帧速率。
正如我们所看到的,它实现了令人印象深刻的 109 帧/秒的帧速率。
然而,高帧率的一部分也归因于使用的网络非常小,准确性不是这里的关键问题。因此,在这个项目中,准确性不是基准。
第一部分中解释的最终后处理是在主机上完成的,因为这不是推理的一部分。
附上一些测试文件。
链接:https://pan.baidu.com/s/1cBse7zkCWwK7idnx9qZhtw?pwd=open提取码:open
结论
对我来说,这是一个非常有趣的机会,可以在硬件上尝试加速深度学习算法。一些预处理和后处理也可以作为硬件 IP 来实现。这将使推理更快。
项目参考地址:
https://www.hackster.io/sm\_1991/hardware-accelerated-real-time-perception-in-3d-harp-3d-fde0c0
END
原文链接: https://mp.weixin.qq.com/s/aKD46ZokKpXgTiezRxBeHg
微信公众号:
推荐阅读
更多IC设计技术干货请关注IC设计技术专栏。