|
写的教程反响平平,可能是晦涩难懂,那就直接上代码(极度粗糙的demo)。 接上次的软硬件环境,我采用的STemwin(本来想用littlevgl)自带bmp显示(详细代码可参考某某莱教程)。先看看生成的一些代码。3 `! Q2 D0 Q" k) H' d4 G8 F" C- K' n GUI_Init(); GUI_SetBkColor(GUI_BLUE_98);/ u( y3 r1 _ V" N5 `" u# Y$ e GUI_Clear(); : Z4 k1 X6 E! R- M8 y. ^% x4 v GUI_DispStringHCenterAt( GUI_GetVersionString() , GUI_GetScreenSizeX()/2, GUI_GetScreenSizeY()/2);# y1 V4 C% o- `# ? SDRes=f_mount(&SDFatFS,(TCHAR*)SDPath,0);3 _0 J+ u/ G b3 ?/ `+ f( s if(SDRes!=FR_OK) { Error_Handler(); } MX_X_CUBE_AI_Process();) F! A9 f& t" {/ Z0 O- S /* USER CODE END 2 */3 X. z- f7 P" [! W' U! O /* Infinite loop */6 @ j! r+ e3 Y. L; ]7 f /* USER CODE BEGIN WHILE */5 w e& p4 C: m& h' q$ Z while (1) {. r( _( w+ q, V! u' o1 R+ { /* USER CODE END WHILE */ GUI_Delay(10);% Y, E2 Y9 v# j' ]0 ~ /* USER CODE BEGIN 3 */7 {! q6 G t( Y6 `" o) S }. o: E( t) o9 ^0 a1 o 简单的主函数。 2 I6 H/ P. p8 m' N) ] 进入MX_X_CUBE_AI_Process(); 9 \# V9 x- i7 o1 c 4 x- H' Z( ?/ }* C8 _/ U! W/ d( J4 d ai_buffer ai_input;) ~; z2 R% a, U8 l ai_buffer ai_output; ai_i32 batch;& y5 E, D# |# _" r$ U, t+ `8 _ char str_tmp[16];0 m/ u5 S8 D# E8 L/ v8 f for(uint8_t i=0; i<10; i++)1 t2 q- x- _( U( t# b {/ Z- J5 ?( W9 P; Z; I2 N0 y sprintf(str_tmp,"%1d.bmp",i); _ShowBMPEx(str_tmp);2 W0 ?3 y: }8 m. R. }0 A LCD_ShowBMP(str_tmp);0 A+ y8 H7 E3 G. g for(uint16_t i=0; i<AI_LENET_IN_1_SIZE ; i++ ): y0 P. N; I H: s8 R* W5 a! p# W& q {- g0 r! A# j; f, V8 l in_data[i] = *bmpBuffPtr++;. z' z# q5 z/ q4 c8 ^ }2 E% z- M, M& L n9 H: k ai_input.n_batches = 1;4 w/ f! o! b+ P- k) W8 b# }9 ~4 } ai_input.data = AI_HANDLE_PTR(in_data); 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) / u0 F4 M1 s, [7 q {! \8 j' L* c Z. m err = ai_lenet_get_error(handel);& A$ W( o" E' o) z1 g5 O, P* v if( err.code )+ k( a4 m1 {0 x! s1 E% D { while(1);6 { E* `2 d1 ?9 ?3 o }& o! k5 i5 z; B+ b: {* c }5 \0 q0 A4 L( x$ t5 a9 a0 v uint8_t count=0; for(uint8_t i=0; i<AI_MNETWORK_OUT_1_SIZE; i++) {1 g x0 x4 m1 ` if( out_data[i] >=0.9f) {9 v; X/ S, j7 l, g I7 r7 w k sprintf(str_tmp,"Num:%d",i); GUI_SetFont(GUI_FONT_32B_ASCII);- E. z, b6 U9 o# r" K: \ GUI_DispStringAt(str_tmp,200,0);: {- k. g1 }1 B# A% H7 c& I GUI_SetFont(GUI_FONT_16B_ASCII);/ U4 e+ v" w2 v count++; p `4 s/ t( n( \5 C }! t* K4 p. c/ X( |9 |* v/ p6 M } if(count!=1) {5 S/ N- H' X$ f# A7 d GUI_SetFont(GUI_FONT_32B_ASCII);" b! j. ^0 V) [) ~6 E0 J+ r GUI_DispStringAt("err",200,0);: g0 [" I' L, U* a, P GUI_SetFont(GUI_FONT_16B_ASCII);; `, t2 u' z. K" u) G+ P }, ] q5 Q# [+ k) W# E% r9 q2 t3 G free(bmpBuffPtr); HAL_Delay(2000);6 p# k& U' z; n8 P- ? }( W4 }# r$ N1 M1 Q 熟悉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 型 何必不输出 所有的置信度。后面我将继续挖掘。 , o' F: t0 x8 W 流程介绍完毕,下面说一说cubeAI的主要函数。 ai_lenet_create(&handel, NULL); ai_lenet_get_info(handel, &report); ai_network_params params = { AI_LENET_DATA_WEIGHTS(ai_lenet_data_weights_get()), //权重的获取( m* h# Z2 a( y$ B6 P AI_LENET_DATA_ACTIVATIONS(activations) // 激活函数 }; ai_lenet_init(handel, ¶ms); //lenet的初始化,估计是申请内存什么的,写flash。0 f, E. x" t2 w. x err = ai_lenet_get_error(handel); batch = ai_lenet_run(handel, &ai_input, &ai_output); //图片输入以及处理完毕的输出,1batch批/ U6 k2 s$ a+ c) z " @" l1 A- r7 o9 U 总的来说比较简单的demo,其实也可以做复杂一点,先手写然后STemwin存bmp图片,然后利用加权平均得到BMP颜色数据的灰度,输入到lenet,dedaojieguo。效果会比较酷炫。9 e+ n2 F v+ P. ^/ j2 i 这模型被压缩很厉害,能有这样的结果以及不错了,最后祝贺一下ST,半导体前15! 期待MP1,玩玩不用压缩的AI。" r& m* o, J8 ~! X! [; N) v 附件:工程源码。$ Z8 J; Z; C+ m5 ~$ ]* ^( z2 X+ V " k3 k4 ~0 J1 l |
Minist.rar
下载10.2 MB, 下载次数: 150
【STM32H5 评测】MNIST 数字识别
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进行端侧推理
微信公众号
手机版
谢谢支持