基于STM32单片机设计的红外测温仪(带人脸检测)

发布者:数据旅人最新更新时间:2022-09-15 来源: csdn关键字:STM32  单片机  红外测温仪 手机看文章 扫描二维码
随时随地手机看文章

由于医学发展的需要,在很多情况下,一般的温度计己经满足不了快速而又准确的测温要求,例如:车站、地铁、机场等人口密度较大的地方进行人体温度测量。


当前设计的这款红外非接触式测温仪由测温硬件+上位机软件组合而成,主要用在地铁、车站入口等地方,可以准确识别人脸进行测温,如果有人温度超标会进行语音提示并且保存当前人脸照片。


1、 硬件选型与设计思路

(1). 设备端

主控单片机采用STM32F103C8T6,人体测温功能采用非接触式红外测温模块。

imgimg

(2). 上位机设计思路

上位机采用Qt5设计,Qt5是一套基于C++语言的跨平台软件库,性能非常强大,目前桌面端很多主流的软件都是采用QT开发。比如: 金山办公旗下的-WPS,字节跳动旗下的-剪映,暴雪娱乐公司旗下-多款游戏登录器等等。Qt在车联网领域用的也非常多,比如,哈佛,特斯拉,比亚迪等等很多车的中控屏整个系统都是采用Qt设计。


在测温项目里,上位机与STM32之间采用串口协议进行通信,上位机可以打开笔记本电脑默认的摄像头,进行人脸检测;当检测到人脸时,控制STM32测量当前人体的实时温度实时,再将温度传递到上位机显示;当温度正常时,上位机上显示绿色的提示字样“温度正常”,并有语音播报,语音播报的声音使用笔记本自带的声卡发出。如果温度过高,上位机显示红色提示字样“温度异常,请重新测量”,并有语音播报提示。温度过高时,会自动将当前人脸拍照留存,照片存放在当前软件目录下的“face”目录里,文件的命名规则是“38.8_2022-01-05-22-12-34.jpg”,其中38.8表示温度值,后面是日期(年月日时分秒)。


(3) 上位机运行效果

img

img

上位机需要连接STM32设备之后才可以获取温度数据,点击软件上的打开摄像头按钮,开启摄像头,让检测到人脸时,下面会显示当前测量的温度。如果没有连接STM32设备,那么默认会显示一个正常的固定温度值。界面上右边红色的字,表示当前处理一帧图像的耗时时间,电脑性能越好,检测速度越快。


(4) 拿到可执行文件之后如何运行?

先解压压缩包,进入“测温仪上位机-可执行文件”目录,将“haarcascade_frontalface_alt2.xml”拷贝到C盘根目录。

img

img

然后双击“FaceTemperatureCheck.exe”运行程序。

img

未连接设备,也可以打开摄像头检测人脸,只不过温度值是一个固定的正常温度值范围。


二、上位机设计

2.1 安装编译环境

如果需要自己编译运行源代码,需要先安装Qt5开发环境。


下载地址: https://download.qt.io/official_releases/qt/5.12/5.12.0/

img

下载之后,先将电脑网络断掉(不然会提示要求输入QT的账号),然后双击安装包进行安装。


安装可以只需要选择一个MinGW 32位编译器就够用了,详情看下面截图,选择“MinGW 7.3.0 32-bit”后,就点击下一步,然后等待安装完成即可。

img

2.2 软件代码整体效果

如果需要完整的工程,可以在这里去下载:

https://download.csdn.net/download/xiaolong1126626497/85892490

img

打开工程后(工程文件的后缀是xxx.pro),点击左下角的绿色三角形按钮就可以编译运行程序。

img

2.3 UI设计界面

img

2.4 人脸检测核心代码

//人脸检测代码

bool ImageHandle::opencv_face(QImage qImage)

{

    bool check_flag=0;


    QTime time;

    time.start();

    static CvMemStorage* storage = nullptr;

    static CvHaarClassifierCascade* cascade = nullptr;


    //模型文件路径

    QString face_model_file = QCoreApplication::applicationDirPath()+"/"+FACE_MODEL_FILE;


    //加载分类器:正面脸检测

    cascade = (CvHaarClassifierCascade*)cvLoad(face_model_file.toUtf8().data(), 0, 0, 0 );

    if(!cascade)

    {

        qDebug()<<"分类器加载错误.n";

        return check_flag;

    }


    //创建内存空间

    storage = cvCreateMemStorage(0);


    //加载需要检测的图片

    IplImage* img = QImageToIplImage(&qImage);


    if(img ==nullptr )

    {

        qDebug()<<"图片加载错误.n";

        return check_flag;

    }


    double scale=1.2;


    //创建图像首地址,并分配存储空间

    IplImage* gray = cvCreateImage(cvSize(img->width,img->height),8,1);


    //创建图像首地址,并分配存储空间

    IplImage* small_img=cvCreateImage(cvSize(cvRound(img->width/scale),cvRound(img->height/scale)),8,1);

    cvCvtColor(img,gray, CV_BGR2GRAY);

    cvResize(gray, small_img, CV_INTER_LINEAR);

    cvEqualizeHist(small_img,small_img); //直方图均衡

    /*

     * 指定相应的人脸特征检测分类器,就可以检测出图片中所有的人脸,并将检测到的人脸通过矩形的方式返回。

     * 总共有8个参数,函数说明:

    参数1:表示输入图像,尽量使用灰度图以加快检测速度。

    参数2:表示Haar特征分类器,可以用cvLoad()函数来从磁盘中加载xml文件作为Haar特征分类器。

    参数3:用来存储检测到的候选目标的内存缓存区域。

    参数4:表示在前后两次相继的扫描中,搜索窗口的比例系数。默认为1.1即每次搜索窗口依次扩大10%

    参数5:表示构成检测目标的相邻矩形的最小个数(默认为3个)。如果组成检测目标的小矩形的个数和小于 min_neighbors - 1 都会被排除。如果min_neighbors 为 0, 则函数不做任何操作就返回所有的被检候选矩形框,这种设定值一般用在用户自定义对检测结果的组合程序上。

    参数6:要么使用默认值,要么使用CV_HAAR_DO_CANNY_PRUNING,如果设置为CV_HAAR_DO_CANNY_PRUNING,那么函数将会使用Canny边缘检测来排除边缘过多或过少的区域,因此这些区域通常不会是人脸所在区域。

    参数7:表示检测窗口的最小值,一般设置为默认即可。

    参数8:表示检测窗口的最大值,一般设置为默认即可。

    函数返回值:函数将返回CvSeq对象,该对象包含一系列CvRect表示检测到的人脸矩形。

    */

    CvSeq* objects = cvHaarDetectObjects(small_img,

                                           cascade,

                                           storage,

                                           1.1,

                                           3,

                                           0/*CV_HAAR_DO_CANNY_PRUNING*/,

                                           cvSize(50,50)/*大小决定了检测时消耗的时间多少*/);


    qDebug()<<"人脸数量:"<total;


    //遍历找到对象和周围画盒

    QPainter painter(&qImage);//构建 QPainter 绘图对象

    QPen pen;

    pen.setColor(Qt::blue); //画笔颜色

    pen.setWidth(5); //画笔宽度

    painter.setPen(pen); //设置画笔


    CvRect *max=nullptr;


    for(int i=0;i<(objects->total);++i)

    {

        //得到人脸的坐标位置和宽度高度信息

        CvRect* r=(CvRect*)cvGetSeqElem(objects,i);


        if(max==nullptr)max=r;

        else

        {

            if(r->width > max->width || r->height > max->height)

            {

                max=r;

            }

        }

    }


    //如果找到最大的目标脸

    if(max!=nullptr)

    {

        check_flag=true;

        //将人脸区域绘制矩形圈起来

        painter.drawRect(max->x*scale,max->y*scale,max->width*scale,max->height*scale);

    }


    cvReleaseImage(&gray);  //释放图片内存

    cvReleaseImage(&small_img);  //释放图片内存

    cvReleaseHaarClassifierCascade(&cascade); //释放内存-->分类器

    cvReleaseMemStorage(&objects->storage); //释放内存-->检测出图片中所有的人脸


    //释放图片

    cvReleaseImage(&img);


    qint32 time_ms=0;

    time_ms=time.elapsed();


    //耗时时间

    emit ss_log_text(QString("%1").arg(time_ms));


    //保存结果

    m_image=qImage.copy();


    return check_flag;

}


2.5 配置文件(修改参数-很重要)

img

参数说明:


如果电脑上有多个摄像头,可以修改配置文件里的摄像头编号,具体的数量在程序启动时会自动查询,通过打印代码输出到终端。


如果自己第一次编译运行源码,运行之后,


(1)需要将软件源码目录下的“haarcascade_frontalface_alt2.xml” 文件拷贝到C盘根目录,或者其他非中文目录下,具体路径可以在配置文件里修改,默认就是C盘根目录。


(2)需要将软件源码目录下的“OpenCV-MinGW-Build-OpenCV-3.4.7x86mingwbin”目录里所有文件拷贝到,生成的程序执行文件同级目录下。


这样才能保证程序可以正常运行。


报警温度的阀值范围,也可以自行更改,在配置文件里有说明。


2.6 语音提示文件与背景图

语音提示文件,背景图是通过资源文件加载的。


源文件存放在,源代码的“FaceTemperatureCheckres”目录下。

img

自己也可以自行替换,重新编译程序即可生效。


2.7 语音播报与图像显示处理代码

//图像处理的结果

void Widget::slot_HandleImage(bool flag,QImage image)

{

    bool temp_state=0;


    //检测到人脸

    if(flag)

    {

        //判断温度是否正常

        if(current_tempMIN_TEMP)

        {

            temp_state=true;

            //显示温度正常

            ui->label_temp->setStyleSheet("color: rgb(0, 255, 127);font: 20pt "Arial";");

            ui->label_temp->setText(QString("%1℃").arg(current_temp));

        }

        else //语音播报,温度异常

        {

            temp_state=false;

            //显示温度异常

            ui->label_temp->setStyleSheet("color: rgb(255, 0, 0);font: 20pt "Arial";");

            ui->label_temp->setText(QString("%1℃").arg(current_temp));

        }


        //获取当前ms时间

        long long currentTime = QDateTime::currentDateTime().toMSecsSinceEpoch();


        //判断时间间隔是否到达

        if(currentTime-old_currentTime>AUDIO_RATE_MS)

        {

            //更改当前时间

            old_currentTime=currentTime;

            //温度正常

            if(temp_state)

            {

                //语音播报,温度正常

                QSound::play(":/res/ok.wav");

            }

            //温度异常

            else

            {

                //语音播报,温度异常

                QSound::play(":/res/error.wav");


                //拍照留存

                QString dir_str = QCoreApplication::applicationDirPath()+"/face";


                //检查目录是否存在,若不存在则新建

                QDir dir;

                if (!dir.exists(dir_str))

                {

                    bool res = dir.mkpath(dir_str);

                    qDebug() << "新建目录状态:" << res;

                }


                //目录存在就保存图片

                QDir dir2;

[1] [2]
关键字:STM32  单片机  红外测温仪 引用地址:基于STM32单片机设计的红外测温仪(带人脸检测)

上一篇:基于STM32设计的WiFi语音播报日程表
下一篇:基于STM32+RFID设计的宿舍检修管理系统

推荐阅读最新更新时间:2024-11-12 15:29

51单片机对DS1302突发模式的读写
#include STC89C5xRC.H #include intrins.h #include DS1302.h //DS1302管脚 sbit SCLK = P3^6; //时钟 sbit CE = P3^5; //片选 sbit databus = P3^4; //双向IO //写模式寄存器 #define WRITE_CONTROL_SECONDS 0x80 //秒 //位7=1暂停 =0运行 #define WRITE_CONTROL_MINUTE 0x82 //分 #define WRITE_CONTROL_HOUR 0x84 //时 位7 1——12小时模式 0——2
[单片机]
如何让keil5可开发51系列单片机
通常,我们使用keil5开发32,keil4开发51。但这样切换版本太过繁琐,下面介绍一种让keil5兼容51程序的方法。只针对已经xx的keil5系列! 1.下载 C51相关依赖包 从官网下载 (或者使用最下面提供的链接下载!!!) 2.安装按照默认配置,点击下一步即可 3.打开keil5,新建项目,选择对应型号的51单片机 选择对应的型号,我是Atmel - 89C51 4. 完成 C51依赖:链接:https://pan.baidu.com/s/17ZxGJCl9PClXh-g4lWaeSQ 提取码:a3p4 keil5 xx:http://pan.baidu.com/s/1o8h0v5w 密码
[单片机]
如何让keil5可开发51系列<font color='red'>单片机</font>
AT系列51单片机简介
支持ISP的51 单片机 AT89S系列 ATMEL公司新推出的可在编程的MCS51兼容单片机AT89S51/52将全面替代AT89C51/52单片机。 AT89S系列单片机有以下特点: 兼容MCS51微控制器 4/8K字节FLASH存贮器支持在系统编程ISP1000次擦写 周期 128/256字节片内RAM 工作 电压 4.0V到5.5V 全静态时钟0 Hz 到33 MHz 三级程序加密 32个可编程IO口 2/3个16位定时/计数器 6/8个中断源 全双工 UART 完全的双工UART串行口 低功耗支持Idle和Power
[单片机]
单片机开发初期应该了解的几个概念
很多学习电子电路设计的朋友都会涉及到单片机的开发,网络上有很多关于单片学习开发的资料,但是这些资料当中或多或少都会涉及一些比较专业的名词和概念,电路设计初学者看不明白,学习起来也比较困难,本篇文章就对单片机开发过程中所要涉及到的几个概念进行介绍,希望能对新手有所帮助。 什么是DSP中的 内部上拉 和 内部下拉 ? DSP中介绍引脚时,注明PU,PD说是 内部上拉 和 内部下拉 ,就是说内部已经配置了接电源的上拉电阻或是接地的下拉电阻。这样,当作为输入端口连接OC或COMS芯片或浮空时。信号线平是确定的高/低电平。而不是不确定的浮地电平。内部上拉,相当于输入和电源之间接了一个几十K的电阻;下拉,相当于用电阻和地相
[单片机]
STM32GPIO的描述和配置
一、GPIO的综合描述 stm32每一个GPIO端口拥有2个32bits的configuration寄存器(GPIOx_CRL,GPIOx_CRH),2个32bits的数据寄存器(GPIOx_IDR,GPIOx_ODR),1个32bits的set/reset寄存器(GPIOx_BSRR),1个16bits的reset寄存器(GPIOx_BRR)和1个32bits的Lock寄存器(GPIOx_LCKR)。 (一)每一个IO引脚都可以使用软件配置为以下几种模式: 1. 浮空输入 2. 带上拉输入 3. 带下拉输入 4. 模拟输入 5. 开漏输出——(此模式可实现hotpower说的真双向IO) 6. 推挽
[单片机]
51单片机PS2键盘解码实验--C51源代码
#include #include KBCODE.H #define LCM_RS P2_0 #define LCM_RW P2_1 //定义LCD引脚 #define LCM_E P2_2 #define LCM_Data P0 #define Busy 0x80 //用于检测LCM状态字中的Busy标识 #define Key_Data P3_2 //定义Keyboard引脚 #define Key_CLK P3_3 void LCMInit(void); void DisplayOneChar(unsigned char X,unsigned char Y,unsigned char DData); void D
[单片机]
STM32的ISP方式和IAP方式下载程序有什么区别
都可以通过串口来下载啊 ISP方式:需要将BOOT管脚配置成上电从System Memory启动,System Memory中有一段BOOTLOADER来接收串口来的数据,把它们烧写到FLASH中。 IAP方式:是用户自己写一段烧写程序,通过ISP或者仿真器事先烧写到用户FLASH中,使用时通过某种方式触发这段程序,再来从串口接收数据,然后烧到相应的FLASH中,不需要改变BOOT管脚配置。
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved