今年的电赛给我的感觉是时间真的紧张,可能是因为去年有疫情原因影响所以能准备的时间到七月份,今年不到月底就要全部出成品。我们团队一直在自研一款增强现实眼镜,从硬件设计到软件实现全部由我和另外两个小伙伴一起完成,所以就把我们做出来的原型机的一部分拿出来改了改参赛了。
在面对如地震、飓风、洪水、火灾等突发自然灾害和事故时,光波导显示技术可以提供实时的信息和增强的感知,帮助救援人员更有效地响应紧急情况。基于增强现实的应急救援多功能头盔是一项具有挑战性的创新项目。它融合了头盔结构设计、应急救援功能的设计与实现,以及增强显示功能的设计和制作,我们的项目是《基于AR光波导显示的应急救援多功能头盔》。
一、作品原理及创新点
本项目的难点在于头盔结构设计创新和加工、 应急救援功能的设计与实现、增强显示功能的设计和制作。项目的创新之处在于用场景、硬件结构和软件系统方面。应用场景创新首次将增强现实头盔应用于应急救援,并根据实际需求进行优化。硬件结构创新采用多模态融合设计,将多种传感器集成到头盔中,实现气体检测、红外显示等功能,提供了位姿精度更高、环境适应性更强、动态性能更稳定,成本更低的多模态硬件解决方案。软件系统创新涉及双目相机和IMU多模态融合SLAM技术、三维重建、增强现实显示、视频录制和手势识别等功能的设计与实现。
二、结构介绍
1、双目相机和imu实现多模态融合
我们采用两个全局快门相机和一块IMU,IMU型号:ICM-20602进行多模态融合,通过ISP 桥接芯片进行时间同步和数据传输,输出到USB,以此整合为一个双目视觉惯性模组。
2、气体检测模块
SHT35传感器低功耗、长期稳定,无需频繁校准。SHT35传感器在应急救援中可提供快速、准确、可靠温湿度测量结果
SGP30气体传感器检测有害气体
SGP30气体传感器是一款单一芯片上具有多个传感元件的金属氧化物室内气体传感器,能够快速响应时间,能够在短时间内提供准确的测量结果。
MQ-9气体传感器所使用的气敏材料是在清洁空气中电导率较低的二氧化锡(SnO2)。
MPU6050姿态传感器是一种用于测量物体姿态的传感器,它可以检测物体的加速度和角速度,并计算出物体的方向和角度。
3、单目摄像头
DF100-720P型号的单目摄像头。该摄像头具有1/4英寸的CMOS传感器,像素尺寸为3um*3um,支持高清100万像素的工业级图像采集。
4、测温热像模组
Xmodule 系列T5-612-68非制冷测温热像模组,该模组是基于陶瓷封装非制冷氧化钒红外探测器开发的一款高性能红外热成像产品,该产品采用并行数字接口输出,控制接口丰富,可适配接入各种智能处理平台,具备高性能、低功耗、体积小、易于开发集成的特点,能够满足各类红外测温应用的二次开发需求。
三、功能演示
1、UI界面
首先进入系统,这是我们设计的UI界面,光波导会显示应急救援系统,提供用户信息,通过光学系统将虚拟信息叠加在现实世界中。
2、毒气检测
可以检测一氧化碳、二氧化碳、甲醛、甲烷和天然气气体浓度,当传感器所处环境中存在可燃气体时,传感器的电导率随空气中可燃气体浓度的增加而增大,从而会在系统中报警,保证用户安全。
3、感知定位功能
检测加速度和减速度。通过模拟不同的运动场景,如匀速、加速和减速等,生成相应的加速度和角 速度数据,并
输入到检测系统中进行实时监测和分析。可以包括不同方向上的加速度和角速度变化,以验证系统对于不同运动状态的检测能力。
4、红外显示功能
能够提供更远的探测范围,有助于救援人员在夜间或缺乏光源的场景下检测生命体迹,为救援行动提供更好的支持。
手势识别功能能够帮助佩戴者通过手势操作执行特定的程序,解放了佩戴者的双手,使其能够在需要保持双手自由的情况下进行操作,提高了操作的便利性和灵活性。
4、视频录制功能
能够帮助救援人员在救援过程中记录自己的行动过程。这样,一旦离开灾难现场,他们可以重新观察录制的视频,
以便回顾并注意到之前可能未注意到的细节。这对于总结经验教训、提高救援效率以及进行后续分析和讨论非常有帮助。通过录制整个过程,救援人员可以更好地评估自己的行动和决策,并进行必要的改进。
5、深度解算功能
可输出点云图和深度图,并保存点云信息,帮助用户进行场景重建。
6、增强现实功能
所有功能通过光波导材料叠加到现实场景,检测场景中的最佳平面与渲染虚拟模型,给用户带来身临其境的视觉体验。
import cv2
import numpy as np
import serial
import queue
import threading
import mediapipe as mp
import time
#0是单目相机,1是计算机自带相机,2是imu相机,3是红外相机
def videocapture():
cap = cv2.VideoCapture(1) # 生成读取摄像头对象
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) # 获取视频的宽度
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) # 获取视频的高度
fps = cap.get(cv2.CAP_PROP_FPS) # 获取视频的帧率
fourcc = int(cap.get(cv2.CAP_PROP_FOURCC)) # 视频的编码
# 定义视频对象输出
writer = cv2.VideoWriter("video_result.mp4", fourcc, fps, (width, height))
while cap.isOpened():
ret, frame = cap.read() # 读取摄像头画面
# frame = cv2.flip(frame, 1) # 画面反转
cv2.imshow('video', frame) # 显示画面
key = cv2.waitKey(24)
writer.write(frame) # 视频保存
# 按Q退出
if key == 27:
break
cap.release() # 释放摄像头
def show_image():
path='hollo_world.png'
cv2.namedWindow('camera', cv2.WND_PROP_FULLSCREEN) # 窗口全屏
cv2.setWindowProperty('camera', cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN) # 窗口全屏
image=cv2.imread(path, cv2.IMREAD_COLOR)
# image = np.zeros((1920, 1080, 3))
while True:
cv2.imshow('camera', image)
key = cv2.waitKey(24)
if key == 27:
break
def show_gas():
Q = queue.Queue(-1)
ser = serial.Serial()
def get_gastxt():
global flag
flag = True
ser.port = 'COM3'
ser.baudrate = 115200
ser.open()
while True:
if flag==False:
break
data_all = '' # 增加气体显示
for i in range(7):
data = ser.readline().decode('utf-8')
data_all = data_all + data
print(data_all)
Q.put(data_all)
def show_gastxt():
global data_all
global flag
data_all = ''
cv2.namedWindow('camera', cv2.WND_PROP_FULLSCREEN) # 窗口全屏
cv2.setWindowProperty('camera', cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN) # 窗口全屏
while True:
image = np.zeros((1920, 1080, 3))
try:
_data_all = Q.get_nowait()
except:
pass
else:
data_all = _data_all
if data_all:
y0, dy = 90, 90
for i, txt in enumerate(data_all.split('\n')):
y = y0 + i * dy
cv2.putText(image, txt, (20, y), cv2.FONT_HERSHEY_SIMPLEX, fontScale=1.2, color=(0, 255, 0),
thickness=3)
# 显示帧
cv2.imshow('camera', image)
key = cv2.waitKey(24)
if key == 27:
flag=False
break
t1 = threading.Thread(target=get_gastxt)
t2 = threading.Thread(target=show_gastxt)
t1.start()
t2.start()
t1.join()
t2.join()
def show_infared():
cap0 = cv2.VideoCapture(0) # 0为电脑内置摄像头
# cap0.set(cv2.CAP_PROP_FRAME_WIDTH, 1920) # 设置摄像头图像宽度
# cap0.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080) # 设置摄像头图像高度
cap0.set(cv2.CAP_PROP_BUFFERSIZE, 1)
while (True):
ret, frame0 = cap0.read() # 摄像头读取,ret为是否成功打开摄像头,true,false。 frame为视频的每一帧图像
# frame0 = cv2.flip(frame0, 1)#画面反转
# #将绿色蓝色通道设置为0
# frame0[:, :, 0] = 0
# frame0[:, :, 1] = 0
# frame0[frame0 < 80] = 0
#
cv2.namedWindow('camera', cv2.WND_PROP_FULLSCREEN) # 窗口全屏
cv2.setWindowProperty('camera', cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN) # 窗口全屏
cv2.imshow("camera", frame0)
c = cv2.waitKey(10)
if c == 27:
break
cap0.release() # 释放摄像头
#1是双目0是电脑2是单目,3是红外
def mphands():
cap = cv2.VideoCapture(1) # OpenCV摄像头调用:0=内置摄像头(笔记本) 1=USB摄像头-1 2=USB摄像头-2
cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
# 定义并引用mediapipe中的hands模块
mpHands = mp.solutions.hands
hands = mpHands.Hands()
mpDraw = mp.solutions.drawing_utils
# 帧率时间计算
pTime = 0
cTime = 0
while True:
success, img = cap.read()
# img = cv2.flip(img, 1) # 画面反转
imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # cv2图像初始化
results = hands.process(imgRGB)
# print(results.multi_hand_landmarks)
image0 = np.zeros((1920, 1080, 3))
if results.multi_hand_landmarks:
for handLms in results.multi_hand_landmarks:
# 绘制手部特征点:
mpDraw.draw_landmarks(image0, handLms, mpHands.HAND_CONNECTIONS)
'''''
视频FPS计算
'''
cTime = time.time()
fps = 1 / (cTime - pTime)
pTime = cTime
cv2.putText(image0, 'F P S : '+str(int(fps)), (10, 70), cv2.FONT_HERSHEY_PLAIN, 3,
(255, 0, 255), 3) # FPS的字号,颜色等设置
cv2.namedWindow('HandsImage', cv2.WND_PROP_FULLSCREEN) # 窗口全屏
cv2.setWindowProperty('HandsImage', cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN) # 窗口全屏
cv2.imshow("HandsImage",image0) # CV2窗体
c = cv2.waitKey(10)
if c == 27:
break
cap.release() # 释放摄像头
if __name__ == '__main__':
# videocapture()
# show_image()
# show_gas()
# show_infared()
#mphands()
四、总结
这次从硬件到软件都是我们自己设计的,硬件的元器件虽然有一些现成的,不过根据我们需要的功能又做以改进,从整个原型机的创作周期来讲真的是遇到了很多很多困难,不管对外形还是功能都在不断的改稿,一直改进我们的功能,最后的原型机其实也非常简陋,实现的功能也没有完全达到我们预期的全部,不过这个过程我们收获的更多,下一步对标Vison Pro,期待我们的新作品!加油!