写的教程反响平平,可能是晦涩难懂,那就直接上代码(极度粗糙的demo)。 接上次的软硬件环境,我采用的STemwin(本来想用littlevgl)自带bmp显示(详细代码可参考某某莱教程)。先看看生成的一些代码。 GUI_Init(); GUI_SetBkColor(GUI_BLUE_98); GUI_Clear(); GUI_DispStringHCenterAt( GUI_GetVersionString() , GUI_GetScreenSizeX()/2, GUI_GetScreenSizeY()/2); SDRes=f_mount(&SDFatFS,(TCHAR*)SDPath,0); if(SDRes!=FR_OK) {0 \2 c/ e: k/ \7 w6 D. G: A- R, d& j Error_Handler(); } MX_X_CUBE_AI_Process();4 y/ B( v9 ]7 Q9 f, k6 Z /* USER CODE END 2 */$ L. W: j: t- p$ S4 p8 g /* Infinite loop */8 l- Q- a. X) N# { /* USER CODE BEGIN WHILE */5 r% Y" w5 @/ D. S! C while (1)( k! s0 w: S3 [6 P7 A {) H2 j, V" W7 R7 t$ L /* USER CODE END WHILE */$ ^) ~( `# I3 }4 I GUI_Delay(10); /* USER CODE BEGIN 3 */. i. t' v l$ H }. M# x) w3 s N Q. A$ Q 简单的主函数。 . K' U. N+ n- c' a- B3 r2 f2 ` 0 K+ }, M. ~8 m, ^- a" [ 进入MX_X_CUBE_AI_Process();0 B5 Y% i; W, o: {6 X% I- K 0 K w4 C/ b+ k8 g% U* C ai_buffer ai_input; ai_buffer ai_output;7 v; F# S. m. W8 T ai_i32 batch; char str_tmp[16];. C3 ~! }# v, d8 F for(uint8_t i=0; i<10; i++) {) ]. W3 M4 w! \. _; ? sprintf(str_tmp,"%1d.bmp",i); _ShowBMPEx(str_tmp); LCD_ShowBMP(str_tmp);$ h0 E# C: b$ U3 ]) Y! X for(uint16_t i=0; i<AI_LENET_IN_1_SIZE ; i++ )9 b& i; a" R y) w' j {4 f3 r; o7 z3 s* K in_data[i] = *bmpBuffPtr++;( v& r R6 D9 i J( P$ f, G }! M* J s6 P5 T$ F ai_input.n_batches = 1; ai_input.data = AI_HANDLE_PTR(in_data);; d0 x; l+ q5 H* n/ V1 j0 ? ai_output.n_batches = 1; ai_output.data = AI_HANDLE_PTR(out_data); batch = ai_lenet_run(handel, &ai_input, &ai_output); if (batch != 1) , x* \0 o( \" g8 i {$ f$ Y4 I+ {. ^ err = ai_lenet_get_error(handel);& V" v7 }4 {& ^+ L( N: t; n8 \" I if( err.code )8 s3 A7 T7 V2 q& J2 m2 F {9 y% Y, A j5 @* V5 y# b: }! q while(1); }; m2 x$ R) `( Z* v3 K: F$ L% j } uint8_t count=0; for(uint8_t i=0; i<AI_MNETWORK_OUT_1_SIZE; i++) {6 p* J/ \4 r% b0 C if( out_data[i] >=0.9f)' ?% X9 s$ o5 o& j; R$ _% j { sprintf(str_tmp,"Num:%d",i);( M0 e( z& s+ B, }2 G. h GUI_SetFont(GUI_FONT_32B_ASCII);: m5 b6 Z) M: v* B GUI_DispStringAt(str_tmp,200,0); GUI_SetFont(GUI_FONT_16B_ASCII);. j7 d% P! H. G2 S# I2 P count++;- a$ x8 ?$ x( [9 W" x, ^/ W7 O z2 u- g M }/ h) n* w9 s* r7 c/ o p4 A }7 A; V% {# t5 y3 v$ P. ~ if(count!=1)9 g7 _8 K9 ` a& o. m {' t5 P @) K( H8 P( E8 j# e$ e GUI_SetFont(GUI_FONT_32B_ASCII); GUI_DispStringAt("err",200,0);( p' n/ N% b& N9 k GUI_SetFont(GUI_FONT_16B_ASCII);! D5 y" |5 g) E V3 U }3 ]3 Z( E/ {; k' Y8 \ free(bmpBuffPtr); 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 型 何必不输出 所有的置信度。后面我将继续挖掘。 流程介绍完毕,下面说一说cubeAI的主要函数。. g8 W* ?3 ^3 A Y/ `- J$ i- H7 C ai_lenet_create(&handel, NULL);6 |3 ?* k" c# T+ C+ r2 }. B7 I ai_lenet_get_info(handel, &report);) G; I: k$ c- W/ F6 q) ~$ a7 w ai_network_params params = { AI_LENET_DATA_WEIGHTS(ai_lenet_data_weights_get()), //权重的获取/ O* u1 [6 g4 b c0 S8 ~4 ^/ Y: [ AI_LENET_DATA_ACTIVATIONS(activations) // 激活函数1 T) w* h' e: i7 M! L* N };, ~0 Y u3 U, z$ t1 u9 s ai_lenet_init(handel, ¶ms); //lenet的初始化,估计是申请内存什么的,写flash。% B6 Y3 f6 Y( T; K err = ai_lenet_get_error(handel); batch = ai_lenet_run(handel, &ai_input, &ai_output); //图片输入以及处理完毕的输出,1batch批 5 N$ A1 e' \# x 总的来说比较简单的demo,其实也可以做复杂一点,先手写然后STemwin存bmp图片,然后利用加权平均得到BMP颜色数据的灰度,输入到lenet,dedaojieguo。效果会比较酷炫。/ O: H/ }5 r9 U' a 这模型被压缩很厉害,能有这样的结果以及不错了,最后祝贺一下ST,半导体前15! 期待MP1,玩玩不用压缩的AI。 附件:工程源码。 ' `. J" Q3 `4 b2 K! ]0 | |
Minist.rar
下载10.2 MB, 下载次数: 150
谢谢支持