[STM32N6] 【STM32N6570-DK测评】4、AI+H264+USB摄像头综合应用

[复制链接]
 楼主| sujingliang 发表于 2025-5-3 21:40 | 显示全部楼层 |阅读模式
<
本帖最后由 sujingliang 于 2025-5-3 21:46 编辑

en.n6-ai-h264-usb-uvc例程在STM32N6570-DK板上部署对象检测模型,并使用UVC/H264格式通过USB传输结果到计算机,通过视频查看软件观察结果。

示例中演示的功能
-多线程应用程序流(Azure RTOS ThreadX)
-NPU加速量化AI模型推理
-双DCMIP管道
-DCMIP裁剪、抽取、缩小规模
-DCMIP ISP使用情况
-H264编码器
-USB UVC(Azure RTOS USBX)
-开发模式
-从外部闪存启动

部署en.n6-ai-h264-usb-uvc例程后,STM32N6570-DK通过USB连接PC机,会被识别为了USB摄像头:
23.png
此时,使用类似PotPlayer 64 bit的工具可以将USB摄像头拍摄的内容显示在屏幕上:
24.png

一、多线程
22.png
  1. int main(void)
  2. {
  3. ...
  4.   return main_threadx();//调用主线程函数
  5. }
初始化ThreadX,调用 tx_kernel_enter() 启动内核
  1. static int main_threadx()
  2. {
  3.   _tx_initialize_kernel_setup();
  4.   tx_kernel_enter();
  5.   assert(0);

  6.   return -1;
  7. }
tx_kernel_enter() 动 ThreadX 内核后,会自动调用 tx_application_define
tx_application_define中建立主线程

  1. void tx_application_define(void *first_unused_memory)
  2. {
  3.   const UINT priority = TX_MAX_PRIORITIES - 1;
  4.   const ULONG time_slice = 10;
  5.   int ret;

  6.   ret = tx_thread_create(&main_thread, "main", main_thread_fct, 0, main_tread_stack,
  7.                          sizeof(main_tread_stack), priority, priority, time_slice, TX_AUTO_START);
  8.   assert(ret == 0);
  9. }
main_thread_fct中调用app_run();
  1. static void main_thread_fct(ULONG arg)
  2. {
  3. ...
  4.   app_run();
  5. }
app_run()中建立3个thread
  1. void app_run()
  2. {
  3. ...
  4.   /* threads init */
  5.   ret = tx_thread_create(&nn_thread, "nn", nn_thread_fct, 0, nn_tread_stack,
  6.                          sizeof(nn_tread_stack), nn_priority, nn_priority, time_slice, TX_AUTO_START);
  7.   assert(ret == TX_SUCCESS);
  8.   ret = tx_thread_create(&dp_thread, "dp", dp_thread_fct, 0, dp_tread_stack,
  9.                          sizeof(dp_tread_stack), dp_priority, dp_priority, time_slice, TX_AUTO_START);
  10.   assert(ret == TX_SUCCESS);
  11.   ret = tx_thread_create(&isp_thread, "isp", isp_thread_fct, 0, isp_tread_stack,
  12.                          sizeof(isp_tread_stack), isp_priority, isp_priority, time_slice, TX_AUTO_START);
  13.   assert(ret == TX_SUCCESS);
  14. }
到此,线程初始化基本完成。

二、修改显示内容
  1. static void build_display(uint8_t *p_buffer, od_pp_out_t *pp_out)
  2. {
  3.   const uint8_t *fig_array[] = {fig0, fig1, fig2, fig3, fig4, fig5, fig6, fig7, fig8, fig9};
  4.   const uint8_t *nz_array[] ={gImage_nz1,gImage_nz2};
  5.   int line_nb = VENC_HEIGHT / INF_INFO_FONT.height - 4;
  6.   stat_info_t si_copy;
  7.   int nb;
  8.   int i;

  9.   stat_info_copy(&si_copy);

  10.   for (i = 0; i < pp_out->nb_detect; i++)
  11.     draw_box(p_buffer, &pp_out->pOutBuff[i]);

  12.   line_nb = build_display_inference_info(p_buffer, si_copy.nn_inference_time.last, line_nb);
  13.   line_nb = build_display_cpu_load(p_buffer, line_nb);

  14.   nb = MIN(pp_out->nb_detect, ARRAY_NB(fig_array) - 1);
  15.    DRAW_CopyArgbHW(p_buffer, VENC_WIDTH, VENC_HEIGHT, (uint8_t *) nz_array[nb%2], 256, 256, 16, 256);


  16.   build_display_stat_info(p_buffer, &si_copy);
  17. }
build_display可以在显示缓冲区中进行画图操作,可以将对象检测模型的结果显示在屏幕上,如:
STM32N6_AI_H264_UVC_capture.jpg

对象检测模型监测到3个人,显示每个人模型匹配比率,并在左上角显示监测到的对象为:3。
个人实践情况:
tutieshi_480x304_25s.gif

gImage_nz1、gImage_nz2改成了哪吒的表情包,图片格式为BGRA
  1. const unsigned char gImage_nz1[262144] = { /* 0X10,0X20,0X01,0X00,0X01,0X00,0X00,0XE4, */
  2. 0XFD,0XFD,0XFD,0X00,0XFD,0XFD,0XFD,0X00,0XFD,0XFD,0XFD,0X00,0XFC,0XFC,0XFC,0X00,
  3. 0XFE,0XFE,0XFE,0X00,0XFE,0XFE,0XFE,0X00,0XFE,0XFE,0XFE,0X00,0XFE,0XFE,0XFE,0X00,
修改后的界面显示:
tutieshi_480x280_14s.gif
识别到对象为奇数时,显示哪吒头像1;
识别到对象为偶数时,显示哪吒头像2;


本例程将STM32N6570-DK驱动为USB摄像头,通过摄像头拍摄的视频流结合对象检测模型,将检测结果H264格式压缩后,传递给PC显示。




Hexzuo 发表于 2025-5-19 12:25 | 显示全部楼层
大佬可以求一份代码吗,跪求
Hexzuo 发表于 2025-5-19 12:26 | 显示全部楼层
可以的话,跪谢大佬发送到s17762070039@outlook.com
Ketose 发表于 2025-7-8 15:59 | 显示全部楼层
收一块STM32N6开发板。
szt1993 发表于 2025-7-8 19:34 | 显示全部楼层
综合应用非常不错
您需要登录后才可以回帖 登录 | 注册

本版积分规则

84

主题

146

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部