|
写的教程反响平平,可能是晦涩难懂,那就直接上代码(极度粗糙的demo)。: W) f: N/ \# u+ S 接上次的软硬件环境,我采用的STemwin(本来想用littlevgl)自带bmp显示(详细代码可参考某某莱教程)。先看看生成的一些代码。 2 P# I* R0 e" H! C1 ?$ A" y6 v GUI_Init(); GUI_SetBkColor(GUI_BLUE_98); GUI_Clear(); ! d- {( N/ \! x* z7 w) t GUI_DispStringHCenterAt( GUI_GetVersionString() , GUI_GetScreenSizeX()/2, GUI_GetScreenSizeY()/2); SDRes=f_mount(&SDFatFS,(TCHAR*)SDPath,0); if(SDRes!=FR_OK) {; e e6 }( \5 {3 \' `( d' L Error_Handler(); } MX_X_CUBE_AI_Process();2 v' v& V6 H+ `3 ]/ s+ Y9 Q x. f /* USER CODE END 2 */; R3 E" C3 a* ]+ K' D /* Infinite loop */* w% [4 [* K- k% p /* USER CODE BEGIN WHILE */ while (1) {7 W' Z# C2 |, } T/ q1 H2 Y4 p /* USER CODE END WHILE */# [! n7 n9 d# P& f( l4 Y GUI_Delay(10);! s- V0 Y" r3 d0 U9 v /* USER CODE BEGIN 3 *// g9 q* m; n9 ~/ `; Z } 简单的主函数。 6 r" z9 _" g' g: `3 O" C 4 ?& A! P a8 \) F/ \ 进入MX_X_CUBE_AI_Process();9 H9 m* q4 z2 z' y. M4 K ai_buffer ai_input;. G2 L4 ]3 g& c l+ d0 h9 ^ ai_buffer ai_output; ai_i32 batch; char str_tmp[16];2 R4 g0 M- N) w; ~ for(uint8_t i=0; i<10; i++)# Y) h4 d2 A8 k% ?. T { sprintf(str_tmp,"%1d.bmp",i); T( i' g4 }: d( |+ t' @ _ShowBMPEx(str_tmp);4 ?" }& _8 o' ~( b) c LCD_ShowBMP(str_tmp); for(uint16_t i=0; i<AI_LENET_IN_1_SIZE ; i++ )" J$ z Z3 R. [# l$ K' c! h { in_data[i] = *bmpBuffPtr++;/ X! }4 `4 k' d4 E( d3 C& } }- ~8 K P0 R* d" B ai_input.n_batches = 1; ai_input.data = AI_HANDLE_PTR(in_data);2 B$ @* V- q4 o! T" D! D ai_output.n_batches = 1; ai_output.data = AI_HANDLE_PTR(out_data);. F" c; P! B# A" e- \6 j batch = ai_lenet_run(handel, &ai_input, &ai_output); if (batch != 1) & c0 {! V9 `4 P3 q' S/ C { err = ai_lenet_get_error(handel); if( err.code ): Y( `% ^" C# Z' _. [+ X { while(1);/ _) i$ X. P- X- \ } } uint8_t count=0; A/ C% G) A2 O/ v3 y for(uint8_t i=0; i<AI_MNETWORK_OUT_1_SIZE; i++) { if( out_data[i] >=0.9f)% P: I5 _9 u1 K2 Y7 E2 B' j+ M {+ w4 }+ ?4 Q/ ~& P# c. V/ `0 S1 o sprintf(str_tmp,"Num:%d",i);" M0 g: x$ a4 ~; O+ b& P* q GUI_SetFont(GUI_FONT_32B_ASCII);' {5 m, ~+ K i; w5 C2 C F GUI_DispStringAt(str_tmp,200,0); GUI_SetFont(GUI_FONT_16B_ASCII);2 x8 _$ [" `" p$ E$ c$ v count++; } }0 J0 v- t8 ^2 H4 U } if(count!=1) {' \! ~1 R2 J5 ~- O0 `. A GUI_SetFont(GUI_FONT_32B_ASCII);2 |, H6 S8 M, z GUI_DispStringAt("err",200,0); GUI_SetFont(GUI_FONT_16B_ASCII);: A* S: ]. U. r# c$ A" c } free(bmpBuffPtr); B! C1 u. m$ \0 m7 U. ^% R HAL_Delay(2000); }1 A, I i f; ^ 0 k5 K5 \: e3 N3 z) ^$ s) {; _ 熟悉STemwin的大佬肯定知道我在干嘛,不断的读取SD卡中的bmp文件,然后显示,并且通过ai_lenet_run函数得到识别结果,输出是static ai_float out_data[AI_MNETWORK_OUT_1_SIZE]; 0-9有十个识别结果,这个向量大小是十。调试程序时,输出不像是我在PC ubuntu caffe环境中的输出结果,PC上主要是以softmax得到每个类别的置信度,所以PC上向量肯定全部都有值,置信度最高即为模型结果。在MCU上,输出结果只有零和一。让我很奇怪,既然是ai_float 型 何必不输出 所有的置信度。后面我将继续挖掘。$ y* j# t) r( o2 @' f) B+ b+ B( n 流程介绍完毕,下面说一说cubeAI的主要函数。1 m% U- Z& P6 U2 W% A5 V' C ai_lenet_create(&handel, NULL); j! P) _; }6 ^2 g( n! }* g' [ ai_lenet_get_info(handel, &report); ai_network_params params = {% V: y$ x; [! q7 T5 ^% @ AI_LENET_DATA_WEIGHTS(ai_lenet_data_weights_get()), //权重的获取 AI_LENET_DATA_ACTIVATIONS(activations) // 激活函数5 Z, P* ^; f1 I& d' o* b };, Q/ L ~. V' \) w6 t ai_lenet_init(handel, ¶ms); //lenet的初始化,估计是申请内存什么的,写flash。: [* N! i, E5 ` err = ai_lenet_get_error(handel); ; L6 m: }7 D _1 h5 R3 ? batch = ai_lenet_run(handel, &ai_input, &ai_output); //图片输入以及处理完毕的输出,1batch批 总的来说比较简单的demo,其实也可以做复杂一点,先手写然后STemwin存bmp图片,然后利用加权平均得到BMP颜色数据的灰度,输入到lenet,dedaojieguo。效果会比较酷炫。 这模型被压缩很厉害,能有这样的结果以及不错了,最后祝贺一下ST,半导体前15! 期待MP1,玩玩不用压缩的AI。 附件:工程源码。7 p+ F: L- H+ k/ s4 T 0 T3 M; O( f6 S" A! a4 @8 ` |
Minist.rar
下载10.2 MB, 下载次数: 150
STM32在边缘AI的布局及能力版图
从家电到机器人:STM32边缘AI应用案例拆解
STM32U3B5/U3C5:为超低功耗设计带来高性能 DSP 与边缘 AI
【NUCLEO-U3C5ZI 测评】+ 手写数字识别
【STM32U3 评测】MNIST 数字识别
AI玩具爆发前夜:技术拐点、体验鸿沟与破局路径
STM32 AI Model Zoo,现支持PyTorch的最大规模MCU AI模型集合
经验分享 | STM32 AFCI 方案 TensorBoard 使用指南:AI 模型调优可视化终极方案
STM32F334运行超轻量级神经网络推理框架TinyMaxi进行端侧推理
【DIY-STM32N6570-DK-MINI板子功耗测试】
微信公众号
手机版
谢谢支持