|
写的教程反响平平,可能是晦涩难懂,那就直接上代码(极度粗糙的demo)。 接上次的软硬件环境,我采用的STemwin(本来想用littlevgl)自带bmp显示(详细代码可参考某某莱教程)。先看看生成的一些代码。: N( p6 Z+ m7 u8 t GUI_Init(); GUI_SetBkColor(GUI_BLUE_98); GUI_Clear(); GUI_DispStringHCenterAt( GUI_GetVersionString() , GUI_GetScreenSizeX()/2, GUI_GetScreenSizeY()/2);, j. W4 a$ }- D9 h9 J% e* c SDRes=f_mount(&SDFatFS,(TCHAR*)SDPath,0); if(SDRes!=FR_OK) { Error_Handler(); } MX_X_CUBE_AI_Process(); /* USER CODE END 2 */ /* Infinite loop */! P e# ]7 u! z2 y" Y /* USER CODE BEGIN WHILE */, z! N2 S3 V. f% f4 q! } while (1)* h0 V7 ]' n: N+ K, N {8 C3 U- j) z3 s# k; ] /* USER CODE END WHILE */ GUI_Delay(10);7 p+ S a' S1 g- S! z /* USER CODE BEGIN 3 */ }( W8 X q5 `/ s i. ? 简单的主函数。 c9 f0 c7 w( B+ F2 e+ W) I l 进入MX_X_CUBE_AI_Process(); H. Q! p: Y6 \ n U8 ]" T ai_buffer ai_input;8 t* U( {2 d4 |- t ai_buffer ai_output;) h3 L: _( E0 W" S+ u/ h ai_i32 batch; char str_tmp[16];2 N) g: [' W6 I for(uint8_t i=0; i<10; i++) { sprintf(str_tmp,"%1d.bmp",i); _ShowBMPEx(str_tmp);! Q2 y3 v. S$ v8 L1 J, D LCD_ShowBMP(str_tmp); for(uint16_t i=0; i<AI_LENET_IN_1_SIZE ; i++ )5 X! ^ X. B3 M. X7 N2 @ {6 k0 h9 P8 l3 K9 W' `2 d- |6 W in_data[i] = *bmpBuffPtr++; } ai_input.n_batches = 1;3 }4 L6 w! R' M; p; q1 t ai_input.data = AI_HANDLE_PTR(in_data); ai_output.n_batches = 1; ai_output.data = AI_HANDLE_PTR(out_data);3 \; m( M5 m. m ~ batch = ai_lenet_run(handel, &ai_input, &ai_output); : Z" ~9 [9 @0 ]. u if (batch != 1) $ F0 h. G. ^+ S- q: X { err = ai_lenet_get_error(handel); if( err.code ) { ` C# U5 u! W0 v while(1);( D5 X2 d4 ]0 S9 S4 J }5 O' I/ s, x- O& z8 ^7 R& m. C }# v* M2 a: y* d b8 ? N5 k" M uint8_t count=0;9 s$ w3 C$ x8 R) B# w" r for(uint8_t i=0; i<AI_MNETWORK_OUT_1_SIZE; i++) { if( out_data[i] >=0.9f) {/ [9 t8 _" K+ R sprintf(str_tmp,"Num:%d",i);* s+ d" [! F7 b: ]8 f GUI_SetFont(GUI_FONT_32B_ASCII);* e* d( W9 Z3 E$ p" H& z GUI_DispStringAt(str_tmp,200,0); GUI_SetFont(GUI_FONT_16B_ASCII);9 v! e8 Z5 H& e5 s count++; } }" l0 E3 w) U% s2 B4 K4 O if(count!=1)% _' ?( t4 C1 d$ _0 c; Q { GUI_SetFont(GUI_FONT_32B_ASCII); GUI_DispStringAt("err",200,0);: G! E) k8 |! T# ^ GUI_SetFont(GUI_FONT_16B_ASCII); }8 }; O5 t* i% f- l free(bmpBuffPtr);5 H x. ^1 N/ o# D& D HAL_Delay(2000); } % f5 l( ]6 ~3 u 熟悉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的主要函数。# Q# f9 {. A" W( c+ R. s ai_lenet_create(&handel, NULL); ai_lenet_get_info(handel, &report); ai_network_params params = { AI_LENET_DATA_WEIGHTS(ai_lenet_data_weights_get()), //权重的获取$ S& N" T5 X! P; ?9 D/ S! ^% q AI_LENET_DATA_ACTIVATIONS(activations) // 激活函数0 k1 q) D3 R& s# F }; ai_lenet_init(handel, ¶ms); //lenet的初始化,估计是申请内存什么的,写flash。0 e- _# u8 K! Z2 y. g: s* D err = ai_lenet_get_error(handel); a4 u2 s& I) d# c& w! \9 w& v $ x$ n! y7 E( |" U; _, ] batch = ai_lenet_run(handel, &ai_input, &ai_output); //图片输入以及处理完毕的输出,1batch批 1 t5 c2 D& \! b: [: g- g' b% m " q1 A, a: r; ~4 R- s# Y 总的来说比较简单的demo,其实也可以做复杂一点,先手写然后STemwin存bmp图片,然后利用加权平均得到BMP颜色数据的灰度,输入到lenet,dedaojieguo。效果会比较酷炫。' z) ?* }% ?- i; V; f7 y) B5 D3 m 这模型被压缩很厉害,能有这样的结果以及不错了,最后祝贺一下ST,半导体前15! 期待MP1,玩玩不用压缩的AI。' b7 x4 E$ Z- l C5 A! |/ T) a+ Y 附件:工程源码。5 B) d1 `, G, w0 I- k |
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板子功耗测试】
微信公众号
手机版
谢谢支持