千里之行始于足下,从一个最简化的全流程示例完成从Camera接入到目标检测输出的应用开发,将是进行复杂应用场景开发的第一步。为此,在地平线芯片算法工具链的工具包中提供了一个全流程的应用示例(ai_forward_view_sample),以源码的形式呈现了一个Hello World级别的视觉目标检测场景应用的Demo。下面和大家一起对该示例进行解读。
为了更顺畅地理解此全流程示例的实现原理,希望大家对J5芯片、J5媒体系统接口、J5视频通路配置、算法工具链等背景知识已经有所了解。
1. 基础原理
1.1 硬件通路
在解读代码之前,有必要了解一下J5芯片的视频通路硬件设计,了解J5芯片的硬件特性可以更好的理解如何高效的进行应用开发。

J5视频通路架构图
主要名词解释
名词 | 释义 |
|---|---|
VPS * | Video Process System 图像处理系统 |
VIN * | Video IN 图像输入 |
VPM* | Video Process Manager 图像处理管理 |
DVP | Digital Video Port 数字视频接口 |
CIM | Camera Interface Manager 图像数据通道管理 |
CIM-DMA | Camera Interface Manager(DMA output)图像数据通道管理(DMA输出) |
ISP | Image Signal Processor 图像处理器 |
PYM | PYraMid 图像金字塔处理单元 |
GDC | Geometry Distortion Correction 几何畸变矫正 |
BPU | Brain Process Unit 地平线神经网络加速处理单元 |
*VPS/VIN/VPM 是虚拟概念,其他是实体硬件单元
J5支持4路MIPI RX 和 2路MIPI TX,Camara通过MIPI 接口接入,通过配置实现On-line 模式或Off-line模式的数据处理流程(RX0/RX1支持配置成On-line模式,RX2/RX3支持配置成Off-line模式)。支持2路ISP和3路PYM,其中PYM2只支持off-line模式。
相机RAW data直接从MIPI接口经过CIM接入到ISP模块,经过ISP处理后,直接进入金字塔模块进行图片的resize/crop操作,输出写入DDR中。在金字塔之前的链路上数据不需要经过DDR,避免了内存的写入读取开销,用于极低延时要求的场景。
Off-line模式:
相机RAW data 经过CIM-DMA模块写入DDR,ISP/PYM/BPU等模块都从DDR上读取数据进行处理后再写入DDR。
从Camera接入,到神经网络处理的最基本的数据流如下所示,每个硬件模块的工作模式通过JSON配置文件进行配置,重点会涉及到三个重要的配置文件:mipi config、cim config、vpm config,后文将有更多的解读。

数据流图
Camera通过MIPI TX 接入后,可配置经过On-line 或 Off-line的模式,将RAW data直接送入到ISP 或是DDR。在这一阶段通过mipi config 和 cim config 两个配置文件来配置实现。
RAW data经过ISP的处理后可以配置直接送入金字塔(PYM)进行crop/resize操作,将图像处理成算法模型所需的尺寸大小。在这一阶段通过vpm config 配置文件进行配置完成。
视频通路支持多种灵活的pipeline配置, 详细的配置说明请参考《MU-3020-12-J5-视频通路配置指南》
图像数据经过金字塔(PYM)处理后输出的是YUV420格式(NV12),该数据格式可以被BPU直接处理。BPU支持在模型中将该数据格式高效的转换成算法模型所需的输入格式(例如RGB/BGR等),并且由于在整个通路上是共享DDR,数据不需搬运即可被BPU所处理,实现零拷贝,最大化的降低了整个处理流程的延时。
1.2 软件Pipeline
在软件层面如何初始化各硬件模块,并实现从Camera->ISP->PYM的数据流处理,除了上面所述的几个重要的配置文件外,还需要依赖J5平台所提供的Auto媒体系统接口(VIO APIs)进行配置的加载和运行,实现数据流pipeline的的运行和图像数据的获取。下面对流程中核心的API进行简要说明。
详细的VIO APIs接口说明请参考《MU-3020-5-J5-图像媒体模块调试指南》

视频通路调用流程图
1.3 模型推理
从金字塔(PYM) 输出的YUV420数据送给BPU作为视觉感知算法模型的输入,BPU上进行模型推理使用libDNN推理库提供的APIs,下图对推理的流程及使用的API做简要的介绍。
详细的接口使用说明可以参考《地平线征程5 算法工具链:5.2 BPU SDK API手册》

模型推理调用流程图
2. 示例功能
全流程示例主要呈现了如下的功能:
1. Camera接入
目前Camera支持max9296+ar0233 和max96712+ar0233。不同的摄像头模组通过配置文件进行配置。
2. ISP/PYM配置使用
通过配置文件实现将Camera数据处理成算法模型推理所需要的输入数据,包括crop/resize功能。
3. 网络图像回灌
实现通过网络发送/接收图像数据作为数据源,完成检测算法推理和可视化渲染功能。
4. 检测模型BPU推理
集成了一个目标检测模型(fcos_efficientnetb0),在BPU上执行图像推理,实现对输入图像中的目标进行检测,输出目标bounding box。
5. 检测结果可视化渲染
将目标检测结果渲染在输入图像上,通过后台uws服务提供web方式的可视化渲染能力。
本文重点对视频通路、模型推理的部分进行解读,网络回灌和可视化渲染只是为了提供更完整、丰富的示例功能,不做详细分解。
3. 实现框架
整个示例涉及到Camera的接入、图像数据处理、算法模型推理、检测结果后处理、图像编码、结果可视化渲染多个功能,为了代码实现更加清晰和解耦,设计了多个不同模块分别完成不同阶段的功能,并最大化减少相互间的依赖。

模块框架图
整个示例设计了5个模块来实现不同的任务,做到功能解耦。
模块 | 功能说明 |
|---|---|
VIOModule | 视频输入模块。对Camera、网络回灌不同的输入模式进行了实现封装,根据配置文件创建不同的子模块实例(CameraInputModule, NetworkInputModule) |
InferenceModule | 模型推理模块。加载目标检测模型在BPU上实现对视频通路的图像数据进行推理执行 |
PostProcessModel | 后处理模块。实现目标检测模型的后处理逻辑,主要是NMS算法的后处理实现 |
CodecModule | 编解码模块。实现将从金字塔输出的YUV420的图像数据转换编码成JPEG格式数据,用于可视化渲染 |
WebDisplayModule | Web渲染模块。实现检测目标Box与图像进行合成渲染,通过UWS服务提供可以Web访问的可视化能力 |
不同的Module里显式的调用下游Module的接口进行数据流的处理,在上面的框架图中已标记出相应的接口。下图对整个示例的运行流程进行详细拆解。

模块调用时序图
4. 模块分析
对整个流程中的三个重点模块进行详细解读,这三个模块构成了在J5开发板上完成一个完整通路的必要流程。
4.1 VIOModule
4.2 CameraInputModule
4.2.1 配置分析
视频通路主要由VIN/VPM模块覆盖,硬件通路的配置主要是VIN 和 VPM相关配置文件,先对配置进行分析。
VIN负责Camera接入部分功能,其中包括Sensor/Serdes、MIPI、CIM/CIM DMA及同步LPWM等,对用户提供统一的API,各中Camera的差异性则通过JSON方式配置,用以适配各类接入场景。
VIN部分的配置共有3个JSON 配置文件,配置结构如下:

VIN Config 结构
Mipi config: 该配置文件在示例代码的 configs/vio/vin/camera/hb_j5dev.json 中指定,如下所示:
Cim config:该配置文件在示例代码的 configs/vio/vin/camera/hb_j5dev.json 中指定,如下所示:
两个子配置文件都可以在J5 板上环境相应目录找到,详细的配置项不做展开。
配置参数详解可以参考系统软件手册《MU-3020-12-J5-视频通路配置指南》
VPM 数据通路主要包含ISP、PYM,和其他模块(GDC、Stitch等)的配置,配置文件结构如下:

VPM Config 结构
VPM config:该配置文件在示例代码的 configs/vip/vpm/vpm_config.json , 对ISP和PYM进行了配置。
isp_stream_output_format 配置了ON-LINE 直连到PYM
示例中配置了Downscale的第一层,从原图中的[0,0, 960,540]的ROI区域缩放到[512, 512]的图像大小,该大小是后续推理模型的输入尺寸。
4.2.2 运行模式
到此时可以深入代码进行解读CameraInputModule的运行机制。首先看类图理解继承关系和接口。

输入Module类图
InputModule在被Start后将创建一个工作线程(produce_thread_),该线程持续的获取输入数据(CameraInputModule从金字塔读取Frame data,NetworkInputModule从网络接收Image data),并将数据传递给下游Module(如InferenceModule,CodecModule)
4.3 InferenceModule
4.3.1 检测模型信息
模型的基本信息:
model name: fcos_effb0_test_model
input[0]:
name: arg0[img]
input source: HB_DNN_INPUT_FROM_PYRAMID
valid shape: (1,3,512,512,)
aligned shape: (1,3,512,512,)
aligned byte size: 393216
从模型信息看到,input source是HB_DNN_INPUT_FROM_PYRAMID, 输入源是金字塔,输入类型是NV12。Valid shape 表示模型输入的有效shape是 1x3x512x512, 所以上面介绍的金字塔配置部分,配置了从Camera输入原图Downscale到512x512的尺寸,直接可作为模型的推理输入数据。
4.3.2 异步处理机制
在InferenceModule中实现了数据异步处理的机制,创建了一个queue,用于缓存从上游Feed的Frame Data,在Module Start时创建的工作线程(produce_thread),从queue读取数据进行模型推理,实现上下游的执行解耦。该机制在其他Module(例如PostProcessModule)中都有使用,将不再赘述。

异步处理机制
4.3.3 Zero-Copy
从金字塔输出的图像格式是NV12_SEPARATE,模型输入Tensor 内存数据需要将Y和UV分量数据分开赋值,因为共享内存,只需要将相应的物理地址和虚拟地址赋值到Input Tensor memory中即可,无需memory copy。具体的实现逻辑可以阅读DoInference()中的实现代码。
在上面的分析中看到,在金字塔的配置中配置的是DownScale的第0层,所以获取输出数据的来源是roi_ds_[0]
推理的输出output_tensor 进行简单封装后传递给下游PostProcessModule进行后处理。
4.4 PostprocessModule
通过后处理的配置文件(configs/model/postprocess_config.json)可以微调部分参数,例如score_threshold, iou_threshold等,用于改善误检或漏检的效果。
该模块将BBox数据传递给WebDisplayModule,用于与CodecModule编码输出后的JPEG进行合并渲染,并提供可视化功能。
5.渲染效果
到此处,主要的模块解读完成,最后根据示例代码中的README,根据接入的摄像头型号的不同简单的调整一下config,运行一下示例,既可在浏览器中查看检测输出的可视化效果。如下图,是通过示例中集成的图片回灌得到的渲染效果,后处理配置中的score_threshold微调到0.61。

渲染效果


