本帖最后由 酒酿大丸子 于 2024-3-10 12:55 编辑

【简介】
本文实现了一个通过摄像头采集图像,然后显示图像到屏幕上,运行TensorFlow Lite运算引擎,实现cafar10的神经网络模型。


【演示视频】



TensorFlow简介
TensorFlow 是一个端到端开源机器学习平台。它拥有一个全面而灵活的生态系统,其中包含各种工具、库和社区资源,可助力研究人员推动先进机器学习技术的发展,并使开发者能够轻松地构建和部署由机器学习提供支持的应用。
TensorFlow 是数据科学家、软件开发者和教育工作者主要使用的开源平台,用于使用数据流图形进行机器学习。图像中的节点代表数学运算,而图像边缘则代表节点间流动的多维数据阵列(张量)。这种灵活的架构允许将机器学习算法描述为相关运算的图形。可以在便携式设备、台式电脑和高端服务器等众多不同平台的 GPU、CPU 和 TPU 上训练和执行这些代码,而无需重写代码。这意味着各种背景的编程人员均可以使用相同的工具集进行协作,从而显著提高效率。该系统最初由 Google Brain 团队开发,用于研究机器学习和深度神经网络 (DNN),其通用性同样适用于其他各种领域。


【cafar10简介
CIFAR-10 和 CIFAR-100 是 8000 万张微小图像数据集的标记子集。它们由 Alex Krizhevsky、Vinod Nair 和 Geoffrey Hinton 收集。
CIFAR-10 数据集由 10 个类的 60000 张 32x32 彩色图像组成,每类 6000 张图像。有 50000 张训练图像和 10000 张测试图像。
数据集分为5个训练批次和1个测试批次,每个批次有10000张图像。测试批次正好包含从每个类中随机选择的 1000 张图像。训练批次以随机顺序包含剩余的图像,但某些训练批次可能包含来自一个类的图像多于另一个类的图像。在它们之间,训练批次正好包含来自每个类的 5000 张图像。
以下是数据集中的类,以及每个类的 10 个随机图像:
微信截图_20240310115848.png
这些类是完全互斥的。汽车和卡车之间没有重叠。“汽车”包括轿车、SUV 之类的东西。“卡车”仅包括大型卡车。两者都不包括皮卡车。


【显示功能实现】
GD为我们提供了很多例子,我们可以直接在提供的例子上进行修改就能得到期望的结果。
显示部分没啥好说的,主要注意一下显存地址就可以了。

初始化参考,这里我只使用了TLI的层0。
void app_lcd_init(void)
  • {
  •     /* LCD configure and TLI enable */
  •     lcd_config();
  •     tli_layer_enable(LAYER0);
  • //    tli_layer_enable(LAYER1);
  •     tli_reload_config(TLI_REQUEST_RELOAD_EN);
  •     tli_enable();
  • }
  • 复制代码


    【摄像头功能实现】
    同使用GD的例子就行

    初始化参考
    void app_ov2640_init(void)
  • {
  •     ov2640_id_struct ov2640id;
  •    
  •     nvic_irq_enable(DMA1_Channel7_IRQn, 0U, 1U);
  •    
  •     /* camera initialization */
  •     dci_ov2640_init();
  •     dci_ov2640_id_read(&ov2640id);

  •     /* DMA interrupt and channel enable */
  •     dma_interrupt_enable(DMA1, DMA_CH7, DMA_CHXCTL_FTFIE);
  •     dma_channel_enable(DMA1, DMA_CH7);
  •     /* DCI enable */
  •     dci_enable();
  •     dci_capture_enable();
  •     delay_1ms(100);
  • }
  • 复制代码


    【TensorFlow移植】
    因为TensorFlow代码非常多,编译一次需要很久,我们可以使用生成lib库的方式减少编译时间。
    工程结构
    微信截图_20240310121753.png

    注意要选择生成lib库
    微信截图_20240310121816.png

    这样我们只需在最终工程里面加入lib库就可以了
    微信截图_20240310122013.png

    适配log接口,这里我在工程里面实现了printf,所以使用printf打印就行。
    #include "tensorflow/lite/micro/debug_log.h"

  • #ifndef TF_LITE_STRIP_ERROR_STRINGS
  • extern "C" {
  • #include "app_init.h"
  • }
  • #endif

  • extern "C" void DebugLog(const char* s) {
  • #ifndef TF_LITE_STRIP_ERROR_STRINGS
  •   // Reusing TF_LITE_STRIP_ERROR_STRINGS to disable DebugLog completely to get
  •   // maximum reduction in binary size. This is because we have DebugLog calls
  •   // via TF_LITE_CHECK that are not stubbed out by TF_LITE_REPORT_ERROR.
  •   printf("%s", s);
  • #endif
  • }
  • 复制代码


    cafar10识别实现】
    首先是要确定模型的输入和输出,本次我们实现的是cafar10模型,使用模型的输入就是32x32的RGB888的图像。
    摄像头采集到的图像是240x272的RGB565,所以要先进行一个转换。
    void Rgb565StridedToRgb888(const uint8_t* pIn, uint8_t* p888) {
  • uint8_t* pSrc = (uint8_t*)pIn;
  • uint8_t* p888out = p888;
  •      
  •     unsigned char R,G,B;  
  •     uint32_t i =0;
  •     for(i=0;i<32*32;i++)
  •     {
  •         B=(*pSrc) & 0x1F;//000BBBBB  
  •         G=((*(pSrc+1) << 3 ) & 0x38) + ((*(pSrc) >> 5 ) & 0x07) ;//得到00GGGGGG  
  •         R=(*(pSrc+1) >> 3 ) & 0x1F; //得到000RRRRR  
  •         *(p888out+0)=(( B * 527 + 23 ) >> 6)^0x80;
  •         *(p888out+1)=(( G * 259 + 33 ) >> 6)^0x80;
  •         *(p888out+2)=(( R * 527 + 23 ) >> 6)^0x80;
  •         pSrc += 2;
  •         p888out += 3;
  •     }
  • }
  • 复制代码

    初始化模型,并运行
       if (MODEL_Init() != 0)
  •     {
  •         printf("Failed initializing model\r\n");
  •         for (;;) {}
  •     }
  •     uint8_t* inputData = MODEL_GetInputTensorData(&inputDims, &inputType);
  •     uint8_t* outputData = MODEL_GetOutputTensorData(&outputDims, &outputType);
  •     printf("init OK %d.%d.%d\r\n",inputDims.data[2], inputDims.data[1], inputDims.data[3]);
  •      
  •     while (1)
  •     {
  •         if(ov_img_flag == 1)
  •         {
  •             uint8_t *buf = 0;
  •             buf = inputData;
  •             Rgb565StridedToRgb888((uint8_t*)IMG_RGB565_32x32_BUFF_ADDR, buf);
  •             mode_run_ms_count = 0;
  •             MODEL_RunInference();
  •             uint32_t mode_run_ms = mode_run_ms_count;
  •             MODEL_ProcessOutput(outputData, &outputDims, outputType, mode_run_ms);
  •             ov_img_flag = 0;
  •         }
  •     }
  • 复制代码



    【演示】
    空识别
    微信截图_20240310123846.png
    识别船
    微信截图_20240310123859.png
    识别狗
    微信截图_20240310123907.png
    识别猫
    微信截图_20240310123914.png
    识别车
    微信截图_20240310123928.png
    识别飞机
    微信截图_20240310123949.png
    识别鹿
    微信截图_20240310123959.png


    【后记】
    不知道为啥一些代码插入就会崩溃,所以一些代码就没有贴出来。