树莓派同时录制Pi Camera与FLIR USB热成像视频问题求助
树莓派野生动物监测系统热成像视频录制故障排查与修复
问题背景
开发树莓派野生动物监测系统,需求为:
- 用Raspberry Pi Camera模块循环录制20秒缓存视频,PIR检测到运动时保存前后各10秒的可见光视频
- 同时用USB迷你FLIR热成像摄像头录制对应时长的热成像视频
当前故障:通过multiprocessing+OpenCV实现热成像录制后,生成的视频文件无法打开,用VLC播放会导致崩溃甚至树莓派死机。单独运行热成像录制代码、缩短录制时长至2秒,问题仍存在。
用户提供的代码
import time from time import sleep, strftime from datetime import datetime, timedelta from picamera import PiCamera, PiCameraCircularIO from gpiozero import MotionSensor import logging from subprocess import call import cv2 from multiprocessing import Process import gz # 假设这是用户自定义的CPU温度模块 MotionDetected = False # 设置PIR传感器引脚 pir = MotionSensor(4) # 等待PIR传感器稳定 sleep(5) print('Ready!') # 设置音视频存储目录 audiopath= "/home/pi/testing/" videopath= "/home/pi/testing/" # 记录CPU温度 temp = gz.CPUTemperature().temperature # 启动可见光摄像头循环录制(20秒缓存) camera = PiCamera() camera.resolution=(1280, 720) stream = PiCameraCircularIO(camera, seconds=20) camera.start_recording(stream, format='h264') # 音频录制参数 samplerate = 250000 # Hz duration = 10 # 秒 # 保存可见光视频函数 def save_video(): logging.basicConfig(filename='NatBatVideo.log', format='%(filename)s [%(lineno)d] %(message)s', level=logging.INFO) videofilename = "Video-" + datetime.now().strftime("%d.%m.%Y-%H.%M.%S") +".h264" camera.wait_recording(10) stream.copy_to(videopath + videofilename, seconds=20) start_time = datetime.now() - timedelta(seconds=20) start = start_time.strftime('%Y-%m-%d %H-%M-%S') end_time = datetime.now() end = end_time.strftime('%Y-%m-%d %H-%M-%S') logging.info("%s ~ %s (%f) %s" %(start, end,(end_time-start_time).total_seconds(), temp)) sleep(2) # 录制音频函数 def record_audio(): audioname = audiopath +"Audio-" + strftime("%d.%m.%Y-%H.%M.%S") +".wav" soundcommand = ['rec', '-c' ,'1', '-r', '250000', audioname, 'sinc', '10k', 'silence' ,'1', '0.001', '1%', 'trim', '0', '10'] call(soundcommand) def FindTheTime(): return datetime.now() # 录制热成像视频函数 def record_thermal(): cap = cv2.VideoCapture(1) if (cap.isOpened() == False): print("The camera did not open.") frame_width = int(cap.get(3)) frame_height = int(cap.get(4)) videopath='/home/pi/testing/' duration = 10 end_time= datetime.now() + timedelta(seconds=duration) video_cod = cv2.VideoWriter_fourcc(*'XVID') video_output= cv2.VideoWriter(videopath + 'Thermal-' + datetime.now().strftime("%d.%m.%Y-%H.%M.%S") + '.avi', video_cod, 10, (frame_width,frame_height)) while datetime.now() < end_time: ret, frame = cap.read() if ret == True: video_output.write(frame) if cv2.waitKey(1) & 0xFF == ord('x'): break else: break cap.release() video_output.release() cv2.destroyAllWindows() # 主循环:PIR检测触发录制 try: while True: logging.basicConfig(filename='NatBatVideo.log', format='%(filename)s [%(lineno)d] %(message)s', level=logging.INFO) pir.wait_for_motion() print("Motion detected!") Time = FindTheTime() Process(target= save_video).start() Process(target= record_audio).start() Process(target= record_thermal).start() sleep(11) print("Video recorded.") print("Audio recorded.") print("Thermal video recorded") finally: camera.stop_recording()
修复方案与优化建议
1. 修正OpenCV视频写入参数(核心修复)
FLIR热成像摄像头的硬件特性和普通USB摄像头不同,默认参数容易不匹配:
- 强制匹配摄像头实际参数:先通过命令行查看摄像头支持的格式、分辨率和帧率:
然后在v4l2-ctl --list-formats-ext -d /dev/video1record_thermal中手动设置对应参数,示例:def record_thermal(): cap = cv2.VideoCapture(1) # 手动设置分辨率(根据摄像头支持的参数修改) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 320) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 240) # 获取摄像头实际帧率 fps = cap.get(cv2.CAP_PROP_FPS) if fps <= 0: fps = 10 # fallback值 if not cap.isOpened(): print("热成像摄像头打开失败") return # 更换更兼容的MJPG编码 video_cod = cv2.VideoWriter_fourcc(*'MJPG') timestamp = datetime.now().strftime("%d.%m.%Y-%H.%M.%S") video_output = cv2.VideoWriter( f'/home/pi/testing/Thermal-{timestamp}.avi', video_cod, fps, (320, 240) ) end_time = datetime.now() + timedelta(seconds=10) while datetime.now() < end_time: ret, frame = cap.read() if ret: video_output.write(frame) # 去掉无桌面环境下的GUI操作 time.sleep(0.01) # 降低CPU占用 else: print("读取热成像帧失败") break cap.release() video_output.release()
2. 优化多进程稳定性
- 避免在多进程中共享
picamera对象(当前代码中save_video直接使用全局camera,存在风险),可以将循环录制逻辑放在主进程,save_video仅负责复制流 - 给每个进程添加超时控制,避免进程挂起占用资源
3. 替代方案:用FFmpeg录制热成像视频
OpenCV在树莓派上对部分USB摄像头的兼容性有限,改用FFmpeg直接录制稳定性更好:
def record_thermal(): import subprocess timestamp = datetime.now().strftime("%d.%m.%Y-%H.%M.%S") output_path = f'/home/pi/testing/Thermal-{timestamp}.avi' # 替换为摄像头支持的分辨率、帧率、格式 cmd = [ 'ffmpeg', '-f', 'v4l2', '-framerate', '10', '-video_size', '320x240', '-i', '/dev/video1', '-c:v', 'mjpeg', '-t', '10', output_path ] try: subprocess.run(cmd, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) except subprocess.CalledProcessError: print("热成像视频录制失败")
4. 基础排查步骤
- 检查树莓派CPU温度:
vcgencmd measure_temp,温度超过80℃会导致硬件降频,录制异常 - 测试视频文件完整性:用
ffmpeg -i Thermal-xxx.avi查看文件是否损坏,会输出详细错误信息 - 确认USB供电:FLIR摄像头可能需要额外供电,避免USB端口功率不足
内容的提问来源于stack exchange,提问作者Tiga
相关产品推荐
相关产品推荐

