基于Stm32F1和Openmv的热成像人脸跟随测温仪


摘要

  设计并实现一个基于STM32的人体追踪温度检测系统,结合电路设计要求与经济性,实时性,选择STM32F103C8T6微控制器作为主控芯片和AMG8833热成像温度传感器来实现对人体温度的检测,基于Openmv做图像处理实现人脸额头追踪,实现自动人体无接触式体温测量,实时显示在Oled液晶显示屏上,超过预定温度启动声光报警。本文介绍该系统软硬件架构框图,硬件电路设计原理图以及主要外接模块。

一、方案概述

  按照系统设计功能要求,本自动人体追踪测温系统的设计采用电路设计结合单片机嵌入系统实现。设计系统由主控电路模块、测温模块、声光报警模块、显示模块、云台模块、图像获取与处理模块、键盘模块共七个模块(电源模块在PCB及硬件设计上加入)组成。

二、具体方案设计

1. 模块选择

主控芯片:STM32F103C8T6

测温模块:AMG8833

图像处理模块:Openmv

  采用的OpenMV是一个开源,低成本,功能强大的机器视觉模块。集成了OV7725摄像头芯片,内接图像降噪及稳定模块,在小巧的硬件模块上,用C语言高效地实现了核心机器视觉算法,搭载MicroPython解释器,这允许你在嵌入式上使用Python来编程,内置图像处理算法以及网络训练模型,集成硬件方便直接编程运作,速度与效率更高[3],能够满足本系统的实时性要求。

2. 系统框图

2.1 系统架构

  基于STM32F103RCT6所设计的自动温度测量系统,主控电路由 STM32微处理器及其外围电路组成,是系统的核心部分,主要完成数据的传输和处理工作。整个系统由单片机主控模块、测温模块、声光报警模块、显示模块、键盘模块、云台模块、图像获取与处理模块共七个模块。当检测到有人进入便启动测温电路,同步移动测温传感器追踪人体头部,通过温度芯片AMG8833测量温度,在短时间内精确测温,微控制器驱动液晶模块显示当前测得的温度,当温度大于37.8℃驱动报警电路,。 整个系统模块分为单片机主控模块、测温模块、声光报警模块、显示模块、键盘模块、云台模块、图像获取与处理模块共七个模块。
系统框图

2.2 系统软件设计流程

  软件设计主程序是云台处于循环扫描状态,搭载在云台上的OpenMV集成摄像头能够获取实时图像信息,返回给OpenMV主芯片,经过图像降噪和滤波,转化为灰度图,提取有效特征等预处理操作,导入网络训练模型进行目标特征识别,检测到有行人时,同步导入人脸关键点特征库,使用Openmv内置的Haar Cascade级联特征检测器实现人脸特征点检测,获取到额头的坐标信息返回给单片机,检测到串口传输信息,单片机进入串口中断,计算云台的更新信息,实时更新云台,搭载在云台上的温度传感器获取额头的温度,当温度超过37.8℃时,启动声光报警。通过键盘模块可以复位系统。

在这里插入图片描述
Stm32部分的源码
Openmv检测人脸

import sensor, image, time

from pid import PID
from pyb import Servo

pan_servo=Servo(1)
tilt_servo=Servo(2)

red_threshold  = (13, 49, 18, 61, 6, 47)

pan_pid = PID(p=0.07, i=0, imax=90) #脱机运行或者禁用图像传输,使用这个PID
tilt_pid = PID(p=0.05, i=0, imax=90) #脱机运行或者禁用图像传输,使用这个PID
#pan_pid = PID(p=0.1, i=0, imax=90)#在线调试使用这个PID
#tilt_pid = PID(p=0.1, i=0, imax=90)#在线调试使用这个PID

sensor.reset() # Initialize the camera sensor.
sensor.set_pixformat(sensor.GRAYSCALE) # use RGB565.
sensor.set_framesize(sensor.QVGA) # use QQVGA for speed.
sensor.set_vflip(True)
sensor.skip_frames(10) # Let new settings take affect.
sensor.set_auto_whitebal(False) # turn this off.
clock = time.clock() # Tracks FPS.
face_cascade = image.HaarCascade("frontalface", stages=25)

def find_max(blobs):
    max_size=0
    for blob in blobs:
        if blob[2]*blob[3] > max_size:
            max_blob=blob
            max_size = blob[2]*blob[3]
    return max_blob


while(True):
    clock.tick() # Track elapsed milliseconds between snapshots().
    img = sensor.snapshot() # Take a picture and return the image.

    faces = img.find_features(face_cascade, threshold=0.5, scale=1.25)
    if faces:
        face = find_max(faces)
        cx = int(face[0]+face[2]/2)
        cy = int(face[1]+face[3]/2)
        pan_error = cx-img.width()/2
        tilt_error = cy-img.height()/2

        print("pan_error: ", pan_error)

        img.draw_rectangle(face) # rect
        img.draw_cross(cx, cy) # cx, cy

        pan_output=pan_pid.get_pid(pan_error,1)
        tilt_output=tilt_pid.get_pid(tilt_error,1)
        print("pan_output",pan_output)
        pan_servo.angle(pan_servo.angle()+pan_output)
        tilt_servo.angle(tilt_servo.angle()+tilt_output)

Openmv控制云台

from pyb import millis
from math import pi, isnan

class PID:
    _kp = _ki = _kd = _integrator = _imax = 0
    _last_error = _last_derivative = _last_t = 0
    _RC = 1/(2 * pi * 20)
    def __init__(self, p=0, i=0, d=0, imax=0):
        self._kp = float(p)
        self._ki = float(i)
        self._kd = float(d)
        self._imax = abs(imax)
        self._last_derivative = float('nan')

    def get_pid(self, error, scaler):
        tnow = millis()
        dt = tnow - self._last_t
        output = 0
        if self._last_t == 0 or dt > 1000:
            dt = 0
            self.reset_I()
        self._last_t = tnow
        delta_time = float(dt) / float(1000)
        output += error * self._kp
        if abs(self._kd) > 0 and dt > 0:
            if isnan(self._last_derivative):
                derivative = 0
                self._last_derivative = 0
            else:
                derivative = (error - self._last_error) / delta_time
            derivative = self._last_derivative + \
                                     ((delta_time / (self._RC + delta_time)) * \
                                        (derivative - self._last_derivative))
            self._last_error = error
            self._last_derivative = derivative
            output += self._kd * derivative
        output *= scaler
        if abs(self._ki) > 0 and dt > 0:
            self._integrator += (error * self._ki) * scaler * delta_time
            if self._integrator < -self._imax: self._integrator = -self._imax
            elif self._integrator > self._imax: self._integrator = self._imax
            output += self._integrator
        return output
    def reset_I(self):
        self._integrator = 0
        self._last_derivative = float('nan')

猜你喜欢

转载自blog.csdn.net/weixin_45336082/article/details/115030061