这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » 【MAX78000FEATHER】板卡试用——手势识别

共2条 1/1 1 跳转至

【MAX78000FEATHER】板卡试用——手势识别

助工
2025-08-05 11:25:22     打赏

完成训练后,就是在开发板上实现自己的项目了。将脚本生成的项目导入到eclipse里边。

image.png

这个生成的项目中已经完成了CNN神经网络推理的实现。现在就是需要额外将摄像头采集到的数据喂给CNN网络即可。参考例程ImgCapture。通过DMA来读取摄像头。

// rps-demo
// Created using ./ai8xize.py --verbose --log --test-dir pytorch --prefix rps-demo --checkpoint-file trained/ai85-rps82-chw.pth.tar --config-file networks/rps-chw.yaml --softmax --embedded-code --device MAX78000 --compact-data --mexpress --timer 0 --display-checkpoint --fifo

#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "mxc_device.h"
#include "mxc_sys.h"
#include "bbfc_regs.h"
#include "fcr_regs.h"
#include "icc.h"
#include "dma.h"
#include "led.h"
#include "tmr.h"
#include "pb.h"
#include "cnn.h"
#include "weights.h"
#include "sampledata.h"
#include "mxc_delay.h"
#include "camera.h"

#define TFT_ENABLE

#define IMAGE_SIZE_X  (64)
#define IMAGE_SIZE_Y  (64)
#define CAMERA_FREQ   (10 * 1000 * 1000)

#define CNN_NUM_OUTPUTS 4  // number of classes



const char classes[CNN_NUM_OUTPUTS][10] = {"Paper", "Rock", "Scissors", "Empty"};

volatile uint32_t cnn_time; // Stopwatch
uint32_t input_0_camera[1024];
uint32_t input_1_camera[1024];
uint32_t input_2_camera[1024];

void fail(void)
{
    printf("\n*** FAIL ***\n\n");
    while (1)
        ;
}

void load_input(void)
{
    int i;
    const uint32_t* in0 = input_0_camera;
    const uint32_t* in1 = input_1_camera;
    const uint32_t* in2 = input_2_camera;

    for (i = 0; i < 1024; i++)
    {
        while (((*((volatile uint32_t*)0x50000004) & 1)) != 0)
            ;                                       // Wait for FIFO 0
        *((volatile uint32_t*)0x50000008) = *in0++; // Write FIFO 0
        while (((*((volatile uint32_t*)0x50000004) & 2)) != 0)
            ;                                       // Wait for FIFO 1
        *((volatile uint32_t*)0x5000000c) = *in1++; // Write FIFO 1
        while (((*((volatile uint32_t*)0x50000004) & 4)) != 0)
            ;                                       // Wait for FIFO 2
        *((volatile uint32_t*)0x50000010) = *in2++; // Write FIFO 2
    }
}

// Expected output of layer 6 for rps-demo given the sample input
int check_output(void)
{
    if ((*((volatile uint32_t*)0x50401000)) != 0x00079c32)
        return CNN_FAIL; // 0,0,0
    if ((*((volatile uint32_t*)0x50401004)) != 0xfffae676)
        return CNN_FAIL; // 0,0,1
    if ((*((volatile uint32_t*)0x50401008)) != 0xfff657b6)
        return CNN_FAIL; // 0,0,2

    return CNN_OK;
}

// Classification layer:
static int32_t ml_data[CNN_NUM_OUTPUTS];
static q15_t ml_softmax[CNN_NUM_OUTPUTS];

void softmax_layer(void)
{
    cnn_unload((uint32_t*)ml_data);
    softmax_q17p14_q15((const q31_t*)ml_data, CNN_NUM_OUTPUTS, ml_softmax);
}

/* **************************************************************************** */
static uint8_t signed_to_unsigned(int8_t val)
{
    uint8_t value;
    if (val < 0) {
        value = ~val + 1;
        return (128 - value);
    }
    return val + 128;
}

/* **************************************************************************** */
int8_t unsigned_to_signed(uint8_t val)
{
    return val - 128;
}

/* **************************************************************************** */
void process_camera_img(uint32_t* data0, uint32_t* data1, uint32_t* data2)
{
    uint8_t* frame_buffer;
    uint32_t imgLen;
    uint32_t w, h, x, y;
    uint8_t* ptr0;
    uint8_t* ptr1;
    uint8_t* ptr2;
    uint8_t* buffer;

    camera_get_image(&frame_buffer, &imgLen, &w, &h);
    ptr0   = (uint8_t*)data0;
    ptr1   = (uint8_t*)data1;
    ptr2   = (uint8_t*)data2;
    buffer = frame_buffer;
    for (y = 0; y < h; y++)
    {
        for (x = 0; x < w; x++, ptr0++, ptr1++, ptr2++)
        {
            *ptr0 = (*buffer);
            buffer++;
            *ptr1 = (*buffer);
            buffer++;
            *ptr2 = (*buffer);
            buffer++;

            buffer++; //MSB is zero
        }
    }
}

/* **************************************************************************** */
void capture_camera_img(void)
{
    camera_start_capture_image();
    while (1)
    {
        if (camera_is_image_rcv())
        {
            return;
        }
    }
}

/* **************************************************************************** */
void convert_img_unsigned_to_signed(uint32_t* data0, uint32_t* data1, uint32_t* data2)
{
    uint8_t* ptr0;
    uint8_t* ptr1;
    uint8_t* ptr2;
    ptr0 = (uint8_t*)data0;
    ptr1 = (uint8_t*)data1;
    ptr2 = (uint8_t*)data2;
    for (int i = 0; i < 4096; i++)
    {
        *ptr0 = unsigned_to_signed(*ptr0);
        ptr0++;
        *ptr1 = unsigned_to_signed(*ptr1);
        ptr1++;
        *ptr2 = unsigned_to_signed(*ptr2);
        ptr2++;
    }
}

/* **************************************************************************** */
void convert_img_signed_to_unsigned(uint32_t* data0, uint32_t* data1, uint32_t* data2)
{
    uint8_t* ptr0;
    uint8_t* ptr1;
    uint8_t* ptr2;
    ptr0 = (uint8_t*)data0;
    ptr1 = (uint8_t*)data1;
    ptr2 = (uint8_t*)data2;
    for (int i = 0; i < 4096; i++)
    {
        *ptr0 = signed_to_unsigned(*ptr0);
        ptr0++;
        *ptr1 = signed_to_unsigned(*ptr1);
        ptr1++;
        *ptr2 = signed_to_unsigned(*ptr2);
        ptr2++;
    }
}

/* **************************************************************************** */
void cnn_wait(void)
{
    while ((*((volatile uint32_t*)0x50100000) & (1 << 12)) != 1 << 12)
        ;
    CNN_COMPLETE; // Signal that processing is complete
    cnn_time = MXC_TMR_SW_Stop(MXC_TMR0);
}

/* **************************************************************************** */
int main(void)
{
    int i, dma_channel;
    int digs, tens;
    int ret             = 0;
    int result[CNN_NUM_OUTPUTS] = {0};

    // Wait for PMIC 1.8V to become available, about 180ms after power up.
    MXC_Delay(200000);
    /* Enable camera power */
    Camera_Power(POWER_ON);
    printf("\n\nRPS Feather Demo\n");

    MXC_ICC_Enable(MXC_ICC0); // Enable cache

    // Switch to 100 MHz clock
    MXC_SYS_Clock_Select(MXC_SYS_CLOCK_IPO);
    SystemCoreClockUpdate();

    printf("Waiting...\n");

    // DO NOT DELETE THIS LINE:
    MXC_Delay(SEC(2)); // Let debugger interrupt if needed

    // Enable peripheral, enable CNN interrupt, turn on CNN clock
    // CNN clock: 50 MHz div 1
    cnn_enable(MXC_S_GCR_PCLKDIV_CNNCLKSEL_PCLK, MXC_S_GCR_PCLKDIV_CNNCLKDIV_DIV1);

    // Configure P2.5, turn on the CNN Boost
    mxc_gpio_cfg_t gpio_out;
    gpio_out.port = MXC_GPIO2;
    gpio_out.mask = MXC_GPIO_PIN_5;
    gpio_out.pad  = MXC_GPIO_PAD_NONE;
    gpio_out.func = MXC_GPIO_FUNC_OUT;
    MXC_GPIO_Config(&gpio_out);
    MXC_GPIO_OutSet(gpio_out.port, gpio_out.mask);

    MXC_Delay(1000000);

    // Initialize DMA for camera interface
    MXC_DMA_Init();
    dma_channel = MXC_DMA_AcquireChannel();

    // Initialize camera.
    printf("Init Camera.\n");
    camera_init(CAMERA_FREQ);

    ret = camera_setup(IMAGE_SIZE_X, IMAGE_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;
    }
    int frame = 0;

    while (1)
    {
        // Capture a single camera frame.
        printf("\nCapture a camera frame %d\n", ++frame);
        capture_camera_img();
        // Copy the image data to the CNN input arrays.
//        printf("Copy camera frame to CNN input buffers.\n");
        process_camera_img(input_0_camera, input_1_camera, input_2_camera);

        convert_img_unsigned_to_signed(input_0_camera, input_1_camera, input_2_camera);

        cnn_init();         // Bring state machine into consistent state
        cnn_load_weights(); // Load kernels
        cnn_load_bias();
        cnn_configure(); // Configure state machine
        cnn_start();     // Start CNN processing
        load_input();    // Load data input via FIFO
        MXC_TMR_SW_Start(MXC_TMR0);

        while (cnn_time == 0)
            __WFI(); // Wait for CNN

        softmax_layer();

        printf("Time for CNN: %d us\n\n", cnn_time);

        printf("Classification results:\n");
        for (i = 0; i < CNN_NUM_OUTPUTS; i++)
        {
            digs      = (1000 * ml_softmax[i] + 0x4000) >> 15;
            tens      = digs % 10;
            digs      = digs / 10;
            result[i] = digs;
            printf("[%7d] -> Class %d %16s: %d.%d%%\r\n", ml_data[i], i, classes[i], digs, tens);
        }

        printf("\n");
        MXC_Delay(SEC(2));
    }

    return 0;
}

将摄像头获得到的数据,喂给CNN网络后,会得出不同手势的概率值。

image.png

image.png

image.png

不过实际测试发现,剪刀、石头识别率还行,到了布总是识别错误。

最后附上视频:https://www.bilibili.com/video/BV1PatjzCEq1/



院士
2025-08-05 14:18:22     打赏
2楼

我觉得对于小MCU来说,这已经是很不错的效果了


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]