|
写的教程反响平平,可能是晦涩难懂,那就直接上代码(极度粗糙的demo)。# q+ M3 v& u3 z2 m; g& E 接上次的软硬件环境,我采用的STemwin(本来想用littlevgl)自带bmp显示(详细代码可参考某某莱教程)。先看看生成的一些代码。2 S O$ |. c; u& d ' `5 t( @4 t0 Q. r& R GUI_Init();$ p; _$ v y w. g9 {! G GUI_SetBkColor(GUI_BLUE_98); GUI_Clear(); 5 Q6 _' N/ R5 F) o& m GUI_DispStringHCenterAt( GUI_GetVersionString() , GUI_GetScreenSizeX()/2, GUI_GetScreenSizeY()/2);% q/ ?8 L/ y& @ s5 k' M SDRes=f_mount(&SDFatFS,(TCHAR*)SDPath,0);5 Q* G4 y; e5 L- g. z; |& p. _ if(SDRes!=FR_OK) { Error_Handler(); }. Y& ]5 E6 K9 A5 b6 p MX_X_CUBE_AI_Process();) M8 b6 x* S8 c1 T- [4 e1 U/ U /* USER CODE END 2 */ /* Infinite loop */: G/ x- N/ M6 I /* USER CODE BEGIN WHILE */ while (1)5 b x! X. `: G: ], r {+ G! H4 j! @/ z. R Q9 O /* USER CODE END WHILE */ GUI_Delay(10);2 H' j0 I: G# K z /* USER CODE BEGIN 3 */ } x* o7 j$ j \! Q 简单的主函数。6 `* a+ j5 `% l O% { 进入MX_X_CUBE_AI_Process();" A4 s2 z$ o) j3 F! h( ^. I + J- h* C+ F& }/ |0 Q# a. s ai_buffer ai_input; ai_buffer ai_output; ai_i32 batch;: u ^- Q+ |- | b0 H- q6 C char str_tmp[16];8 U' E7 `" @( X6 G7 t" t! ^' d for(uint8_t i=0; i<10; i++) {. F3 |. D6 Q" @2 | sprintf(str_tmp,"%1d.bmp",i); _ShowBMPEx(str_tmp);& F& H6 k* a* S* B9 R/ H# \ LCD_ShowBMP(str_tmp); for(uint16_t i=0; i<AI_LENET_IN_1_SIZE ; i++ ). N+ g% {" `4 [. b6 d% u {% q! H; Y7 s- X Y2 L in_data[i] = *bmpBuffPtr++; } ai_input.n_batches = 1;/ t5 x+ F4 m6 Y0 o ai_input.data = AI_HANDLE_PTR(in_data); ai_output.n_batches = 1;+ p T) K/ i, Q6 L6 G* { ai_output.data = AI_HANDLE_PTR(out_data);, e+ Y8 p; Y2 @: |% O5 \0 s batch = ai_lenet_run(handel, &ai_input, &ai_output); . [. k, M8 J' D9 }* ? if (batch != 1) ) O( o( z6 s3 L: q& N0 D3 N {' o5 ~- q( K# O& r, R err = ai_lenet_get_error(handel);3 A, B; b2 j8 N& j1 T if( err.code )6 F/ {, J4 \) n* k( z { while(1);9 y) `' m' J: ? } }7 J: o! L* H9 H( u4 @) \& v uint8_t count=0;# R5 t B2 g5 D( L t+ @, x2 Y( W for(uint8_t i=0; i<AI_MNETWORK_OUT_1_SIZE; i++) { if( out_data[i] >=0.9f) { sprintf(str_tmp,"Num:%d",i); GUI_SetFont(GUI_FONT_32B_ASCII); GUI_DispStringAt(str_tmp,200,0);9 M0 k! |9 F u GUI_SetFont(GUI_FONT_16B_ASCII); count++; }* B" N0 c+ L8 p5 H( n }% |, y* m' n$ i+ u if(count!=1)+ d! m2 \; q. K4 W3 W { GUI_SetFont(GUI_FONT_32B_ASCII); GUI_DispStringAt("err",200,0); GUI_SetFont(GUI_FONT_16B_ASCII); } free(bmpBuffPtr); HAL_Delay(2000); }5 Y* B2 x# C. o, b& H* C+ W: n 0 ~ y1 W7 c* C& f 熟悉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的主要函数。 ai_lenet_create(&handel, NULL);7 u7 M' y7 ]* z3 E3 o ai_lenet_get_info(handel, &report);1 x( V% r7 b! ]( X( M# L ai_network_params params = { AI_LENET_DATA_WEIGHTS(ai_lenet_data_weights_get()), //权重的获取 AI_LENET_DATA_ACTIVATIONS(activations) // 激活函数 }; ai_lenet_init(handel, ¶ms); //lenet的初始化,估计是申请内存什么的,写flash。# ^) z! O6 I0 t* P err = ai_lenet_get_error(handel); batch = ai_lenet_run(handel, &ai_input, &ai_output); //图片输入以及处理完毕的输出,1batch批2 H. V1 y: C* f9 ~1 X& H0 v / M e% \& R/ {) R" H 总的来说比较简单的demo,其实也可以做复杂一点,先手写然后STemwin存bmp图片,然后利用加权平均得到BMP颜色数据的灰度,输入到lenet,dedaojieguo。效果会比较酷炫。, [0 K; ]) r1 f- T! S 这模型被压缩很厉害,能有这样的结果以及不错了,最后祝贺一下ST,半导体前15! 期待MP1,玩玩不用压缩的AI。 |% ~( A- R8 i! K 附件:工程源码。3 w) C( D, J+ M. p* T. S8 L ) M' a+ n N- K5 }) } ( G0 y! n5 J! n. z( N4 H( b |
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板子功耗测试】
微信公众号
手机版
谢谢支持