在经历完各种准备工作后,现在终于来到了正主。直接部署Tensorflow Lite Micro那一套玩意确实没啥问题,但是太麻烦,要添加一大堆文件,还得用它家训练生成模型,然后转换,麻烦的很,在ST平台,怎么能不提到用ST自家工具去部署模型,方便快捷,简单实用。
9 Q. r2 j) I! ~( q% @: p |拿出之前准备的工程,选取ai开发需要支持的软件包cue-ai,在software packs点select components5 `2 B, ~& Z3 q4 V) ~9 D
; g; t6 ~1 h B! J% h) S7 k* V* H4 M; l% n# k+ |7 D
" q* O; d. e& E6 @1 e& \1 F, Q& O% h7 w, u5 X4 f/ b
在X-CUBE-AI行下core勾选,点OK完成
3 O$ Y! }3 ~1 B, p! _7 U
4 @: `% _1 P; Z" ~
) @6 w c8 r* K( D0 R8 k% ~, K Y, x7 ~" Z6 \6 k
回到引脚配置页面,最下方就是上面导入的CUBE-AI工具包
+ m* Z5 y+ F8 W$ R
( t$ H8 p$ A4 K: ^1 ]4 n
2 M8 @% O1 w' c1 J! q9 H5 o1 t( h- B1 _
3 @0 q+ v( b" a6 j点击+添加,这里要根据自己使用的模型,以及模型特点选择,如下图选择的是原始模型# k$ m; _0 B/ H
0 K, T( }/ u4 B G% Q
3 {& n0 I, k4 @. D$ [5 v" }' w$ k9 t
这里选择的是量化后的模型(量化可以减少模型的要求,但是精度会下降),点击分析
9 }" C; Z" m% @4 W8 t
# c ^; L& P# N3 t
& I/ D$ S% _, {) {! x. X( ~6 J* O分析中
6 A; |8 K- v. R3 @
- i$ e8 P7 Z, V$ U
/ ?, N8 i% z. N/ P4 {3 l) W( O
分析完成会显示是否可以部署到设备上,以及资源使用情况。2 B4 Y. h$ S; c) V
8 }. ?4 G& k& K% h! Y) p9 F6 k
5 B; b; k" M- H2 Z回到工程,有个小bug(使用的STM32CubeMX版本为6.6.1,X-CUBE-AI版本为7.2.0),下图的几个文件路径老是生成错
4 v8 s; h# T2 T5 C0 r1 {+ B h
+ R( E8 ]% p, l/ j- W: [+ q' H/ B% H3 [2 K- A' |% e o
' b: F" P; ?7 W( p# f
4 q# v R4 ]1 k; F* L$ f+ G右键文件打开设置,修改一下路径就行
; v! H( B. C( l$ z: O+ c. e6 J, ]# e$ ? E a. `
7 u; c# L8 C. N$ o6 @4 w. Z2 g* X1 o! o
头文件路径也有一样的问题
1 Z5 x/ Q! O0 ]* j5 n% t
. V2 E, y. d2 z, d" h1 @
* V" P+ o# w) _4 q初始化模型- ai_handle ai_init(void)( Y7 l z+ w* H$ g
- {: k5 B/ _8 }* A- u
- network_handle = AI_HANDLE_NULL;
9 e! [$ S" s! h1 |
2 }. }& C/ \' f6 {. s8 m- B- e3 L- /* Creating the network */3 ?; J! |6 b* N$ h. Y$ E, {
- ai_network_create(&network_handle, AI_NETWORK_DATA_CONFIG);
u9 X+ E$ T# \ I+ T& H/ G! K! {
5 F9 v5 C- U* N! F2 W- /* Initialize param structure for the activation and weight buffers */
2 s' S+ |' } D9 b$ K& u9 D+ ` - const ai_network_params params = AI_NETWORK_PARAMS_INIT(
) C& f7 |. E" i. W" ]4 w - AI_NETWORK_DATA_WEIGHTS(ai_network_data_weights_get()),
. d' ], u, F8 |! Y6 Y - AI_NETWORK_DATA_ACTIVATIONS(activations)
1 L: U8 ~% R: G \# w& L/ E - );
" v" {( {* w$ ^, v% e8 o4 S6 l A
8 s7 i- e( v* K- /* Initializing the network */0 t w: U e. Y
- ai_network_init(network_handle, ¶ms);
: h# [. W+ | a5 l6 N+ o -
9 s6 o5 W; W/ u" } - /*Retrieve network descriptor*/- q1 K$ D6 P V" q5 H8 V: r# {' T7 b6 l
- ai_network_get_info(network_handle, &desc_report);+ \ i0 ?& F6 v: d+ G& U: O5 Y; d
- # m) z- I2 I$ v( i
- /*Copy descriptor info*/5 ~. m& i; q- W& s2 z. H
- ai_input[0]= desc_report.inputs[0];
: I+ r/ o) D- z2 w F - ai_output[0]= desc_report.outputs[0];- V9 e0 O+ v7 t3 d1 C! h/ v
- . C/ D5 K$ c2 x: A; m( U
- return desc_report.inputs->data;
8 x7 h4 R3 x2 ~+ M2 d) ? - }
复制代码
# U4 k* i/ n6 u# I* [5 O运行模型
- Y$ y2 a r9 k8 Q4 `- void ai_run(void* input, void* output)1 U+ W0 g9 G' e! M S5 V- d( J
- {
1 N4 j$ B6 A" H& C! v - ai_i32 nbatch;
- M6 P. _6 B( |+ L- S# {6 v8 h3 T - & K4 n" n7 @. C* q& |; P
- ai_input[0].data = AI_HANDLE_PTR(input);& C% H; y% p) d) V
- ai_output[0].data = AI_HANDLE_PTR(output);
9 r' @1 G( v$ L! { -
1 a1 @2 I6 ^5 |5 U) j - nbatch = ai_network_run(network_handle, &ai_input[0], &ai_output[0]);* ]' \1 i) k% b7 {2 Z+ [ l% ?. i
- & L2 l0 C- I/ B* X2 D
- if (nbatch != 1) {, R4 ?) e0 \0 p, p, u" ~9 [ D
- while(1);+ \8 l q2 v. r* N7 o D( i! P
- }
3 X/ @: @% E3 G0 n - }
复制代码
0 }1 S r5 ?6 w# r$ t3 [图像接收处理,这个模型要求输入224*224的RGB888的图像,把数据转换一下。2 _5 }' K0 |- U3 \# _
- void HAL_DCMI_FrameEventCallback(DCMI_HandleTypeDef *hdcmi)$ o2 j3 R7 f L$ Z' p2 ^2 C; ~ F
- {7 `; V6 _* l L0 m* z6 `
- uint8_t person_flag;
E* i" n8 [' M - int i,j; W, q7 L- x/ p9 p/ _; f
- for(i=0; i<224; i++)
( z) l F/ {1 D! n1 a" g - {
9 j, D" J& v0 \6 U# O - for(j=0; j<224; j++)
6 |% Q/ d [- G2 ]9 A$ Y - {* f$ {' x0 C( R" x
- uint16_t bg_color = ((uint16_t *)_OV2640->frame->buffer)[i*320 + j];
s" W2 _# C( h% ^' L - network_input[3*i*224 + 3*j + 0] = ((bg_color>>11)&0xff)<<3;% m5 u& q6 ~. f' W4 Y' E o
- network_input[3*i*224 + 3*j + 1] = ((bg_color>>5)&0x3f)<<2;
. _$ W6 o! u7 g8 L/ m; z* s' W - network_input[3*i*224 + 3*j + 2] = (bg_color&0x1f)<<2;
# b6 ^5 T3 d! z; D - }
' h( p3 C$ V7 L, B' _: r - }! }8 Q* W, p+ h( O: \
- ai_run(network_input, network_output);9 P1 t& j! R# j. r
- ! R: A; Q3 Q/ E3 T3 R& H' v
- LCD_Draw_Image(0, 0, 320, 240, (uint16_t *)_OV2640->frame->buffer);
) {: T6 W r" _ @1 y% D2 t - LCD_Draw_String(0, 0, 320, 240, 32, output_labels[network_max()]);
; b& q E7 @9 {) ]8 S: @5 U -
1 _1 p. e4 a4 |. v9 m - OV2640_DMA_Config(_OV2640->frame->buffer, (_OV2640->frame->length)/4);
8 i) z7 i/ G: B e q' a7 P - 2 j7 }( e: g- a
- }
复制代码 . U1 X7 O8 G* O% N8 R. t
& M2 L4 t1 t+ x( @' Q$ D
运行效果(一共能识别18种食物,这里选了几个看看)2 L7 z3 ?) F* v4 D+ ]& _* M
( ^6 {. z' Z; H. c空+ I8 Y& z1 H6 n, s* r7 W7 S- w
- @. P+ n, S2 q8 h# k" B* B可乐
8 D' ^9 Z2 H& p f" @# Q
6 M8 [4 S U4 ?2 h$ k, M6 e" n: B& Q9 e3 D! L
甜甜圈* C: U+ L4 r2 q9 F. p8 U% s# W
: R2 h1 K3 ?- r8 I& _
8 _) L3 S& m0 M* I4 M/ j; m汉堡包! N* Y- q3 b: z+ O! Q. V7 Q
7 p% J+ f; \8 p+ c
# G) m5 ~: e; e+ ?薯条
; w4 E5 O; X7 e0 p! v& ?
M4 l5 o4 |& q+ V2 j6 ]9 F8 [( C$ D+ A0 f
% E# l& s) {- n5 D3 L1 w
小结:STM32Cube.AI工具真的太香了,这里仅仅演示了模型的部署,其实可以快速验证AI模型在目标板上的运行情况,只用串口连接,直接把输入发送到单片机,然后运行完后把结果返回来,全部都集成到了一起,快速验证模型运行情况。很是方便(本文未涉及,有需要的可以在X-CUBE-AI行下勾选时,application里面选择validation,回到配置界面后设置通信接口即可): N$ o: [% x: [
Wio Lite AI视觉开发套件确实是开发AI的很好的选择之一,板子虽小五脏俱全,拿来做单片机视觉绰绰有余,但是不得不吐槽的一点是资料支持太差了,原理图,代码全都藏起来,前期调驱动花了很长的时间,后来管管给了一个例程后好转了一些(但是已经晚了。。。),Ai在单片机上应用已经有很多厂商都推出类似的解决方案了,ST这一个环境很优秀,就是如果相关的培训跟资料再多一点就好了。
& G! H6 |% D D+ H5 ^) N+ X4 E# i |
up有没有原理图资料~
求求了
[md]好久之前做的了,资料都忘了放哪里了。。。你可以在网上找找,或者找卖家要
up 有更详细一点的建文件工程的教程吗? 还有模型怎么弄上去, 求解
按这个文章操作就行