2020电赛F题回顾——简易无接触温度测量与身份识别装置

2020电赛F题回顾——简易无接触温度测量与身份识别装置

第一次参加电赛,已经大三了,这也有可能是我的最后一次,不禁感慨时间过得真快。在实验室一起奋斗的夜晚既辛苦又幸福,感谢陪伴在我身边一起做电赛的同学,同伴之间的鼓励和陪伴真的能带来巨大的动力。——谨以此纪念我的第一次电赛。

使用RT1064作为主控,用的之前的车赛板子。。。

在这里插入图片描述
不得不说逐飞的库真滴好用 ^ ^

测温传感器——MLX90614红外测温模块
在这里插入图片描述
MLX90614 系列模块是一组通用的红外测温模块。在出厂前该模块已进行校验及线性化,具有非接触、体积小、精度高,成本低等优点。被测目标温度和环境温度能通过单通道输出,并有两种输出接口,适合于汽车空调、室内暖气、家用电器、手持设备以及医疗设备应用等。MLX90614温度传感器是一个标准IIC通信协议的温度传感器。它具有体积小,成本低,易集成等优异性能。温宽范围在-40℃~+125℃,最为重要的是它的精度可达到±0.5℃,被广泛的应用于现代医疗领域。做为本设计温度传感器效果极佳。
物体红外辐射能量的大小和波长的分布与其表面温度关系密切。因此,通过对物体自身红外辐射的测量,能准确地确定其表面温度,红外测温就是利用这一原理测量温度的。红外测温器由光学系统、光电探测器、信号放大器和信号处理及输出等部分组成。
光学系统汇聚其视场内的目标红外辐射能量,视场的大小由测温仪的光学零件及其位置确定。红外能量聚焦在光电探测器上并转变为相应的电信号。该信号经过放大器和信号处理电路,并按照仪器内的算法和目标发射率校正后转变为被测目标的温度值。
PWM 的全称是 Pulse Width Modulation(脉冲宽度调制)即通过调节脉冲的周期、宽度,以达到变压、变频的目的,数字式脉宽调制方式中,数字是控制信号,通过改变高低电平数的比值达到改变占空比的目的, PWM 控制电路在开关稳压电源、不间断电源(UPS)以及直流电机调速,交流电机变频调速等控制电路中有着广泛应用。
SMBus (System Management Bus,)是 1995 年由 intel 公司提出的一种高效同步串行总线,SMBus 只有两根信号线:双向数据线和时钟信号线,容许 CPU 与各种外围接口器件以串行方式进行通信、交换信息,即可以提高传输速度也可以减小器件的资源占用,另外即使在没有SMBus 接口的单片机上也可利用软件进行模拟。
Melexis 公司生产的 MLX90614 系列测温模块是应用非常方便的红外测温装置,其所有的模块都在出厂前进行了校验,并且可以直接输出线性或准线性信号,具有很好的互换性,免去了复杂的校正过程。该模块以 81101 热电元件作为红外感应部分。输出是被测物体温度(TO)与传感器自身温度(Ta)共同作用的结果,理想情况下热电元件的输出电压为:
Vir = A(to)
其中温度单位均为 Kelvin, A 为元件的灵敏度常数。目标温度和环境温度由 81101 内置的热电偶测定测量,从 81101 中输出的两路温度信号分别经内部 MLX90302 器件上高性能、低噪声的斩波稳态放大器放大再经一个 17-bit 的模数转换器(ADC)和强大的数字信号处理(DSP)单元后输出。该系列模块的温度解析度可达 0.01°C,体积小巧,被测目标和环境温度能通过单通道(由 MLX90302 内的状态机控制)输出,有两种输出方式: PWM 输出、可编程 SMBus 输出,适于多种应用环境。
读取数据:

在这里插入图片描述

写入数据:
在这里插入图片描述

摄像头——Openmv4H7
在这里插入图片描述
OpenMV-H7是低功耗的Python3可编程机器视觉硬件,结合摄像头可以支持一系列广泛的图像处理功能和神经网络。OpenMV-H7使用跨平台 IDE 进行编程,该 IDE 允许查看摄像机的帧缓冲器、访问传感器控件、通过 USB 串行(或 WiFi/BLE(如果可用)将脚本上传到摄像机。OpenMV-H7 基板基于在 400MHz 下运行的STM32H743 MCU,具有 1MB SRAM、2MB 闪存、FPU、DSP 和硬件 JPEG 编码器。基板采用模块化传感器设计,将传感器与摄像机分离。模块化传感器设计使摄像机能够支持多个传感器,包括 OV7725、MT9V03x 全球快门传感器和 FLIR Lepton 1、2 和 3 热传感器。它的机器视觉算法包括寻找色块、边缘检测、标志跟踪等。我们可以利用其寻找色块算法进行防疫检测识别。它在本设计中可以充分发挥出非常好的作用。

电子信息专业,视觉小白,泪目了。。。

C语言部分代码

#include "headfile.h"
//串口接线 openmv: 红色线在上
//按下实行人脸识别和
#define KEY1 C25
#define KEY2 C27
//板子上左编码器处
#define KEY3 C0
#define KEY4 C1
//板子上右编码器
#define KEY5 C2
#define KEY6 C24 //温度开启按键
#define JIGUANG C3026
float temperature22;
//开关状态变量
uint8 key1_status = 1;
uint8 key2_status = 1;
//温度阈值加减
uint8 key3_status = 1;
uint8 key4_status = 1;
//进入口罩检测
uint8 key5_status = 1;
//返回人脸检测
uint8 key6_status = 1;
//上一次开关状态变量
uint8 key1_last_status;
uint8 key2_last_status;
uint8 key3_last_status;
uint8 key4_last_status;
uint8 key5_last_status; //切换到口罩追踪识别
uint8 key6_last_status; //切换回人脸追踪
//开关标志位
uint8 key1_flag;
uint8 key2_flag;
uint8 key3_flag;
uint8 key4_flag;
uint8 key5_flag;
uint8 key6_flag;
/
uint8 rec_val;27
int8 rec_display[2];
int8 temp_str[]="Temperature:";
uint8 led_flag;
uint8 temp_yuzhi=30;
uint8 buzzer_flag=1;
u8 key5_index=0;
u8 temp_key6_count=0; //1 开启测温 2 停止测温
u8 temp_start_flag=0;
int main(void)
{
DisableGlobalIRQ();
board_init();//务必保留,本函数用于初始化 MPU 时钟 调试串口
//此处编写用户代码(例如:外设初始化代码等)
oled_init();
simiic_init();
pit_init();
//串口初始化
uart_init(USART_4,115200,UART4_TX_C16,UART4_RX_C17);
gpio_init(KEY1, GPI, 0, GPIO_PIN_CONFIG);
gpio_init(KEY2, GPI, 0, GPIO_PIN_CONFIG);
gpio_init(KEY3, GPI, 0, GPIO_PIN_CONFIG);
gpio_init(KEY4, GPI, 0,GPIO_PIN_CONFIG);
gpio_init(KEY5, GPI, 0,GPIO_PIN_CONFIG);
gpio_init(KEY6, GPI, 0,GPIO_PIN_CONFIG);
//LED,BUZZER INIT
gpio_init(B9, GPO, 1, GPIO_PIN_CONFIG);28
gpio_init(B15, GPO, 1, GPIO_PIN_CONFIG);
//JIGUANG INIT
gpio_init(C30, GPO,0,GPIO_PIN_CONFIG); //不亮
oled_p6x8str(0,0,temp_str); //temperature
oled_print_chinese(96,0,16,oled_16x16_chinese[26],1); //℃
//显示报警温度阈值
oled_print_chinese(0,2,16,oled_16x16_chinese[16],5);
pit_interrupt_ms(PIT_CH0,200);
NVIC_SetPriority(PIT_IRQn,15);
//uart_putchar(USART_4,'1');
//总中断最后开启
EnableGlobalIRQ(0);
while (1)
{
oled_int16(75,3,temp_yuzhi);
//保存按键状态
key1_last_status = key1_status;
key2_last_status = key2_status;
key3_last_status = key3_status;
key4_last_status = key4_status;
key5_last_status = key5_status;
key6_last_status = key6_status;
//读取当前按键状态
key1_status = gpio_get(KEY1);
key2_status = gpio_get(KEY2);
key3_status = gpio_get(KEY3);
key4_status = gpio_get(KEY4);
key5_status = gpio_get(KEY5);
key6_status = gpio_get(KEY6);
//检测到按键按下之后 并放开置位标志位
if(key1_status && !key1_last_status) key1_flag = 1;
if(key2_status && !key2_last_status) key2_flag = 1;
if(key3_status && !key3_last_status) key3_flag = 1;
if(key4_status && !key4_last_status) key4_flag = 1;
if(key5_status && !key5_last_status) key5_flag = 1;29
if(key6_status && !key6_last_status) key6_flag = 1;
//标志位置位之后,可以使用标志位执行自己想要做的事件
//按键逻辑:
//进入人脸识别
if(key1_flag)
{
key1_flag = 0;//使用按键之后,应该清除标志位
uart_putchar(USART_4,'1');
systick_delay_ms(1000);
}
//进入人脸采集
if(key2_flag)
{
key2_flag = 0;//使用按键之后,应该清除标志位
uart_putchar(USART_4,'2');
systick_delay_ms(1000);
}
if(key3_flag)
{
key3_flag = 0;//使用按键之后,应该清除标志位
if(temp_yuzhi<46)
{
temp_yuzhi++;
}
//systick_delay_ms(1000);
}
if(key4_flag)
{
key4_flag = 0;//使用按键之后,应该清除标志位
if(temp_yuzhi>30)
{
temp_yuzhi--;
}
//systick_delay_ms(1000);
}
//进入口罩识别
if(key5_flag)
{30
key5_flag = 0;//使用按键之后,应该清除标志位
key5_index++;
uart_putchar(USART_4,'3');
if(key5_index==2) //0 口罩 1 人脸
{
key5_index=0;
}
if(key5_index==1)
{
kouzhao_flag=2;
gpio_set(B9,1);
oled_print_chinese(0,6,16,oled_16x16_chinese[66],2); // 三个空格
oled_print_chinese(32,6,16,oled_16x16_chinese[108],6); //前面空三个汉字
的显示
}
systick_delay_ms(1000);
}
if(key6_flag) //控制测温是否开启
{
key6_flag = 0;//使用按键之后,应该清除标志位
temp_key6_count++;
if(temp_key6_count==2)
{
temp_key6_count=0;
}
if(temp_key6_count==1)
{
temp_start_flag=1;
}
else
{
temp_start_flag=0;
}
systick_delay_ms(1000);
}
if(mm_flag2==1)
{
oled_print_chinese(0,4,16,oled_16x16_chinese[40],8); // 身份待识别
}
if(mm_flag2==2)
{
oled_print_chinese(0,4,16,oled_16x16_chinese[56],8); //识别失败31
}
if(kouzhao_flag==2) //未识别到口罩
{
oled_print_chinese(0,6,16,oled_16x16_chinese[66],2); // 三个空格
oled_print_chinese(32,6,16,oled_16x16_chinese[108],6); //前面空三个汉字的
显示
}
if(kouzhao_flag==1) //识别到口罩
{
oled_print_chinese(0,6,16,oled_16x16_chinese[66],3); // 三个空格
oled_print_chinese(48,6,16,oled_16x16_chinese[110],5); //前面空三个汉字的显}
// 单片机接受 openmv 发的串口数据
if(uart_query(USART_4,&rec_val))
{
rec_display[0]=rec_val;
if(rec_display[0]=='1') //任世豪
{
mm_flag2=0;
oled_print_chinese(0,4,16,oled_16x16_chinese[28],5); //识别成功:
oled_print_chinese(70,4,16,oled_16x16_chinese[0],3);
}
if(rec_display[0]=='2') //周进
{)
oled_print_chinese(0,4,16,oled_16x16_chinese[28],5); //识别成功:
oled_print_chinese(70,4,16,oled_16x16_chinese[12],2);
oled_print_chinese(102,4,16,oled_16x16_chinese[38],1);
mm_flag2=0;
}
if(rec_display[0]=='3') //伍郭成
{
oled_print_chinese(0,4,16,oled_16x16_chinese[28],5); //识别成功:
oled_print_chinese(70,4,16,oled_16x16_chinese[6],3);
mm_flag2=0;
}
if(rec_display[0]=='4') //识别失败
{
if(buzzer_flag)
{
buzzer_flag=0;32
gpio_set(B15,0);
systick_delay_ms(500);
gpio_set(B15,1);
systick_delay_ms(500);
gpio_set(B15,0);
systick_delay_ms(500);
gpio_set(B15,1); //关
systick_delay_ms(500);
}
}
if(rec_display[0]=='5') //新人员
{
oled_print_chinese(0,4,16,oled_16x16_chinese[28],5); //识别成功:
oled_print_chinese(70,4,16,oled_16x16_chinese[120],3);
mm_flag2=0;
}
if(rec_display[0]=='6') //识别失败
{
mm_flag2=2;
systick_delay_ms(1);
if(buzzer_flag)
{
gpio_set(B15,0);
systick_delay_ms(500);
gpio_set(B15,1);
systick_delay_ms(500);
gpio_set(B15,0);
systick_delay_ms(500);
gpio_set(B15,1); //关
systick_delay_ms(500);
}
}
if(rec_display[0]=='a') //口罩识别通过,,显示已佩戴口罩
{
gpio_set(B9,0);
kouzhao_flag=1;
}
if(rec_display[0]=='b') //口罩识别失败, LED 熄灭,显示未佩戴
口罩
{33
gpio_set(B9,1);
kouzhao_flag=2;
}
}
if(temp_start_flag)
{
if(temp_flag)
{
temp_flag=0;
temperature22 = MLX90614_Get_Temperature();
}
gpio_set(C30,1);
}
else
{
gpio_set(C30,0);
}
if(temperature22>=temp_yuzhi)
{
gpio_set(B9,0);
systick_delay_ms(500);
gpio_set(B9,1);
systick_delay_ms(500);
gpio_set(B15,0);
}
else
{
gpio_set(B15,1);
}
oled_printf_float(53,1,temperature22,2,3);
}
}在这里插入代码片

使用Openmv进行身份识别和口罩佩戴的判断

from pyb import millis
from math import pi, isnan
import sensor, time, image, pyb
from pyb import UART
from pyb import Servo
from pid import PID
from pyb import Servo
import os
pan_servo=Servo(1)
tilt_servo=Servo(2)
red_threshold =[(1, 74, 4, 27, 27, 8), #人脸颜色
(0, 86, -10, -128, -10, -40)]
#(0, 100, -128, 127, -128, -9)]
# #
(59, 80, -14, -74, -29, 75)] #blue
#(0, 86, -10, -128, -10, -40) 对着白墙得到的数值,下午 14:23
threshold_index = 1
#blue_threshold =(59, 80, -14, -74, -29, 75)
pan_pid = PID(p=0.07, i=0, imax=90) #脱机运行或者禁用图像传输,使用这个 PID
tilt_pid = PID(p=0.05, i=0, imax=90) #脱机运行或者禁用图像传输,使用这个 PID
NUM_SUBJECTS = 3 #图像库中不同人数,一共 6 人
import sensor, image, time
RED_LED_PIN = 1
BLUE_LED_PIN = 3
#sensor.set_vflip(True)
uart = UART(3, 115200)35
num=0
'''
def mkdir(path):
folder = os.path.exists(path)
uos.path.e
if not folder: #判断是否存在文件夹如果不存在则创建为文件夹
os.makedirs(path) #makedirs 创建文件时如果路径不存在会创建这个路径
print("--- new folder... ---")
print("--- OK ---")
else:
print("--- There is this folder! ---")
'''
class collect_face:
def collect(self):
sensor.reset() # Initialize the camera sensor.
sensor.set_pixformat(sensor.GRAYSCALE) # or sensor.GRAYSCALE
sensor.set_framesize(sensor.B128X128) # or sensor.QQVGA (or others)
sensor.set_windowing((92,112))
sensor.skip_frames(10) # Let new settings take affect.
sensor.skip_frames(time = 2000)
num = 4 #设置被拍摄者序号,第一个人的图片保存到 s1 文件夹,第二个人的
图片保存到 s2 文件夹,以此类推。每次更换拍摄者时,修改 num 值。
n = 17 #设置每个人拍摄图片数量。
#连续拍摄 n 张照片,每间隔 3s 拍摄一次。
while(n):
#红灯亮
pyb.LED(RED_LED_PIN).on()
sensor.skip_frames(time = 3000) # Give the user time to get ready.等待 3s,准备
一下表情。
#红灯灭,蓝灯亮
pyb.LED(RED_LED_PIN).off()
pyb.LED(BLUE_LED_PIN).on()
#保存截取到的图片到 SD 卡
print(n)36
sensor.snapshot().save("singtown/s%s/%s.pgm" % (num, n) ) # or "example.bmp"
(or others)
n -= 1
pyb.LED(BLUE_LED_PIN).off()
print("Done! Reset the camera to see the saved image.")
num+=1
class face_rendering:
#def __init__(self)
#self.num =0
def min(self,pmin, a, s):
if a<pmin:
pmin=a
self.num=s
return pmin
def start_face_rendering(self):
sensor.reset() # Initialize the camera sensor.
sensor.set_pixformat(sensor.GRAYSCALE) # or sensor.GRAYSCALE
sensor.set_framesize(sensor.B128X128) # or sensor.QQVGA (or others)
sensor.set_windowing((92,112))
sensor.skip_frames(10) # Let new settings take affect.
sensor.skip_frames(time = 5000) #等待 5s
s3 = Servo(3) # servo on position 1 (P7)
#将蓝灯赋值给变量 led
led = pyb.LED(3) # Red LED = 1, Green LED = 2, Blue LED = 3, IR LEDs = 4.
#SUB = "s1"
#NUM_SUBJECTS = 3 #图像库中不同人数,一共 6 人
NUM_SUBJECTS_IMGS = 17 #每人有 20 张样本图片
# 拍摄当前人脸。
img = sensor.snapshot()
#img = image.Image("singtown/%s/1.pgm"%(SUB))
d0 = img.find_lbp((0, 0, img.width(), img.height()))
#d0 为当前人脸的 lbp 特征
img = None
pmin = 999999
self.num=037
for s in range(1, NUM_SUBJECTS+1):
dist = 0
for i in range(2, NUM_SUBJECTS_IMGS+1):
img = image.Image("singtown/s%d/%d.pgm"%(s, i))
d1 = img.find_lbp((0, 0, img.width(), img.height()))
#d1 为第 s 文件夹中的第 i 张图片的 lbp 特征
dist += image.match_descriptor(d0, d1)#计算 d0 d1 即样本图像与被检测人脸
的特征差异度。
print("Average dist for subject %d: %d"%(s, dist/NUM_SUBJECTS_IMGS))
pmin = self.min(pmin, dist/NUM_SUBJECTS_IMGS, s)#特征差异度越小,被检测
人脸与此样本更相似更匹配。
print(pmin)
print(self.num) # num 为当前最匹配的人的编号。
if pmin<=6000:
if self.num==1: #任世豪
uart.write('1')
if self.num==2: #周进
uart.write('2')
if self.num==3: #伍郭成
uart.write('3')
if self.num==4:
uart.write('5') #新添加人员
#uart.write("a")
led.on() #亮灯
led1.off()
time.sleep(3500) #延时 1500ms
led.off()
else:
uart.write('6') #识别失败
t = collect_face()
y= face_rendering(0)
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)38
sensor.skip_frames(time = 2000)
#sensor.skip_frames(10) # Let new settings take affect.
sensor.set_auto_whitebal(False) # turn this off.
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
led1 = pyb.LED(1)
c= "hg"
while(1):
#sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
#sensor.skip_frames(time = 2000)
#uart.write('k')
#clock.tick()
#uart.write('2')
img = sensor.snapshot() # Take a picture and return the image.
if uart.any():
c=uart.readline()
print(c[0])
#c= '2' 接收单片机的串口信息来执行相应功能
if c[0]== 49: #'1'
print("Face recognition")
led1.on()
y.start_face_rendering()
led1.off()
if c[0]== 50: #'2'39
print("Face acquisition")
NUM_SUBJECTS+=1
t.collect()
# led.on()
if c[0]== 51: #'3' //转到人脸
print("change")
text=2
threshold_index=threshold_index+1
if threshold_index==2:
threshold_index=0
#clock.tick()
'''count=0
for i in range(1000):
img = sensor.snapshot()
blob = img.find_blobs([red_threshold[1]], area_threshold=300)
if blob:
count+=1
if count<=10:
uart.write("b")
else:
uart.write("a")'''
c="52"
blobs = img.find_blobs([red_threshold[threshold_index]],area_threshold=2500)
if blobs:
text=1
if threshold_index==1:
if text==1:
uart.write("a") #识别到口罩
max_blob = find_max(blobs)
pan_error = max_blob.cx()-img.width()/2
tilt_error = max_blob.cy()-img.height()/2
#print("pan_error: ", pan_error)
img.draw_rectangle(max_blob.rect()) # rect
img.draw_cross(max_blob.cx(), max_blob.cy()) # cx, cy
pan_output=pan_pid.get_pid(pan_error,1)/2
tilt_output=tilt_pid.get_pid(tilt_error,1)40
#print("pan_output",pan_output)
pan_servo.angle(pan_servo.angle()+pan_output)
tilt_servo.angle(tilt_servo.angle()-tilt_output)
else:
text=2
if threshold_index==1:
if text==2:
uart.write("b") #未识别到口罩
#if threshold_index==1:
#print(text)
#print(text)
#口罩判断
img = sensor.snapshot()
for blob in img.find_blobs([red_threshold[threshold_index]], pixels_threshold=200, ar
ea_threshold=2500, merge=True):
# These values depend on the blob not being circular - otherwise they will be shaky.
#if blob.elongation() > 0.5:
#img.draw_edges(blob.min_corners(), color=(255,0,0))
#img.draw_line(blob.major_axis_line(), color=(0,255,0))
#img.draw_line(blob.minor_axis_line(), color=(0,0,255))
# These values are stable all the time.
img.draw_rectangle(blob.rect())
img.draw_cross(blob.cx(), blob.cy())
# Note - the blob rotation is unique to 0-180 only.
# img.draw_keypoints([(blob.cx(), blob.cy(), int(math.degrees(blob.rotation())))], size
=20)
#print(clock.fps())
#print(blob.code())
  • 19
    点赞
  • 126
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值