python高级玩法_AI视觉组仙人一步之高级玩法——从Python回归C语言

215244316_1_20210210110955365

开心的程序猿@NXP

本文专为参加今年大学生智能车竞赛AI视觉组的同学们而写,也很适合其他对MCU上AI应用感兴趣的朋友。

读过之前两篇的童鞋们,想来已经开始着手开发属于自己的AI视觉应用了,当然,手中还没有OpenART套件的朋友们,也不用着急,可以先参照'智能车大赛AI视觉组参考答案'在PC上先试训一下AI模型,然后结合AI视觉组仙人一步之模型量化,熟悉一下模型部署流程。215244316_2_20210210110955959

在智能车大赛AI视觉组参考答案推文中,小编介绍了如何借助OpenART所提供的python接口,在openMV IDE中编写脚本以运行AI模型。Python以其简单易用的特点,可以说极大的减轻了我们的开发负荷。

但是,想必高级玩家已经不满足止步于只使用python了吧。

了解我们的OpenART套件的童鞋们肯定知道,套件本身是集成了RT-Thread这款RTOS的,何不尝试点新玩法?挑战点高难度,尝试下用C来直接写code,在小伙伴面前炫耀一下?

也正式因为有了RTOS的加持,每一个任务本身在RTOS中都作为一个独立线程存在,想要为项目添加新功能的话,只需要为其创建一个新的线程即可,无需更改已有裸机代码。

本文的目的就是展示给大家,如何以线程的方式在工程中添加一个新的功能,以实现对于tflite micro推理引擎的直接调用。

那么,话不多说,直接开整。215244316_3_2021021011095621

首先介绍一下如何在OpenART中创建一个新的线程(OpenART中集成了RT-Thread操作系统,因此如下操作都是以RT-Thread为基础的):215244316_4_2021021011095699

下面开始编写线程主函数,主要包括以下内容:

一、初始化摄像头:

因为我们需要通过摄像头读取指令,由于我们已经不再使用python脚本,摄像头初始化部分需要手动进行,到了这里,是不是要劝退一些小伙伴了呢?别急,还有更厉害的在后面,感受C语言的魅力吧!

初始化流程和python调用流程类似,只不过我们这次要直接进行函数调用,来实现摄像头模块的初始化,这里要感谢RT-Thread所提供的设备管理框架,能够让我们能够方便的实现这一功能:215244316_5_20210210110956177

二、读取图像:

大家可能注意到了这个fb_alloc,可能有同学会问,这个不是Micropython中的吗?这里还能用吗,当然,大家可以把它理解成一个内存管理器,是可以用C来直接进行函数调用的:215244316_6_20210210110956255

这个image_t结构体,实际上它包含了图像的所有信息,就可以直接进行处理了。215244316_7_20210210110956318

三、模型推理:

至此,代码中所涉及到的图像采集部分就到此为止了,下面开始介绍模型推理部分。

不过,要提前说明的是,在这里我们没有保留python API所实现的图像输入部分,即可以通过设置窗口滑动步长和窗口放缩比,来实现多尺度下的图像识别,我们假设要识别的物体充满整个屏幕,即识别区域为整副摄像头采集的图像,而这就丧失了多目标识别能力,有兴趣的玩家可以自行实现。

那么如何利用tflite micro进行模型推断呢?

⊙  首先第一步是读取模型,model_data就是以二进制方式读取的tflite模型,在OpenART中,我们采用DFS文件系统来进行模型文件的读取,full_path根据:215244316_8_20210210110956365

⊙ 之后是实例化操作解析器和模型解释器,其中,解析器用来访问Tensorflow的操作,可以扩展此类以向项目中添加自定义操作。解释器是用来对模型进行结构上的解析,以进行模型求解。

⊙  运算之前,我们需要预先为输入、输出以及中间数组分配一定的内存。因此,用户需要预分配一个大小为tensor_arena_size的uint8_t的数组,传递给模型解析器。215244316_9_20210210110956443

⊙ 随后还需要调用函数对预分配的tensor arena进行分配:215244316_10_20210210110956505

⊙ 至此,万事俱备,只欠东风了,而我们的东风就是待识别的图像,tflite模型的输入,是通过对input tensor进行赋值实现的,实现方法也很简单,我们只需要将第二步读取到的图像数据,按照模型输入的要求进行处理后,直接对其赋值即可:215244316_11_20210210110956552

这里我们假设image是已经按照模型出入要求处理好的图像数据,size是其大小,实际情况下,可以随机应变,宗旨就是要对model_input->data.data这个变量进行遍历赋值。

让我们的模型解释器开始干活,还需要最后一步:215244316_12_20210210110956630

⊙ 最后,怎样获取结果呢?和设置input tensor大同小异,我们这次要获取output tensor, 需要注意的是这里的model_output->data.data是个void*类型,需要根据model_output->type进行指针的强制类型转化:215244316_13_20210210110956834

至此,运行tflite模型的所有所需代码均已介绍完毕,当然,为了方便使用,小编已经为大家亲手烹制了对应的库,已经集成了这些函数,可以直接调用。215244316_14_2021021011095784

⊙  这里面比较重要的是两个callback函数,要注意的是,这两个函数会在函数内部自动调用,用户需要传入input_callback_data和output_callback_data,下面进行一一说明。首先是input_callback,其定义如下,用户需要自行实现其函数体,其作用是,根据传入的input_height,input_width, input_channels对采集的图像进行放缩处理,is_float表示数据是否转换为浮点数表示,最后对model_input进行赋值:215244316_15_20210210110957318与其对应的是output_callback, 其定义如下,其作用是,根据传入的output_height,output_width, output_channels对采集的图像进行放缩处理,is_float表示结果是否为浮点数表示,最后将model_ouput的值赋值到callback_data中:215244316_16_20210210110957380

四、导出:

最后一步是导出到msh命令行,这样才可以在系统启动后,在RT-Thread的命令窗口中进行调用,这里我们通过EXPORT_MSH_CMD()这个特殊的宏进行命令的声明:215244316_17_20210210110957599

这里包含两部分的内容,以逗号进行分割,第一部分既代表命令行中所对应的命令,又代表当输入tflite_micro这一命令时所调用的函数名,没错,我们就是要把我们创建tflite线程的函数tflite_micro_main放到这里面,这样,我们就导出了一个叫做tflite_micro的命令,当我们运行这一命令时,所创建的tflite micro线程就会被调用。第二部分,是对于指令的描述。215244316_18_20210210110957787

至此,我们的菜就全部备齐了,这里略过1万字的代码调试以及下载过程,在出现的msh命令行窗口中输入tflite_micro,将待识别的图像对准摄像头,即可进行物体的识别:msh /> tflite_micro

运行结果:215244316_19_2021021011095821

不过,由于我们是直接以线程的形式调用tflite micro的推理引擎,因此没有办法在使用openmv ide进行图像的预览了,不过,如果拥有一块LCD的小伙伴,就可以不用慌张了,可以显示在LCD屏幕上一睹芳容。

本期,小编为大家带来了如何在底层以新建线程的方式直接调用tflite micro推理引擎,参考代码位于https://gitee.com/crist_xu/tflite_thread_call.git,不过,代码并不包含OpenART代码包,同学们可以参考下实现,等到OpenART软件包正式和大家见面之后再进行动手。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值