加入星计划,您可以享受以下权益:

  • 创作内容快速变现
  • 行业影响力扩散
  • 作品版权保护
  • 300W+ 专业用户
  • 1.5W+ 优质创作者
  • 5000+ 长期合作伙伴
立即加入

【RT-Thread作品秀】基于ART-Pi的人脸识别系统

2020/12/19
1124
服务支持:
技术交流群

完成交易后在“购买成功”页面扫码入群,即可与技术大咖们分享疑惑和经验、收获成长和认同、领取优惠和红包等。

虚拟商品不可退

当前内容为数字版权作品,购买后不支持退换且无法转移使用。

加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论
放大
方块图(2)
相关方案
  • 方案介绍
  • 相关文件
  • 相关推荐
  • 电子产业图谱
申请入驻 产业图谱

作者:Signx

概述

当前的人脸识别摄像头,价格昂贵,拟改造成stm32单片机版本的,节省成本

功能:

1.连接摄像头OV2640,用fish指令开启摄像头

2.将摄像头数据传到电脑显示图片

3.将摄像头数据传到spi显示屏显示(未完成)

4.用人脸识别算法识别人脸开锁(未完成)

5.可登录到tencent Cloud云平台,实现上云

开发环境:

硬件:Art-pi+OV2640

RT-Thread版本:4.0.2

开发工具及版本:rt-stuidio V2.0.0

RT-Thread使用情况概述:

硬件框架:art-pi官方开发板+OV2640(dma+DCMI)

软件框架说明:

见思维导图

软件模块说明:

见思维导图

该系统的思维脑图如下:

 

演示效果:

视频:

实物图如下:

实现的效果如图:

连接电路如图所示:

实现功能:

1.连接摄像头OV2640,用fish指令开启摄像头

2.将摄像头数据传到电脑显示图片

3.将摄像头数据传到spi显示屏显示(未完成)

4.用人脸识别算法识别人脸开锁(未完成)

5.可登录到tencent Cloud云平台,实现上云主要碰到的技术难点:

1.art-pi组建库里有ov2640的软件包,本以为直接能用的,结果发现有很多缺失

首先是io口的确实,没有定义到足够的io口,所以代码里又加上了io口的定义以及初始化:

io口定义代码:

typedef enum   
{
  BMP_QQVGA             =   0x00,        /* BMP Image QQVGA 160x120 Size */
  BMP_QVGA              =   0x01,      /* BMP Image VGA 800*480 Size */
  JPEG_160x120          =   0x02,        /* JPEG Image 160x120 Size */
  JPEG_176x144          =   0x03,        /* JPEG Image 176x144 Size */
  JPEG_320x240          =   0x04,        /* JPEG Image 320x240 Size */
  JPEG_352x288          =   0x05        /* JPEG Image 352x288 Size */
}ImageFormat_TypeDef;

/*摄像头接口 */
//IIC SCCB
//#define CAMERA_I2C                          I2C1
//#define CAMERA_I2C_CLK_ENABLE()             __HAL_RCC_I2C1_CLK_ENABLE()
//
//#define CAMERA_I2C_SCL_PIN                  GPIO_PIN_8
//#define CAMERA_I2C_SCL_GPIO_PORT            GPIOB
//#define CAMERA_I2C_SCL_GPIO_CLK_ENABLE()    __HAL_RCC_GPIOB_CLK_ENABLE()
//#define CAMERA_I2C_SCL_AF                   GPIO_AF4_I2C1
//
//#define CAMERA_I2C_SDA_PIN                  GPIO_PIN_9
//#define CAMERA_I2C_SDA_GPIO_PORT            GPIOB
//#define CAMERA_I2C_SDA_GPIO_CLK_ENABLE()    __HAL_RCC_GPIOB_CLK_ENABLE()
//#define CAMERA_I2C_SDA_AF                   GPIO_AF4_I2C1

//VSYNC
#define DCMI_VSYNC_GPIO_PORT                GPIOI
#define DCMI_VSYNC_GPIO_CLK_ENABLE()        __HAL_RCC_GPIOI_CLK_ENABLE()
#define DCMI_VSYNC_GPIO_PIN                 GPIO_PIN_5
#define DCMI_VSYNC_AF                            GPIO_AF13_DCMI
// HSYNC
#define DCMI_HSYNC_GPIO_PORT                GPIOH
#define DCMI_HSYNC_GPIO_CLK_ENABLE()        __HAL_RCC_GPIOH_CLK_ENABLE()
#define DCMI_HSYNC_GPIO_PIN                 GPIO_PIN_8
#define DCMI_HSYNC_AF                            GPIO_AF13_DCMI
//PIXCLK
#define DCMI_PIXCLK_GPIO_PORT                GPIOA
#define DCMI_PIXCLK_GPIO_CLK_ENABLE()       __HAL_RCC_GPIOA_CLK_ENABLE()
#define DCMI_PIXCLK_GPIO_PIN                 GPIO_PIN_6
#define DCMI_PIXCLK_AF                          GPIO_AF13_DCMI
//PWDN
#define DCMI_PWDN_GPIO_PORT                  GPIOH
#define DCMI_PWDN_GPIO_CLK_ENABLE()         __HAL_RCC_GPIOH_CLK_ENABLE()
#define DCMI_PWDN_GPIO_PIN                   GPIO_PIN_3

//RST
//#define DCMI_RST_GPIO_PORT                  GPIOH
//#define DCMI_RST_GPIO_CLK_ENABLE()          __HAL_RCC_GPIOH_CLK_ENABLE()
//#define DCMI_RST_GPIO_PIN                   GPIO_PIN_8

//数据信号线
#define DCMI_D0_GPIO_PORT                    GPIOC
#define DCMI_D0_GPIO_CLK_ENABLE()             __HAL_RCC_GPIOC_CLK_ENABLE()
#define DCMI_D0_GPIO_PIN                     GPIO_PIN_6
#define DCMI_D0_AF                              GPIO_AF13_DCMI

#define DCMI_D1_GPIO_PORT                    GPIOC
#define DCMI_D1_GPIO_CLK_ENABLE()             __HAL_RCC_GPIOC_CLK_ENABLE()
#define DCMI_D1_GPIO_PIN                     GPIO_PIN_7
#define DCMI_D1_AF                              GPIO_AF13_DCMI

#define DCMI_D2_GPIO_PORT                    GPIOG
#define DCMI_D2_GPIO_CLK_ENABLE()             __HAL_RCC_GPIOG_CLK_ENABLE()
#define DCMI_D2_GPIO_PIN                     GPIO_PIN_10
#define DCMI_D2_AF                              GPIO_AF13_DCMI

#define DCMI_D3_GPIO_PORT                    GPIOG
#define DCMI_D3_GPIO_CLK_ENABLE()             __HAL_RCC_GPIOG_CLK_ENABLE()
#define DCMI_D3_GPIO_PIN                     GPIO_PIN_11
#define DCMI_D3_AF                              GPIO_AF13_DCMI

#define DCMI_D4_GPIO_PORT                    GPIOH
#define DCMI_D4_GPIO_CLK_ENABLE()             __HAL_RCC_GPIOH_CLK_ENABLE()
#define DCMI_D4_GPIO_PIN                     GPIO_PIN_14
#define DCMI_D4_AF                              GPIO_AF13_DCMI

#define DCMI_D5_GPIO_PORT                    GPIOI
#define DCMI_D5_GPIO_CLK_ENABLE()         __HAL_RCC_GPIOI_CLK_ENABLE()
#define DCMI_D5_GPIO_PIN                     GPIO_PIN_4
#define DCMI_D5_AF                              GPIO_AF13_DCMI

#define DCMI_D6_GPIO_PORT                    GPIOB
#define DCMI_D6_GPIO_CLK_ENABLE()         __HAL_RCC_GPIOB_CLK_ENABLE()
#define DCMI_D6_GPIO_PIN                     GPIO_PIN_8
#define DCMI_D6_AF                              GPIO_AF13_DCMI

#define DCMI_D7_GPIO_PORT                    GPIOI
#define DCMI_D7_GPIO_CLK_ENABLE()         __HAL_RCC_GPIOI_CLK_ENABLE()
#define DCMI_D7_GPIO_PIN                     GPIO_PIN_7
#define DCMI_D7_AF                              GPIO_AF13_DCMI

io口初始化代码:

void OV2640_HW_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    
    /***DCMI引脚配置***/
    /* 使能DCMI时钟 */
    DCMI_PWDN_GPIO_CLK_ENABLE();
    DCMI_VSYNC_GPIO_CLK_ENABLE();
    DCMI_HSYNC_GPIO_CLK_ENABLE();
    DCMI_PIXCLK_GPIO_CLK_ENABLE();    
    DCMI_D0_GPIO_CLK_ENABLE();
    DCMI_D1_GPIO_CLK_ENABLE();
    DCMI_D2_GPIO_CLK_ENABLE();
    DCMI_D3_GPIO_CLK_ENABLE();    
    DCMI_D4_GPIO_CLK_ENABLE();
    DCMI_D5_GPIO_CLK_ENABLE();
    DCMI_D6_GPIO_CLK_ENABLE();
    DCMI_D7_GPIO_CLK_ENABLE();

    /*控制/同步信号线*/
    GPIO_InitStructure.Pin = DCMI_VSYNC_GPIO_PIN;
    GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStructure.Pull = GPIO_PULLUP ;
    GPIO_InitStructure.Alternate = DCMI_VSYNC_AF;
    HAL_GPIO_Init(DCMI_VSYNC_GPIO_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.Pin = DCMI_HSYNC_GPIO_PIN;
    GPIO_InitStructure.Alternate = DCMI_VSYNC_AF;
    HAL_GPIO_Init(DCMI_HSYNC_GPIO_PORT, &GPIO_InitStructure);
 

    GPIO_InitStructure.Pin = DCMI_PIXCLK_GPIO_PIN;
    GPIO_InitStructure.Alternate = DCMI_PIXCLK_AF;
    HAL_GPIO_Init(DCMI_PIXCLK_GPIO_PORT, &GPIO_InitStructure);
    
    /*数据信号*/
    GPIO_InitStructure.Pin = DCMI_D0_GPIO_PIN;
    GPIO_InitStructure.Alternate = DCMI_D0_AF;
    HAL_GPIO_Init(DCMI_D0_GPIO_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.Pin = DCMI_D1_GPIO_PIN;
    GPIO_InitStructure.Alternate = DCMI_D1_AF;
    HAL_GPIO_Init(DCMI_D1_GPIO_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.Pin = DCMI_D2_GPIO_PIN;
    GPIO_InitStructure.Alternate = DCMI_D2_AF;
    HAL_GPIO_Init(DCMI_D2_GPIO_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.Pin = DCMI_D3_GPIO_PIN;
    GPIO_InitStructure.Alternate = DCMI_D3_AF;
    HAL_GPIO_Init(DCMI_D3_GPIO_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.Pin = DCMI_D4_GPIO_PIN;
    GPIO_InitStructure.Alternate = DCMI_D4_AF;
    HAL_GPIO_Init(DCMI_D4_GPIO_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.Pin = DCMI_D5_GPIO_PIN;
    GPIO_InitStructure.Alternate = DCMI_D5_AF;
    HAL_GPIO_Init(DCMI_D5_GPIO_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.Pin = DCMI_D6_GPIO_PIN;
    GPIO_InitStructure.Alternate = DCMI_D6_AF;
    HAL_GPIO_Init(DCMI_D6_GPIO_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.Pin = DCMI_D7_GPIO_PIN;
    GPIO_InitStructure.Alternate = DCMI_D7_AF;
    HAL_GPIO_Init(DCMI_D7_GPIO_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.Pin = DCMI_PWDN_GPIO_PIN;
    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;    
    HAL_GPIO_Init(DCMI_PWDN_GPIO_PORT, &GPIO_InitStructure);
    /*PWDN引脚,高电平关闭电源,低电平供电*/
    HAL_GPIO_WritePin(DCMI_PWDN_GPIO_PORT,DCMI_PWDN_GPIO_PIN,GPIO_PIN_RESET);
    
}

2.官方源代码里没有打开dcmi使能,导致编译的时候会报错,根据报错的情况把对应的使能开开就行;

3.官方代码导入之后并没有开启dcmi的中断,又要打开中断:

static rt_err_t rt_hw_dcmi_init(DCMI_HandleTypeDef *device)
{
    RT_ASSERT(device != RT_NULL);

    __HAL_RCC_DCMI_CLK_ENABLE();//signx

    device->Instance               = DCMI;
    device->Init.SynchroMode       = DCMI_SYNCHRO_HARDWARE;
    device->Init.PCKPolarity       = DCMI_PCKPOLARITY_RISING;
    device->Init.VSPolarity        = DCMI_VSPOLARITY_LOW;
    device->Init.HSPolarity        = DCMI_HSPOLARITY_LOW;
    device->Init.CaptureRate       = DCMI_CR_ALL_FRAME;
    device->Init.ExtendedDataMode  = DCMI_EXTEND_DATA_8B;

    device->Init.JPEGMode          = DCMI_JPEG_ENABLE;
    device->Init.ByteSelectMode    = DCMI_BSM_ALL;
    device->Init.ByteSelectStart   = DCMI_OEBS_ODD;
    device->Init.LineSelectMode    = DCMI_LSM_ALL;
    device->Init.LineSelectStart   = DCMI_OELS_ODD;

    if (HAL_DCMI_Init(device) != HAL_OK)
    {
        LOG_E("dcmi init error!");
        return RT_ERROR;
    }

    DCMI->IER = 0x0;

    __HAL_DCMI_ENABLE_IT(device, DCMI_IT_FRAME);
    __HAL_DCMI_ENABLE(device);

    HAL_NVIC_SetPriority(DCMI_IRQn, 0x00, 0x05);
    HAL_NVIC_EnableIRQ(DCMI_IRQn);;

    return RT_EOK;
}

4.官方的代码没有打开dma的中断,又把dma的中断打开:

static void rt_hw_dcmi_dma_init(void)
{
    __HAL_RCC_DMA2_CLK_ENABLE();

    hdma_dcmi.Instance                 = DMA2_Stream1;
    hdma_dcmi.Init.Request             = DMA_REQUEST_DCMI;
    hdma_dcmi.Init.Direction           = DMA_PERIPH_TO_MEMORY;
    hdma_dcmi.Init.PeriphInc           = DMA_PINC_DISABLE;
    hdma_dcmi.Init.MemInc              = DMA_MINC_ENABLE;
    hdma_dcmi.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
    hdma_dcmi.Init.MemDataAlignment    = DMA_MDATAALIGN_WORD;
    hdma_dcmi.Init.Mode                = DMA_CIRCULAR;
    hdma_dcmi.Init.Priority            = DMA_PRIORITY_HIGH;
    hdma_dcmi.Init.FIFOMode            = DMA_FIFOMODE_ENABLE;
    hdma_dcmi.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
    hdma_dcmi.Init.MemBurst            = DMA_MBURST_SINGLE;
    hdma_dcmi.Init.PeriphBurst         = DMA_PBURST_SINGLE;

    HAL_DMA_Init(&hdma_dcmi);

    __HAL_LINKDMA(&rt_dcmi.DCMI_Handle, DMA_Handle, hdma_dcmi);

    HAL_NVIC_SetPriority(DMA2_Stream1_IRQn, 0x00, 0x00);
    HAL_NVIC_EnableIRQ(DMA2_Stream1_IRQn);;

}

然后就把摄像头驱动起来了,这过程用去了3个周末的时间,吐槽一下官方库,没做好就没必要放出来嘛,放出来个有问题的,找问题比从头写更费劲

比赛感悟:

1.学习到了如何用单片机控制OV2640乃至其他的摄像头,学习到了DMA和HDCI的操作,这其中涉及到HDCI的引脚定义,需要查找手册书

2.Rt-thread真的是一款非常好用的实时系统,不光是功能强大,而且接口简洁明了,类linux的明明风格更是让开发者上手简单,先进的面向对象设计思想让我的代码公里也见长进

3.感谢RT和电路城提供这么好的机会,能让我有机会亲自操作ART-PI,当然STM32H750和开发板的强大性能还拥有很大的开发潜力,

4.由于时间关系(年底事情多,好多项目等着结项),原定的实现人脸识别开锁的功能做不了了,但是这么好的art-pi不能浪费了,所以接下来还会继续开发,直到完成所有的功能为止.学会了rtthread官方包的导入

  • 电路图.png
    描述:电路图
  • smartLock.zip
    描述:源代码
  • 代码地址.txt
  • 基于art-pi的人脸识别系统.docx
    描述:文档电子版

相关推荐

电子产业图谱