Funpack3-4 FRDM-MCX N947 鞋帽图像分类
该项目使用了FRDM-MCXN947,实现了鞋帽图像分类的设计,它的主要功能为:使用串口中断接受图片二进制文件,并调用NPU加速完成鞋帽图像分类任务。
标签
Funpack活动
机器学习
FunPack3-4
MCX N94
图像分类
TetraPak
更新2024-09-09
106

项目背景

很高兴参加funpack第三季第四期的活动,本次活动的开发板是来自恩智浦的FRDM-MCXN947。

功能介绍

任务描述

  • 使用调试器的串口向MCU直接发送图像
  • 使用eIQ 实现图像分类(帽子或鞋子)

硬件介绍

开发板具备丰富硬件连接性和拓展性,包括Arduino®、FlexIO/LCD、SmartDMA摄像头、Pmod™、mikroBUS™、Micro SD卡插槽、以太网、HS USB Type-C、SPI/I2C/UART、WIFI及CAN-FD收发器等多种接口。

开发板配备的MCX N947是一款高性能、低功耗微控制器,配备两个Arm Cortex-M33内核和一个神经处理单元(即NPU),运行频率可达150MHz。它提供2MB闪存和可配置的带ECC的RAM,并集成DSP协处理器和eIQ Neutron NPU。与单独的CPU内核相比,NPU能提升高达42倍的机器学习吞吐量,从而减少系统唤醒时间并降低整体功耗。该MCU适用于安全、智能的电机控制和机器学习应用。MCX N947还包括多种智能外设和加速器,如PowerQUAD DSP加速器、SmartDMA协处理器、eIQ Neutron N1-16神经处理单元、以及高达2MB片上闪存和512KB RAM。它支持多种通信接口,包括USB高速/全速接口、Micro SD高速卡接口、多个SPI、I2C、UART接口、以太网接口等。此外,它还具备强大的模拟和定时器功能,适合多样化应用需求。

设计思路

主要困难

从任务描述中可以看出,实现该任务有三个核心功能:

  1. 建立模型:使用公开数据集训练模型
  2. 接收图片数据:用串口中断接收二进制图片RGB数据
  3. 输出识别结果:接收一次图片后,调用模型开始识别,将识别结果通过串口发送出去

解决思路

核心功能一

需要找到一个包含帽子和鞋子图片的公开数据集,并使用该数据集训练一个图像分类模型。数据集是从网上公开数据集中获取的。然后使用eIQ Portal这个软件构建图像分类模型。eIQ Portal集成加载数据集,训练,评估,优化,部署等功能,可极大简化机器学习模型的开发。选择用mobilenet v1架构作为基础模型架构,在此基础上完成鞋帽分类模型的训练,训练完成后对模型进行评估,导出,最后要转换模型架构为tensorflow lite。

训练集:测试集为250:50。

核心功能二

为了让MCU能够接收图像数据,通过调试器的串口发送二进制形式的RGB图像数据。

通过图像取模软件将图片转换为二进制文件,MCU需要设置串口中断来处理接收数据,并将接收到的数据存储到适当的缓存中,确保数据的完整性和正确性。

核心功能三

当MCU接收到完整的图像数据后,会调用之前训练好的模型对图像进行分类,判断图像中是帽子还是鞋子。识别完成后,将分类结果通过串口发送回调试器,以便进一步处理或显示。

软件流程图

功能展示

核心代码片段及说明

加载模型,model-data.s

npu_model_data:
.incbin "../source/model/mobilenet_v1-2024-07-09T03-18-05.169Z_in-int8_out-int8_channel_ptq_converted.tflite"
npu_model_data_end:


调用训练好的模型,识别图片,cifar10_recognize.cpp

extern uint32_t g_label_num;
extern uint32_t g_detedted_flag;
extern uint8_t gImage[49152];
extern volatile uint16_t txIndex; /* Index of the data to send out. */
extern volatile uint16_t rxIndex; /* Index of the memory to save new arrived data. */
extern volatile uint8_t end_flag;

void cifar10_recognize()
{
tensor_dims_t inputDims;
tensor_type_t inputType;
uint8_t* inputData;

tensor_dims_t outputDims;
tensor_type_t outputType;
uint8_t* outputData;
size_t arenaSize;

if (MODEL_Init() != kStatus_Success)
{
PRINTF("Failed initializing model");
for (;;) {}
}

size_t usedSize = MODEL_GetArenaUsedBytes(&arenaSize);
PRINTF("\r\n%d/%d kB (%0.2f%%) tensor arena used\r\n", usedSize / 1024, arenaSize / 1024, 100.0*usedSize/arenaSize);

inputData = MODEL_GetInputTensorData(&inputDims, &inputType);
outputData = MODEL_GetOutputTensorData(&outputDims, &outputType);

while(1)
{
if (rxIndex >= 49100 && rxIndex <= 49152)
{
PRINTF("__end_flag = %d, rxIndex = %d\r\n", end_flag, rxIndex);
}
if (end_flag == 0 || !(kLPUART_TxDataRegEmptyFlag & LPUART_GetStatusFlags(LPUART4)))
continue;
memcpy(model_input_buf, gImage, 49152);
PRINTF("end_flag, rxIndex = %d\r\n", rxIndex);
rxIndex = 0;
end_flag = 0;

uint8_t *buf = 0;

memset(inputData,0,inputDims.data[1]*inputDims.data[2]*inputDims.data[3]);
buf = inputData + (inputData,inputDims.data[1] - MODEL_IN_H) /2 * MODEL_IN_W * MODEL_IN_C;
memcpy(buf, model_input_buf, MODEL_IN_W*MODEL_IN_H*MODEL_IN_C);

auto startTime = TIMER_GetTimeInUS();
MODEL_RunInference();
auto endTime = TIMER_GetTimeInUS();

auto dt = endTime - startTime;
s_infUs = (uint32_t)dt;

MODEL_ProcessOutput(outputData, &outputDims, outputType, dt);
if(g_detedted_flag)
{
char str_buf[96] = {0x0};
sprintf(str_buf,"Label: %s\r\n",labels[g_label_num]);
PRINTF(str_buf);
}
memset(gImage, 0, sizeof(gImage));
}
}


开启串口中断,中断函数中接收图片二进制文件,main.c

#define DEMO_LPUART            LPUART4
#define DEMO_LPUART_CLK_FREQ CLOCK_GetLPFlexCommClkFreq(4u)
#define DEMO_LPUART_IRQn LP_FLEXCOMM4_IRQn
#define DEMO_LPUART_IRQHandler LP_FLEXCOMM4_IRQHandler

#define DEMO_RING_BUFFER_SIZE 49152

uint8_t gImage[DEMO_RING_BUFFER_SIZE] = {0};
volatile uint16_t txIndex; /* Index of the data to send out. */
volatile uint16_t rxIndex; /* Index of the memory to save new arrived data. */

/*******************************************************************************
* Code
******************************************************************************/

void DEMO_LPUART_IRQHandler(void)
{
uint8_t data;
uint16_t tmprxIndex = rxIndex;

/* If new data arrived. */
if ((kLPUART_RxDataRegFullFlag)&LPUART_GetStatusFlags(DEMO_LPUART))
{
data = LPUART_ReadByte(DEMO_LPUART);

if (tmprxIndex < DEMO_RING_BUFFER_SIZE)
{
gImage[rxIndex] = data;
rxIndex++;
}
if (rxIndex >= DEMO_RING_BUFFER_SIZE)
{
end_flag = 1;
}

}
SDK_ISR_EXIT_BARRIER;
}


int main(void)
{
BOARD_Init();
TIMER_Init();

lpuart_config_t config;
LPUART_GetDefaultConfig(&config);
config.baudRate_Bps = BOARD_DEBUG_UART_BAUDRATE;
config.enableTx = true;
config.enableRx = true;
LPUART_Init(DEMO_LPUART, &config, DEMO_LPUART_CLK_FREQ);

/* Enable RX interrupt. */
LPUART_EnableInterrupts(DEMO_LPUART, kLPUART_RxDataRegFullInterruptEnable);
EnableIRQ(DEMO_LPUART_IRQn);

cifar10_recognize();

while(1)
{
}
}

实现效果

训练模型

评估模型

导出模型

具体演示效果请观看演示视频

总结

本项目依托FRDM-MCX N947平台,完成鞋帽图像分类任务。在此过程中阅读传感器数据手册和平台驱动代码,分别训练分类模型和编写MCU端的驱动代码,完成串口通信、模型调用、分类结果输出,最终顺利完成任务。

附件下载
funpack-mcxn947.zip
MCUXpressoIDE工程文件
image_test.zip
本项目用到的测试图片
团队介绍
团队成员
TetraPak
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号