回答

收藏

【瑞萨AI挑战赛】NPU 加速人脸检测

#板卡评测 #板卡评测 29 人阅读 | 0 人回复 | 2026-03-16

感谢瑞萨电子的活动,很开心能申请到开发板试用!

1 系统架构和组织
运行在 RT-Thread系统上的NPU 加速人脸检测程序,核心功能是:通过摄像头采集 RGB565格式的图像,将图像预处理后送入 NPU(神经网络处理器)运行 YOLO 类检测模型,对检测结果解码和非极大值抑制(NMS)后,在 LCD 屏幕上绘制摄像头画面和检测到的人脸框,并通过 LED 灯的闪烁反馈程序运行状态。
依次实现
采集图像 → 预处理 → 模型推理 → 输出反量化 → 解码检测框 → NMS 去重→ LCD 绘制 → 状态反馈
安装这个过程,的代码组织树如下,其中yolo已经量化为模型,并导入到工程中了。

2编译和下载
代码如下
核心代码直接跳转到RTOS的控制循环

  1. #include "hal_data.h"
  2.             int main(void) {
  3.               hal_entry();
  4.               return 0;
  5.             }
  6. 核心代码如下
  7. #include <rtthread.h>
  8. #include "hal_data.h"
  9. #include <rtdevice.h>

  10. #include <board.h>
  11. #include "sensor.h"
  12. #include <lcd_port.h>
  13. #include "model.h"
  14. #include "pmu_ethosu.h"
  15. #include "yolo_rtthread.h"

  16. #define DBG_TAG     "main"
  17. #define DBG_LVL     DBG_INFO
  18. #include "rtdbg.h"

  19. #define LED_PIN     BSP_IO_PORT_00_PIN_12

  20. #define CAM_WIDTH   640
  21. #define CAM_HEIGHT  480

  22. static volatile bool led_status = false;

  23. extern sensor_t sensor;
  24. static uint8_t g_image_rgb565_sdram_buffer[CAM_WIDTH * CAM_HEIGHT * 2] BSP_PLACE_IN_SECTION(".ospi1_cs0_noinit") BSP_ALIGN_VARIABLE(8);


  25. static void lcd_draw_jpg_with_frame(int32_t x, int32_t y,
  26.                              const void *p, int32_t xSize, int32_t ySize,
  27.                              uint32_t argb, d2_width thickness, det_box_t *boxes, int32_t box_num)
  28. {
  29.     if (thickness < 1) thickness = 1;

  30.     uint32_t ModeSrc = d2_mode_rgb565;
  31.     d2_device *hdl = d2_handle_obj_get();

  32.     // 设定帧缓冲(背景/目标)
  33.     d2_framebuffer(hdl, (uint16_t *)&fb_background[0],
  34.                    LCD_WIDTH, LCD_WIDTH, LCD_HEIGHT, ModeSrc);

  35.     // 选择渲染缓冲并设置裁剪区域(全屏)
  36.     d2_selectrenderbuffer(hdl, d2_renderbuffer_get());
  37.     d2_cliprect(hdl, 0, 0, LCD_WIDTH, LCD_HEIGHT);

  38.     // 设定源图并把整帧图像 Blit 到屏幕
  39.     d2_setblitsrc(hdl, (void *)p, xSize, xSize, ySize, ModeSrc);
  40.     d2_blitcopy(hdl, xSize, ySize, 0, 0,
  41.             D2_FIX(LCD_WIDTH), D2_FIX(LCD_HEIGHT),
  42.                 D2_FIX(x), D2_FIX(y), 0);

  43.     // 颜色
  44.     d2_setcolor(hdl, 0, argb);
  45.     //
  46.     d2_width drwa_thickness = D2_FIX(thickness);
  47.     d2_u32 flags = d2_le_exclude_none;

  48.     for(int i=0;i<box_num;i++){
  49.         d2_point x1 = D2_FIX(boxes->x1);
  50.         d2_point y1 = D2_FIX(boxes->y1);
  51.         d2_point x2 = D2_FIX(boxes->x2);
  52.         d2_point y2 = D2_FIX(boxes->y2);

  53.         d2_renderline(hdl, x1, y1, x2, y1, drwa_thickness, flags);
  54.         d2_renderline(hdl, x1, y1, x1, y2, drwa_thickness, flags);
  55.         d2_renderline(hdl, x2, y1, x2, y2, drwa_thickness, flags);
  56.         d2_renderline(hdl, x1, y2, x2, y2, drwa_thickness, flags);
  57.     }

  58.     d2_executerenderbuffer(hdl, d2_renderbuffer_get(), 0);
  59.     d2_flushframe(hdl);
  60. }

  61. void hal_entry(void)
  62. {
  63.     LOG_I("========================================================================");
  64.     LOG_I("This example project is an an npu accelerated ai face detection routine!");
  65.     LOG_I("========================================================================");

  66.     sensor_init();
  67.     sensor_reset();
  68.     sensor_set_pixformat(PIXFORMAT_RGB565);
  69.     sensor_set_framesize(FRAMESIZE_VGA);

  70.     // 使能 NPU PMU
  71.     int16_t status = FSP_SUCCESS;
  72.     status = RM_ETHOSU_Open(&g_rm_ethosu0_ctrl, &g_rm_ethosu0_cfg);
  73.     if (status != FSP_SUCCESS)
  74.     {
  75.         LOG_E("Failed to start NPU");
  76.         return;
  77.     }

  78.     int8_t *in_i8 = (int8_t *)rt_malloc(INPUT_W * INPUT_H * sizeof(int8_t));

  79.     if (!in_i8)
  80.     {
  81.         LOG_E("malloc in_i8 failed!");
  82.         return;
  83.     }

  84.     float *out_f1 = (float *)rt_malloc(output1_len * sizeof(float));
  85.     float *out_f2 = (float *)rt_malloc(output2_len * sizeof(float));

  86.     while(1)
  87.     {
  88.         rt_tick_t start = rt_tick_get();

  89.         //rt_hw_us_delay(1000);

  90.         sensor_snapshot(&sensor, g_image_rgb565_sdram_buffer, 0);

  91.         rgb565_to_gray_resize_192_and_quantization(g_image_rgb565_sdram_buffer, CAM_WIDTH, CAM_HEIGHT, in_i8);

  92.         memcpy(GetModelInputPtr_serving_default_image_input_0(), in_i8, INPUT_SIZE);

  93.         RunModel(false);

  94.         int8_t* output1 = GetModelOutputPtr_StatefulPartitionedCall_0_70273(); // 6
  95.         int8_t* output2 = GetModelOutputPtr_StatefulPartitionedCall_1_70283(); // 12

  96.         dequantize_int8(output1, out_f1, output1_len, scale_out1, zero_point_out1);
  97.         dequantize_int8(output2, out_f2, output2_len, scale_out2, zero_point_out2);

  98.         int16_t total = 0;
  99.         static det_box_t pool[540]; // 6*6*3 + 12*12*3 = 108 + 432 = 540

  100.         total += decode_output_layer(out_f1, GRID_SIZE_1, 0, LCD_WIDTH, LCD_HEIGHT, CONF_THRESH,
  101.                 pool + total, (int16_t)(sizeof(pool)/sizeof(pool[0])) - total);

  102.         total += decode_output_layer(out_f2, GRID_SIZE_2, 1, LCD_WIDTH, LCD_HEIGHT, CONF_THRESH,
  103.                 pool + total, (int16_t)(sizeof(pool)/sizeof(pool[0])) - total);
  104.         // nms
  105.         int32_t kept = nms_filter(pool, total, NMS_THRESH);
  106.         int32_t out_n = MIN(kept, MAX_BOXES); // 拷贝前 kept(不超过 MAX_BOXES)

  107.         d2_width thickness = 1;
  108.         uint32_t argb = 0xFF00FF00;
  109.         lcd_draw_jpg_with_frame(0, 0, g_image_rgb565_sdram_buffer, CAM_WIDTH, CAM_HEIGHT, argb, thickness, pool, out_n);

  110.         rt_tick_t end = rt_tick_get();
  111.         rt_kprintf("detect box num: %d\n", out_n);
  112.         rt_kprintf("Time elapsed: %d ms\n", (end - start) * (1000 / RT_TICK_PER_SECOND));

  113.         rt_thread_mdelay(5);

  114.         led_status = !led_status;
  115.         if(led_status)
  116.         {
  117.             rt_pin_write(LED_PIN, PIN_HIGH);
  118.         }
  119.         else
  120.         {
  121.             rt_pin_write(LED_PIN, PIN_LOW);
  122.         }
  123.     }
  124. }
复制代码
编译通过
下载成功
运行启动顺利,
这个过程还是比较顺利的。这样体会了瑞萨的AI识别功能,看起来还是比较顺畅的。




分享到:
回复

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /2 下一条