
写的教程反响平平,可能是晦涩难懂,那就直接上代码(极度粗糙的demo)。 接上次的软硬件环境,我采用的STemwin(本来想用littlevgl)自带bmp显示(详细代码可参考某某莱教程)。先看看生成的一些代码。 / W; {; G) |* O/ z& }2 [ GUI_Init();: D% H9 L3 E" R* j5 c, I0 y GUI_SetBkColor(GUI_BLUE_98);% C& R t$ t. x i GUI_Clear();+ ~& F: `2 b4 G' I1 A GUI_DispStringHCenterAt( GUI_GetVersionString() , GUI_GetScreenSizeX()/2, GUI_GetScreenSizeY()/2); SDRes=f_mount(&SDFatFS,(TCHAR*)SDPath,0); if(SDRes!=FR_OK) {6 M# J, g) X& e. t Error_Handler(); }* I3 K/ I- `& J+ K& {7 h. h+ R& [: h MX_X_CUBE_AI_Process();7 q' G3 P) P& M /* USER CODE END 2 */- N& Q8 e. Q5 t /* Infinite loop */+ m( o. K6 |6 q Q /* USER CODE BEGIN WHILE */! p; P4 O! S6 L# R while (1) {. m O% j! f# g+ J; { /* USER CODE END WHILE */2 \* p0 v; l5 c3 K) {9 b X9 _# N GUI_Delay(10);4 R A' _% K& \( _+ e0 k6 M N /* USER CODE BEGIN 3 */ } 简单的主函数。 6 U4 Z" h, z# w c) N; {# q0 Q 进入MX_X_CUBE_AI_Process();( U" t+ g/ }: f& Y) A1 R ai_buffer ai_input;! i! c( g9 G8 g ai_buffer ai_output;+ q2 h9 B: D) J6 B, b: f; Z ai_i32 batch;3 j. X9 J C8 Y char str_tmp[16]; for(uint8_t i=0; i<10; i++) {" e( D! s& v) E% q6 f sprintf(str_tmp,"%1d.bmp",i); _ShowBMPEx(str_tmp);9 ?7 `4 Z# I& ~ S+ D' t LCD_ShowBMP(str_tmp);# @$ w' W( e! S0 T: u for(uint16_t i=0; i<AI_LENET_IN_1_SIZE ; i++ ). m$ i9 s0 ]" q+ G) r, }6 A { in_data[i] = *bmpBuffPtr++;5 j$ v; y5 y/ K J m$ v }2 B8 I$ B+ T: q5 n- L' h ai_input.n_batches = 1;5 _8 O4 B* i+ X ai_input.data = AI_HANDLE_PTR(in_data); ai_output.n_batches = 1; ai_output.data = AI_HANDLE_PTR(out_data);& [) v8 F6 o; |! s% P; ]7 t batch = ai_lenet_run(handel, &ai_input, &ai_output); if (batch != 1) # Q8 O. I, a% \. {( w6 ~' R: G { err = ai_lenet_get_error(handel);- R) l2 i$ H' p. E$ u7 C3 J. [. l if( err.code ) {& g, v* x" E8 @; c6 u6 D) ^ while(1); } }( g) a: v5 h/ z5 \: B& X uint8_t count=0; for(uint8_t i=0; i<AI_MNETWORK_OUT_1_SIZE; i++)6 G8 y: I3 C# q7 v0 \! G { if( out_data[i] >=0.9f) {7 g* k9 {( R. I. c: D0 e0 L sprintf(str_tmp,"Num:%d",i); GUI_SetFont(GUI_FONT_32B_ASCII); GUI_DispStringAt(str_tmp,200,0); GUI_SetFont(GUI_FONT_16B_ASCII); count++;* H' L) x( P% F6 d& V } A. h0 A5 D7 \- _( z }0 i) t- u W3 S! r+ }% r! z9 y if(count!=1) {. }5 p- e6 m. V GUI_SetFont(GUI_FONT_32B_ASCII); ]+ `+ \1 e5 u' O/ `4 {& }. G# i GUI_DispStringAt("err",200,0); GUI_SetFont(GUI_FONT_16B_ASCII); } free(bmpBuffPtr); HAL_Delay(2000);. z; K4 e; K5 ^; @ 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 型 何必不输出 所有的置信度。后面我将继续挖掘。 2 ?- K1 S+ f4 Q. `' O, F) O 流程介绍完毕,下面说一说cubeAI的主要函数。 ai_lenet_create(&handel, NULL);% [- s/ O' ~( e( t7 \3 H$ y ai_lenet_get_info(handel, &report); ai_network_params params = {- B) Q' U T( j1 R% ^ AI_LENET_DATA_WEIGHTS(ai_lenet_data_weights_get()), //权重的获取+ }. |) E+ q- n; J! ^ o. M AI_LENET_DATA_ACTIVATIONS(activations) // 激活函数 }; ai_lenet_init(handel, ¶ms); //lenet的初始化,估计是申请内存什么的,写flash。0 C4 g2 F( `5 F1 E) a- S; ] err = ai_lenet_get_error(handel);. Q# F- C& O' S1 h) m y batch = ai_lenet_run(handel, &ai_input, &ai_output); //图片输入以及处理完毕的输出,1batch批9 F. P: `1 @6 n" [7 O+ k9 p/ Q 总的来说比较简单的demo,其实也可以做复杂一点,先手写然后STemwin存bmp图片,然后利用加权平均得到BMP颜色数据的灰度,输入到lenet,dedaojieguo。效果会比较酷炫。 这模型被压缩很厉害,能有这样的结果以及不错了,最后祝贺一下ST,半导体前15! 期待MP1,玩玩不用压缩的AI。+ K5 t4 W+ s2 g7 J9 H k 附件:工程源码。 : }$ A# T2 I8 e1 {% J3 R |
Minist.rar
下载10.2 MB, 下载次数: 150
【STM32N6570-DK评测】1.开箱测评
【STM32N6570-DK评测】1.你好N6
实战经验 | STM32 AI Model Zoo 的安装及实例介绍
【STM32H7S78-DK评测】移植AI框架TensorFlow【DSP指令加速篇】
【STM32H7S78-DK评测】移植AI框架TensorFlow【下篇】
【STM32H7S78-DK评测】移植AI框架TensorFlow Lite【上篇】
【STM32H7S78-DK评测】移植边缘AI推理框架——TFLM(TensorFlow Lite for Microcontrollers)上篇
破解边缘AI硬件与软件挑战,意法半导体解读三大创新要点
意法半导体助力企业产品智能化,加快边缘人工智能应用
STM32不至于芯,2023济南站研讨会
谢谢支持