基于max78000的边缘计算AI入门学习
本中期报告中,我主要介绍在拿到max78000驱动TFT屏幕,同时展示如何训练自己的模型。
标签
嵌入式系统
开发板
边缘计算
MAX78000
敏爷001
更新2024-01-12
暨南大学
366

      在本文中,我将对使用max78000进行开发做中期总结。由于本人还是机器学习的入门,因此进度较慢,选题方面还没有确定。现在主要介绍包括羽毛板驱动TFT屏幕,以及模型训练。

1.驱动2.4寸TFT显示屏

1)硬件

      该显示屏是2.4寸液晶显示屏模块,分辨率240*320。采用4线SPI通讯,内置的驱动芯片是ILI9341。

FuHFKBe9bXOtJhL2sRb1Vc7aJ3uDFlCj1RaWsLQZjjpUb2LetjidvXaHFvRDnGuBnxfYNhH8iMsAZ1tnysT1

      使用MAX78000的SPI接口连接TFT屏幕的dc、ds、mosi、miso、sck、reset引脚,同时还要给TFT模块的LED引脚提供3.3V的电源,以驱动显示屏的背光。具体的原理图如下:

FpkESo5T1MkV1uB0ftAIf8P9jx8q

原理图

将原理图转换成PCB并进行布线

FuZFoqbzVeKY3E37efo9xETJchzB

      制作PCB。制作PCB主要是考虑到TFT与MAX78000羽毛板的接线比较多,如果纯用杜邦线连接,会存在断连和接触不良的情况。制作的PCB只有75*80mm的大小,这对于调试与放置都有极大的便捷,调试时候只需用USB与电脑连接即可。

2)软件

  • 初始化
    //时钟初始化
    MXC_SYS_Clock_Select(MXC_SYS_CLOCK_IPO);// Switch to 100 MHz clock
    SystemCoreClockUpdate();
    MXC_Delay(SEC(2)); // Let debugger interrupt if needed
    //相机初始化
    MXC_DMA_Init();// 为摄像机接口初始化DMA
    dma_channel = MXC_DMA_AcquireChannel();
    camera_init(CAMERA_FREQ);   //相机初始化
    ret = camera_setup(IMG_SIZE_X, IMG_SIZE_Y, PIXFORMAT_RGB888, FIFO_THREE_BYTE, USE_DMA, dma_channel);//相机设置
    if (ret != STATUS_OK) {
        printf("Error returned from setting up camera. Error %d\n", ret);
        return -1;
    }
    //TFT初始化
    MXC_TFT_Init(MXC_SPI0, 1, NULL, NULL);
    MXC_TFT_SetRotation(ROTATE_270);
    MXC_TFT_SetForeGroundColor(WHITE); // set chars to white
    MXC_TFT_ClearScreen();
    MXC_TFT_SetBackGroundColor(GREEN);
  • 屏幕显示字符串函数
void TFT_Print(int x, int y, char *str, int length)//TFT打印字符串 提供字符串、坐标、长度
{
    int font = (int)&Arial12x12[0];
    text_t text;
    text.data = str;
    text.len = length;
    MXC_TFT_PrintFont(x, y, font, &text, NULL);
}
  • 采集一帧图片并在TFT上显示
void load_input(void)  //摄像头采集图像并显示
{
    uint8_t *frame_buffer;
    uint8_t *buffer;
    uint32_t imgLen;
    uint32_t w, h, x, y;
    uint8_t r, g, b;
    uint32_t color;
    char buff1[TFT_BUFF_SIZE];//字符串
    uint8_t image[IMG_SIZE_X * TFT_SCALE][IMG_SIZE_Y * TFT_SCALE][2];  //定义图像数据

    camera_start_capture_image();  //捕捉图像
    while (!camera_is_image_rcv()) {} //判断图像采集是否成功
    camera_get_image(&frame_buffer, &imgLen, &w, &h); //获取一帧缓冲区的图像数据、长度、宽和高
    buffer = frame_buffer;

    TFT_Print1(5, 210, buff1, snprintf(buff1, sizeof(buff1), "h:%d, w:%d\n,imgLen:%d",h,w,imgLen));//snprintf的返回值是字符串的长度
    for (y = 0; y < h; y++) {  //像素转换
        for (x = 0; x < w; x++) {
            r = *buffer++;
            g = *buffer++;
            b = *buffer++;
            buffer++; // skip msb=0x00
            // display on TFT
            // Convert to RGB565
            color = ((r & 0b11111000) << 8) | ((g & 0b11111100) << 3) | (b >> 3);
            for (uint8_t i = 0; i < TFT_SCALE; i++) {
                for (uint8_t j = 0; j < TFT_SCALE; j++) {
                    image[x*TFT_SCALE+i][y*TFT_SCALE+j][0] = color >> 8;
                    image[x*TFT_SCALE+i][y*TFT_SCALE+j][1] = color & 0xff;
                }
            }
        }
    }
    MXC_TFT_ShowImageCameraRGB565(TFT_OFFSET_X, TFT_OFFSET_Y, (uint8_t *)image, IMG_SIZE_X * TFT_SCALE, IMG_SIZE_Y * TFT_SCALE);
}

 

3) 显示效果

FrRbPwlNi5mArJHETj1W1IMyrbEM

    可以看到可以成功驱动屏幕,并且能将摄像头采集的图像显示在TFT上(上图中TFT显示的画面是视频)。

2.模型训练

    由于我对机器学习处于入门阶段,因此我针对性的学习了pytorch。使用已经有的CIFAR10数据集,搭建卷积神经网络进行GPU的训练。CIFAR10是30*30的10类别数据集,分别是

0: "airplane",
1: "automobile",
2: "bird",
3: "cat",
4: "deer",
5: "dog",
6: "frog",
7: "horse",
8: "ship",
9: "truck"

1)模型搭建

搭建一个3层神经网络。

# 创建网络模型
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.model = nn.Sequential(
            nn.Conv2d(3, 32, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 32, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 64, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Flatten(),
            nn.Linear(64*4*4, 64),
            nn.Linear(64, 10)
        )

    def forward(self, x):
        x = self.model(x)
        return x

2)模型训练

 # 训练步骤开始
    tudui.train()
    for data in train_dataloader:
        imgs, targets = data
        if torch.cuda.is_available():
            imgs = imgs.cuda()
            targets = targets.cuda()
        outputs = tudui(imgs)
        loss = loss_fn(outputs, targets)

        # 优化器优化模型
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        total_train_step = total_train_step + 1
        if total_train_step % 100 == 0:
            end_time = time.time()
            print(end_time - start_time)
            start_time = time.time()
            print("训练次数:{}, Loss: {}".format(total_train_step, loss.item()))
            writer.add_scalar("train_loss", loss.item(), total_train_step)

3)使用opencv采集图像识别

    在下面的代码中,采用opencv读取摄像头的图像,并且使用训练好的模型进行识别。

import torch
import torchvision
import cv2
from torch import nn

#transform = torchvision.transforms.Compose([torchvision.transforms.Resize((32, 32)),
                                            # torchvision.transforms.ToTensor()])  #转换格式32*32的tensor
# 定义一个字典,将索引映射到类别标签
class_mapping = {
    0: "airplane",
    1: "automobile",
    2: "bird",
    3: "cat",
    4: "deer",
    5: "dog",
    6: "frog",
    7: "horse",
    8: "ship",
    9: "truck"
}
# 打开摄像头
cap = cv2.VideoCapture(0)  # 0表示默认摄像头
# 检查摄像头是否成功打开
if not cap.isOpened():
    print("无法打开摄像头")
    exit()
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.model = nn.Sequential(
            nn.Conv2d(3, 32, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 32, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 64, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Flatten(),
            nn.Linear(64*4*4, 64),
            nn.Linear(64, 10)
        )
    def forward(self, x):
        x = self.model(x)
        return x

# 加载模型
model = torch.load("tudui_99.pth", map_location=torch.device('cpu'))
model.eval()
while True:
    # 逐帧捕获图像
    ret, frame = cap.read()
    if not ret:
        print("无法获取图像帧")
        break
    # 缩放图像至 [32, 32]
    image = cv2.resize(frame, (32, 32))
    # 将图像从 BGR 格式转换为 RGB 格式
    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    # 使用 torchvision.transforms.ToTensor() 转换为 PyTorch 张量
    transform = torchvision.transforms.ToTensor()
    image_tensor = transform(image)
    # 添加批量维度 [1, 3, 32, 32]
    image = torch.reshape(image_tensor, (1, 3, 32, 32))  # [1,3,32,32]
    # 进行推理
    with torch.no_grad():
        output = model(image)
    # 获取分类结果
    predicted_class = output.argmax(1).item()
    class_label = class_mapping.get(predicted_class)
    print("预测类别: {}, 是: {}".format(predicted_class, class_label))
    # 在图像上显示结果(可选)
    cv2.putText(frame, "Predicted Class: {}, is: {}".format(predicted_class, class_label), (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
    cv2.imshow('Camera', frame)
    # 按'q'键退出循环
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
# 释放摄像头资源
cap.release()
# 关闭所有窗口
cv2.destroyAllWindows()

4)识别效果

      

FgTtB0_S6G1N0rrOt8xYSBBo4rItFqYzzE3Y2__vbUNr1-jnDAI3EhWd

FvscgFFhjudX-T3i5VMMqiyQ7rYMFggS1uX9syfktgvTacaTRPtf0RJNFrEnpSfLoUryq0_PuQBv8qrBts4gFhZjcfuGNLJJFWxMhf8dP7UysQaF

      可以看到,在识别的10个项目中,可以准确识别出图像里的内容。

3.未来计划

    在接下来,根据选题的要求,搭建对应的图像处理的模型,同时搜集相应的数据集,训练好模型。接着就是将模型转换成MAX78000能执行的代码写入到单片机中。如果有其他硬件的加入,还设计对应的电路和PCB。并且完善项目的整体设计。

团队介绍
个人玩家
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号