基于STM32F407的人脸追踪

2023-11-13

整体概述

本项目采用两个舵机构成的二自由度的电动云台作为执行机构,控制摄像头在水平和垂直方向的运动。舵机带动摄像头进行二维平面的运动的同时,摄像头进行实时人脸检测,一旦检测到人脸,则进行人脸跟踪。

摄像头采用星瞳openMV H7,主控采用的是正点原子探索者F407开发板。

本文通过openMV和STM32两方面来讲解。

openMV部分

OpenMV摄像头是一款小巧,低功耗,低成本的电路板,它帮助你很轻松的完成机器视觉(machine vision)应用。其使用的是STM32F765VI ARM Cortex M7 处理器,所以其实我们编写openMV的代码从某种程度上来说其实还是往STM32里写代码,唯一不同的是,openMV这部分代码我们要用microPython来写。

在openMV上我们要做的很简单,如果摄像头识别到人脸,用矩形框将人脸框起来,通过串口把矩形框的中心坐标返回到开发板,开发读取坐标后控制舵机执行相应的运动。

所以首先,人脸追踪的基础是摄像头能够进行人脸检测。而openMV已经集成封装好了很多能够调用的库,其中正好就包含人脸检测相关的库和方法,只管调用就是了。(同时,openMV内置了n多个example,我们可以在example的基础上对代码进行修改。本例就是在face_detection的基础上修改实现的。)

模板例程这里就不赘述了,注释都写得很清楚,不了解的可以去看看官方的教程。这里主要讲一下人脸追踪的部分。

其中,我们要知道find_features方法返回一个关于这些特征的边界框矩形元组(x,y,w,h)的列表,若未发现任何特征,则返回一个空白列表。x,y是矩形框左上角的坐标值,w,h分别为矩形框的宽度和高度。那么很容易得到中心坐标(cx = x + w / 2, cy = y + h / 2)

接下来的任务就是将这两个数据通过串口传输到开发板。我们在串口上写了个简单的协议,规定发送数据的格式为:‘X’ + cx + ‘Y’ + cy + ‘OK’(后面讲STM32部分的时候会提到),于是我们这里向串口发送的数据为(‘X%dY%dOK\r\n’ % (cx,cy)),到了STM32部分我们会对接收到的数据进行分析然后把有效数据cx和cy从中提取出来。

具体代码如下:

import sensor, time, image
from pyb import UART

# Reset sensor
sensor.reset()

# Sensor settings
sensor.set_contrast(1)
sensor.set_gainceiling(16)
# HQVGA and GRAYSCALE are the best for face tracking.
sensor.set_framesize(sensor.HQVGA)
sensor.set_pixformat(sensor.GRAYSCALE)

# Load Haar Cascade
face_cascade = image.HaarCascade("frontalface", stages=25)

# OpenMV上P4,P5对应的串口3
uart = UART(3, 115200, timeout_char=1000)

# FPS clock
clock = time.clock()

while (True):
    clock.tick()

    # Capture snapshot
    img = sensor.snapshot()

    # Find objects.
    objects = img.find_features(face_cascade, threshold=0.75, scale_factor=1.25)
    #find_features函数返回一个关于要找的这些feature的边界框矩形元组(x,y,w,h)的列表。
    #若未发现任何要找的feature,则返回一个空白列表,即objects是一个元组列表,包含(x,y,w,h)这个元组作为唯一一个元素

    # Draw objects
    for r in objects:
        if(r):
            img.draw_rectangle(r,color = (255,0,0))
            cx = r[0]+r[2]/2                                            #计算得到人脸矩形框的中心x坐标
            cy = r[1]+r[3]/2                                            #计算得到人脸矩形框的中心y坐标
            print('x:%d, y:%d, w:%d, h:%d' % (r[0],r[1],r[2],r[3]) )    #打印矩形框的x,y,w,h
            print('cx = %d, cy = %d' % (cx,cy))
            uart.write('X%dY%dOK\r\n' % (cx,cy))
            break
    else:
            #print('cannot find any face!')
            uart.write('X-1Y-1OK\r\n')

STM32部分

舵机部分

扫描函数:用两层循环分别控制x方向和y方向的舵机运动,即可实现摄像头的二维运动。一旦识别到人脸,退出扫描函数,进入跟随函数,让摄像头跟随人脸运动,使人脸一直处于画面正中心。

跟随函数:如果识别到人脸,获取人脸在屏幕中的位置,当其距离屏幕正中心超过一定的阈值时,调节相应的舵机,使之向屏幕中心靠拢。如果未识别到人脸,则继续从当前位置开始执行扫描函数。

串口部分

上文提到,openMV捕获到人脸后,不断通过串口向STM32发送数据,所以我们串口函数的目的就是把接收到的数据中的cx和cy提取出来(其余数据丢弃不用),然后把cx和cy和舵机的运动函数联系起来,进而控制摄像头云台执行相应运动实现人脸追踪。

串口的配置过于简单,这里就略过不讲了,主要还是讲解一下如何解析从openMV接收到的格式为’X’ + cx + ‘Y’ + cy + 'OK’的数据并从中提取有效信息cx和xy。

我们提取数据的代码将在正点原子的串口中断函数的基础上进行更改,可以先在我的上一篇博文了解到正点原子串口中断函数的思路:基于STM32F407的串口通信

正点原子串口中断函数改编版
通过正点原子的例子,我们知道如果我们的数据如果是以‘OK’结尾,会被串口认为有效数据接收,且‘OK’不会作为数据内容存入buffer数组中。

于是,‘X’ + cx + ‘Y’ + cy + 'OK’格式的数据(e.g. X17Y41OK)被STM32的串口有效接收后存放到buffer数组里的数据是X17Y41,那么我们只要通过遍历把XY之间的cx提取出来,把Y之后的cy提取出来,分别存放在两个数组里,就实现了cx和cy的提取。

(如果STM32部分的代码(如舵机控制)也干脆在openMV上写,那么提取数据用Python的正则表达式之类的应该很轻松能做到。不过当然,如果舵机控制部分在openMV上写,那也不会有串口通信和这些带格式的数据了,毕竟数据不需要通过串口从两个设备之间传输了。当然这是后话了,以后尝试只用openMV实现)

显然,我们是在数据接收完成后(即USART_RX_STA&0x8000==1)进行的进一步操作,于是我们在if((USART_RX_STA&0x8000)==0)后紧跟else if语句,条件为(USART_RX_STA&0x8000),表明接收完成,开始分析数据。

思路前面已经大致提到了,我们先建立两个buffer数组分别用于存放cx和cy的数据。然后按字节遍历整个接收数据,当识别到当前字节的数据为‘X’时,将之后出现的数据存放到cx数组中,当识别到当前字节的数据为‘Y’时,将之后出现的数据存放到cy数组中。最后,由于串口接收到的是char型数据,我们再通过atoi()函数将char型转化成int型的数据即可。

以上就是人脸追踪的大致思路了,写得有点复杂,其实代码还可以较大程度的优化,以后有时间再改了。

具体代码见:完整代码

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于STM32F407的人脸追踪 的相关文章

  • JS数组方法&&es5数组新增方法

    1 unshift 给数组的开头添加一个或多个元素 数组名 unshift 一个值或多个值 返回添加以后的新数组的长度 2 push 给数组的末尾添加一个或多个元素 数组 push 一个值或多个值 返回新数组的长度 3 shift 给数组的

随机推荐

  • C++的Json库的简单实现

    我的Json库实现 Json 实现Json 我的源码 点这里 https github com jo qzy MyJson 和效果图 Json库中的类实现 JSON Value类 JSON Reader JSON Writer FastWr
  • 第十二章 Ambari二次开发之集成Alluxio

    1 Alluxio高可用部署 生产环境 使用具有高可用性的模式来运行Alluxio masters 1 1 Alluxio架构 Alluxio可以被分为三个部分 masters workers以及clients 一个典型的设置由一个主服务器
  • MySQL 过滤重复数据

    方法1 加关键字 DISTINCT 在mysql中 可以利用 SELECT 语句和 DISTINCT 关键字来进行去重查询 过滤掉重复的数据 语法 SELECT DISTINCT 字段名 FROM 数据表名 DISTINCT 关键字的语法格
  • HTML+CSS+JavaScript写计算器

    思维导图 代码 HTML div div div div div div
  • TestNg多线程—— 并行执行测试

    多线程并行执行测试 可以通过参数设置来实现不同级别的多线程配置测试 1 test级别的多线程测试 每个
  • 第二章:25+ Python 数据操作教程(第十八节如何使用 Matplotlib 库在 python 中执行绘图和数据可视化)持续更新中

    本教程概述了如何使用 Matplotlib 库在 python 中执行绘图和数据可视化 这篇文章的目的是让您熟悉该库的基础知识和高级绘图功能 它包含几个示例 将为您提供使用 Python 生成绘图的实践经验 目录 什么是 Matplotli
  • phpshe v1.7漏洞复现(Sql injection+XXE)

    前几天研究了一下xss的绕过 这两天准备深入研究下sql注入的审计 首先自动审计一波 看到疑似的一个变量覆盖点 点进去看原来是 register globals的隐患消除 简单来说如果这个配置设置为On的话 从客户端传输过来的任意参数值会被
  • jboss 热部署

    文章目录 JBoss EAP 6 4 0 GA AS 7 5 0 Final redhat 21 JBoss EAP 6 4 0 GA AS 7 5 0 Final redhat 21
  • 一文学会动态规划

    系列文章目录 注意 在学习理论之前 希望读者能看如下几个例子 有助于理解 算法导论 学习 十七 动态规划之钢条切割 C语言 算法导论 学习 十八 动态规划之矩阵链乘 C语言 算法导论 学习 十九 动态规划之最长公共子序列 C语言 文章目录
  • 浅谈数据挖掘——频繁模式、序列挖掘与搜索优化算法

    本系列将从下面几方面谈谈最近的一点点收获 令声明 本文主要是对我找到的一个莫名其妙国外英文pdf文件的学习与解读 因为我也没有找到他的出处 也没作者也没学校 所以我仅以此段文字向这个未知的作者致敬 本文主要处于科普类的理解 列出的主要算法并
  • SpringBoot学习之单点登录

    SpringBoot学习之单点登录 单点登录 登录 注销 部署 实现 主要功能 重要步骤 sso client拦截未登录请求 sso server拦截未登录请求 sso server验证用户登录信息 sso server创建授权令牌 sso
  • 直播运营岗

    一 理论知识 直播基础知识 直播团队构成 直播工作流程 中控工作流程 中控话术 二 界面操作 电商罗盘 巨量百应 直播伴侣 发单打单 产品链接 三 进阶学习 千川投放 直播复盘 四 面试规划 简历制作 职业生涯规划 1 直播基础知识 1 1
  • 银河麒麟桌面操作系统安装 postgreSQL13(源码安装)

    1 首先下载源码postgres wget http ftp postgresql org pub source v13 1 postgresql 13 1 tar bz2 2 解压 tar xjvf postgresql 13 1 tar
  • visual studio 2017 installer 安装包制作过程出现的问题---无法注册模块 HRESULT -2147024769 请与您的技术支持人员联系...

    使用visual studio 2017 installer制作打包程序时如果用到了外部控件需要按以下方式操作 1 将应用程序及应用程序所用到的所有DLL拷贝到打包目录 加入打包程序之中 2 将应用程序的XXX dll或XXX ocx的Re
  • STM32 C++编程系列一:STM32 C++编程介绍

    一 STM32及其他单片机开发现状 在目前绝大部分的单片机开发当中 C语言占据着主流的地位 但由于C语言本身是一种面向过程的语言 因此在当前利用面向对象思想构建可复用代码为主流的今天显得比较麻烦 很多人写单片机程序时都会遇到一个问题 明明写
  • 大数据采集概述

    文章目录 大数据采集概述 1 互联网大数据与采集 1 1互联网大数据来源 1 社交媒体 2 社交网络 3 百科知识库 4 新闻网站 5 评论信息 6 位置型信息 1 2 互联网大数据的特征 1 大数据类型和语义更加丰富 2 数据的规范化程度
  • 内存溢出问题解决思路

    内存溢出问题解决 一 常规解决思路 首先 在JVM参数配置时需要配置内存溢出后dump出内存的快照来 配置如下 XX HeapDumpOnOutOfMemoryError XX HeapDumpPath 内存快照 hprof输出路径 然后
  • 理解Java类加载的步骤

    前言 与在编译时需要进行 连接 工作的语言不同 在Java语言里 类的加载 连接 初始化过程都是在程序运行期间完成的 这种策略虽然牺牲了一小部分性能 但是大大增加了Java的灵活性 Java里天生可以动态拓展的语言特性就是依赖运行期动态加载
  • Linux线程同步(二)---互斥锁实现线程同步

    一 why 先给自己打个广告 本人的微信公众号 嵌入式Linux江湖 主要关注嵌入式软件开发 股票基金定投 足球等等 希望大家多多关注 有问题可以直接留言给我 一定尽心尽力回答大家的问题 在博客 Linux线程同步 一 初识篇 中 介绍了为
  • 基于STM32F407的人脸追踪

    整体概述 本项目采用两个舵机构成的二自由度的电动云台作为执行机构 控制摄像头在水平和垂直方向的运动 舵机带动摄像头进行二维平面的运动的同时 摄像头进行实时人脸检测 一旦检测到人脸 则进行人脸跟踪 摄像头采用星瞳openMV H7 主控采用的