本帖最后由 kyuliea 于 2024-3-10 12:02 编辑

MCU也要玩边缘AI,GD32H759借助GD32 AI ModelZoo快速部署目标检测模型

1、前言

GD32 AI ModelZoo是一个用于在GD32设备上快速部署AI模型的开源项目,其在github上发布: https://github.com/HomiKetalys/gd32ai-modelzoo。本文将对GD32 AI ModelZoo中的目标检测模型Yolo-FastestV2部署到GD32H759I-EVAL开发板上。

2、开发板介绍

在部署AI模型方面,GD32H759提供了一颗主频高达600Mhz的MCU,同时提供了64KB的L1 Cache,以及1M的片上RAM。本文将对其与GD32F470,STM32H749进行对比。

3、Yolo-FastestV2介绍

Yolo-FastestV2是一个十分轻量的目标检测模型,其已在github上发布: https://github.com/dog-qiuqiu/Yolo-FastestV2

4、程序移植

在GD32H759上运行一个目标检测模型并展示其检测结果,需要使用GD32H759I-EVAL开发板上的摄像头ov2640以及LCD。本文将在GD32H759的开发例程25_DCI_OV2640上对GD32F470蓝莓派开发板的例程15.CameraCapture中的部分程序进行移植。这里将讲述一下代码的移植过程与方法,具体代码请到GD32 AI ModelZoo上查看。

4.1、OV2640程序的移植

由于例程25_DCI_OV2640中的DCI对OV2640采用连续捕获模式,而本文需要从OV2640采集的图像可控,则需要将DCI修改为快照捕获模式。同时例程15.CameraCapture提供了函数ConfigDCI()来控制图像的采集,所以本文需要在例程25_DCI_OV2640上定义函数ConfigDCI()。本次采用的移植方法是在例程25_DCI_OV2640修改其软件部分,硬件不变。

在例程15.CameraCapture中,DCI的初始化由函数InitDCI完成。如图 4‑1 InitDCI函数。

114735bstuu7tgfzlutxst

图 4‑1 InitDCI函数

从图中可以看到其进行了执行了三个关键函数,分别是CongifDCIGPIO,ConfigCKOut0,ConfigDCI。

而在例程25_DCI_OV2640中的DCI初始化由函数dci_config()完成,其与函数CongifDCIGPIO对应的内容如图 4‑2 DCI的IO口配置

114735jvlvvvxedlz4vwxr

114735o9ddq8nntg9zo4tj

图 4‑2 DCI的IO口配置

与函数ConfigDCI 对应的DCI的配置如图 4‑3 DCI配置

114736oxpxchr7r9y4xynh

图 4‑3 DCI配置

IO口的配置可以不用管,这是硬件相关的,直接用原例程25_DCI_OV2640中的配置就行,主要观察DCI的配置。在例程15.CameraCapture中,ConfigDCI函数的内容如

114736k9fujzq49sifkysh

114736enqb8xyakssgy5i7

图 4‑4 ConfigDCI函数内容

从图中可以观察到不同点,由于本文需要图像采集可控,所以DCI的capture_mode需要设置为DCI_CAPTURE_MODE_SNAPSHOT快照模式,同时注意需要配置DCI的中断优先级,以及启用DCI的溢出中断和图像采集结束中断。在DMA的设置中,例程15.CameraCapture中的采集的图像的保存地址为s_iFrameAddr,这一点在例程25_DCI_OV2640中保持不变即0XC0000000即可,这是EXSDRAM的一个地址。而DMA的传输数量为采集的图像的字节数的四分之一(因为传输宽度为为32位)。同时DMA的循环模型需要设置为禁用循环模式。黄色方框中的两个函数在GD32H7的头文件中没有提供,此处便忽略。此外,注意到例程15.CameraCapture中的函数ckout0()函数紧接着GPIO配置结束后调用,而例程25_DCI_OV2640中是在DCI配置后调用,所以在例程25_DCI_OV2640中,本文将ckout0_init()函数也移至GPIO配置结束后位置调用。最后DCI的配置如图 4‑5 新DCI配置。

114738dhz16xhis77xneh6

图 4‑5 新DCI配置

将其写成函数ConfigDCI即可。

随后需要将DCI的中断函数进行复制。如图 4‑6 DCI中断函数

114738oehrvvdt7qutd3t7

图 4‑6 DCI中断函数

随后即可快乐使用OV2640了。其余的小细节,比如要注释掉的头文件或代码,要切换的头文件(f4->h7),不再赘述,自行debug。

4.2、LCD程序的移植

例程25_DCI_OV2640提供的LCD的功能几乎没有,所以本文为了方便使用LCD,将例程15.CameraCapture中的TLILCD.c/h,Font.h文件进行了复制,以便在例程25_DCI_OV2640中使用,本次的移植方法是在例程15.CameraCapture膝盖其硬件部分,软件不变。

LCD的配置过程如图 4‑7 LCD初始化

114738fxrer9vrdd8fbhue

图 4‑7 LCD初始化

其中硬件部分设计IO口配置,TLI时钟配置,和TLI初始化。IO口配置在例程25_DCI_OV2640中的函数tli_gpio_config提供,TLI时钟配置在例程25_DCI_OV2640中的函数lcd_config中有提供,剩下的便是TLI初始化部分的修改。主要是时序部分的修改,如图 4‑8 LCD时序对比,上图为例程25_DCI_OV2640,下图为例程15.CameraCapture

114739ul5oeedlvruu3pr3

114739as439sylo33s31zz

114739havxa58ny4x5dzh4

图 4‑8 LCD时序对比,上图为例程25_DCI_OV2640,下图为例程15.CameraCapture

通过对比计算得到例程25_DCI_OV2640中的时序应该如

114740cuco2udhxdmpd6hy

图 4‑9 例程25_DCI_OV2640的时序

同时注意修改屏幕宽高。同时修改画点函数中竖屏时的写入策略使得其竖屏时方向符合本文需求。

114740fkqr344goz75mqqd

114740ul2w0ylmkqmqqkdq

图 4‑10 上图旧策略,下图新策略

还需修改背景显存的地址,修改成GD32H759I开发板的外部内存的地址。如图 4‑11 修改背景显存地址。

114740unehhl6eb5jyr8jr

图 4‑11 修改背景显存地址

随后即可快乐使用LCD中的各种函数了。其余的小细节,比如要注释掉的头文件或代码,要切换的头文件(f4->h7),不再赘述,自行debug。

5、GD32AI-ModelZoo的使用

终于来到重头戏,GD32AI-ModelZoo的使用。本文将对模型Yolo-FastestV2在GD32H759I上进行部署,直接进入对应模型网址。其提供了该模型的训练,导出,以及近乎一键的部署。

在拿到GD32H759I的第一时间,本文对GD32H759I进行了第一时间的适配,并将部署过程及示例合并到了GD32AI-ModelZoo中。对于本文是如何进行适配的,这涉及的技术细节较多,本文只利用GD32AI-ModelZoo对GD32H759I进行评测,不进行其技术实现的讲解。

本文将使用Yolo-FastestV2已导出的C代码和其提供的Keil工程示例,将模型部署到GD32H759I上。首先将FD32AI-ModelZoo进行下载。

114740xi442t74t41yi0oh

图 5‑1 GD32AI-ModelZoo下载

如图 5‑1 GD32AI-ModelZoo下载。并进行解压

114740szo1ael1e1oogj7a

图 5‑2 keil工程示例

如图 5‑2 keil工程示例中所示,该文件夹下提供了GD32H759的两种编译器下的keil5工程。注意,你的Keil5的版本应该>=5.29。如果你不知道该如何在Keil5中配置GCC,请使用ARMCC版本的keil5工程,本文使用ARMCC版本的Keil工程示例。使用keil5打开如图 5‑3 keil5工程文件。

114741qwp2r8wub22nruhg

图 5‑3 keil5工程文件

随后进行编译烧录,即可得到一个内置的目标检测示例程序。

在如图 5‑4 已导出的在COCO80上训练的模型中,提供了Yolo-FastestV2模型在COCO2017上训练的检测80种目标的模型。提供了两种分辨率

114741q3fhj6lzjkkjfi5z

图 5‑4 已导出的在COCO2017上训练的模型

将图 5‑5 Edge_AI文件夹替换中右图的Edge_AI文件夹替换为左图中的。即可完成模型的替换。

114741ogyv2wa82yn2vd2j 114743u1yqqon0n9axa0gy

图 5‑5 Edge_AI文件夹替换

替换后重新进行编译烧录。即可完成新的目标检测模型在板子上的部署。如果你想在自己的工程中使用,请根据此keil5样例,导入Edge_AI中的.c文件和.lib文件并设置头文件路径。

部署后的开发板结果如图 5‑6 检测结果示例。

114743fs8lsmeq8xw8l300 114743pqth8uhvdptj5tt5

图 5‑6 检测结果示例

6、与GD32F470的对比结果

114744miifi3wy9zqhvohd

114744uqbhzu6ujqhp9vu2

与GD32F470相比,在GD32H759I上部署的模型的推理速度至少提升400%。此处F4使用的是ARMCC编译的,H7是使用GCC编译的。

7、与STM32H7的对比结果

STM32H747I是与GD32H759I同级的MCU,但是STM32H474I仅有最高400Mhz主频,32KB的L1 cache。由于GCC版本的编译结果会比ARMCC版本的编译结果运行更快,主要是使用的库更小,所以接下来将讲一下如何使用GCC版本的keil5工程。STM32的数据来源于STM32AI-ModelZoo

7.1、GCC编译

如果你想要使用GCC版本的keil5工程,则首先从https://developer.arm.com/downloads/-/gnu-rm这里下载GCC。然后解压到某个目录下,比如本文解压到了keil5安装目录下的ARM文件夹中的GCC文件夹中。如图 7‑1 GCC解压位置示例。

114744e12h1fa01mx12xrx

图 7‑1 GCC解压位置示例

然后在GCC版本的keil5工程中,如图 7‑2 GCC路径配置

114745j8cb2ez9n328jl23

114745ckx2ovvo8gapgkdp

图 7‑2 GCC路径配置

随后就可以编译GCC版本的keil5工程了。

7.2、对比结果

以下展示本文的对比结果,更多信息可以去GD32AI-ModelZoo上查看。

7.2.1、COCO Person Dataset AP指标对比

114745zsr7z39bevex9ver

从表中可以看到在各分辨率下,本文提供的模型在相同分辨率下AP指标均高于STM32提供的模型。

7.2.2、推理时间对比

114745jvva5lloqcxxvvg6

114745q8njjwdiyydyg17y

114745zqwqdw0ybgqao2ii

114746o20pg0mq954spmwo

114746vkvreukbjqurdub8

从表中可以看到,本文提供的模型在相同分辨率下在GD32H759IMK6上的推理时间均少于STM32提供的模型在STM32H747上的推理时间,推理速度至少提高20%,最高提升66%。

8、总结

本文将通过GD32AI-ModelZoo提供的模型及示例,完成了在GD32H759I上快速部署一个目标检测模型。同时展示了GD32H759I与GD32F470相比之下,高频MCU与L1 cache对模型推理的加速效果很好,与STM32H747I相比之下,高频MCU与大容量L1 cache对模型推理也有一定的加速效果。

此外,大家如果想要在GD32H759I上检测想要的目标,GD32AI-ModelZoo也提供了数据集格式,以及训练,导出,部署脚本。大家可以制作自己的数据集并训练自己的模型,并部署到GD32H759I上。