
写的教程反响平平,可能是晦涩难懂,那就直接上代码(极度粗糙的demo)。 接上次的软硬件环境,我采用的STemwin(本来想用littlevgl)自带bmp显示(详细代码可参考某某莱教程)。先看看生成的一些代码。 2 U0 r9 E7 x' W; r GUI_Init(); l# j, z. }" ], r' W# Y GUI_SetBkColor(GUI_BLUE_98); GUI_Clear();( Y4 H: j0 C; ?7 O6 _( [ 7 u9 G f* u4 q3 f4 J2 N5 }8 [2 a GUI_DispStringHCenterAt( GUI_GetVersionString() , GUI_GetScreenSizeX()/2, GUI_GetScreenSizeY()/2);6 j' b; ]$ c" c4 Y% y SDRes=f_mount(&SDFatFS,(TCHAR*)SDPath,0); if(SDRes!=FR_OK) { Error_Handler();0 {4 Y7 ?7 ?; P( b } MX_X_CUBE_AI_Process(); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */! o- u; j, i5 w6 p W while (1)! @. J& V' K, ?( J0 L' l7 s {6 H7 _% e4 u1 E /* USER CODE END WHILE */: t* j1 v, \ x& P5 h+ [ G GUI_Delay(10);" W; H, z, i/ h/ n/ K /* USER CODE BEGIN 3 */ }3 A* d1 K, i) A8 s 简单的主函数。: t7 g3 j8 t( ?6 h' @ 7 K- {( l1 u( y: L) K1 K$ V 4 X4 N# X* d) l8 j2 i2 E 进入MX_X_CUBE_AI_Process(); 0 `) i3 S2 f( H5 Y ai_buffer ai_input;) ~. B% y" q1 b; h- I! R: |. w/ O ai_buffer ai_output;2 b w" Z$ V- K I ai_i32 batch;( `7 `2 o G, f: i- _+ R char str_tmp[16]; for(uint8_t i=0; i<10; i++) { sprintf(str_tmp,"%1d.bmp",i); _ShowBMPEx(str_tmp);! Q1 P+ h8 l- P8 u2 v LCD_ShowBMP(str_tmp);3 k; |' M4 x( p: n W for(uint16_t i=0; i<AI_LENET_IN_1_SIZE ; i++ )% U& Z" C. S: ]. T6 m! b0 t {# w/ w3 R |0 X) u, M. y in_data[i] = *bmpBuffPtr++; } e! x \8 p0 h& i* c ai_input.n_batches = 1;* U' E* w4 Z/ |8 Y$ G. }; P* b4 D) A ai_input.data = AI_HANDLE_PTR(in_data); ai_output.n_batches = 1; ai_output.data = AI_HANDLE_PTR(out_data);/ J+ z( {9 z9 e0 G batch = ai_lenet_run(handel, &ai_input, &ai_output); if (batch != 1) {: R. I9 c& R, {8 Q2 h$ N err = ai_lenet_get_error(handel); if( err.code )5 n2 R' }9 u7 Y4 L* \! @; l4 d {$ Y5 P. x# ^$ N while(1);5 q' W/ R. p+ }: w' F& u- ]3 q } }4 H: K1 O2 @1 \4 Q6 y' s' J uint8_t count=0;* {' G/ H* V3 \7 r- f6 N for(uint8_t i=0; i<AI_MNETWORK_OUT_1_SIZE; i++)9 D$ V9 ^3 e7 L. ~* }! D: o8 Y* v9 w {2 I9 U- A7 Q9 _4 T' V if( out_data[i] >=0.9f) {7 I! R2 V& l. p8 A sprintf(str_tmp,"Num:%d",i); GUI_SetFont(GUI_FONT_32B_ASCII);* d4 |& }5 v4 O$ n0 x5 U GUI_DispStringAt(str_tmp,200,0);3 h# O0 S& L2 v4 { GUI_SetFont(GUI_FONT_16B_ASCII); count++; }5 i, `! a1 a" r: p& _ }: `& N7 [$ v' M if(count!=1); ^$ B; z: [' f& }% q* {0 s {. D% _) b' ?+ A8 ^: p7 ? GUI_SetFont(GUI_FONT_32B_ASCII);! l- p. F! ?7 l' P) V8 c GUI_DispStringAt("err",200,0);/ z- R. C6 k5 V+ q" N GUI_SetFont(GUI_FONT_16B_ASCII);& f( z) t* e- j# d; A4 [ } free(bmpBuffPtr);2 _3 k- U% l ]/ v2 Z' d+ O HAL_Delay(2000); } 熟悉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 型 何必不输出 所有的置信度。后面我将继续挖掘。 , k; ]% y6 H8 e8 t4 K9 B& h 流程介绍完毕,下面说一说cubeAI的主要函数。/ t. @3 g6 d7 c: N ai_lenet_create(&handel, NULL); ai_lenet_get_info(handel, &report); ai_network_params params = { Q4 u/ q1 Y: a) T4 J AI_LENET_DATA_WEIGHTS(ai_lenet_data_weights_get()), //权重的获取& q: N+ {. M; G$ [8 A: s2 D" \7 S AI_LENET_DATA_ACTIVATIONS(activations) // 激活函数 }; ai_lenet_init(handel, ¶ms); //lenet的初始化,估计是申请内存什么的,写flash。# Q U& I( c0 u' ^1 K A1 Q0 P err = ai_lenet_get_error(handel); + ~' A' J; H3 H0 \" g! s batch = ai_lenet_run(handel, &ai_input, &ai_output); //图片输入以及处理完毕的输出,1batch批 总的来说比较简单的demo,其实也可以做复杂一点,先手写然后STemwin存bmp图片,然后利用加权平均得到BMP颜色数据的灰度,输入到lenet,dedaojieguo。效果会比较酷炫。 这模型被压缩很厉害,能有这样的结果以及不错了,最后祝贺一下ST,半导体前15! 期待MP1,玩玩不用压缩的AI。; | g: \" I5 R% w5 X$ }8 X 附件:工程源码。 % M0 [5 d0 s7 ]+ J( u% K# {! N : y4 A. B2 F3 S |
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济南站研讨会
谢谢支持