如何使用Python加载红外相机输出的特定结构dat视频文件
问题说明
需要读取红外相机拍摄生成的特定结构dat格式视频数据,此前尝试多种读取方法均触发报错,目标是将文件转换为通用格式后通过Python加载,开展后续数据分析。
此前尝试使用如下代码实现dat转csv,未成功:
import csv datContent = [i.strip().split() for i in open("./Test_s.dat",'rb').readlines()] # write it as a new CSV file with open("./Test_s.csv", "wb") as f: writer = csv.writer(f) writer.writerows(datContent)
该dat文件对应的数据结构参考:
报错原因
原有代码逻辑完全不匹配该dat的文件格式:这类红外相机导出的dat是二进制封装格式,不是按换行符分隔的文本文件,不存在可以按行拆分、按空格分割的文本结构,直接用文本读写的逻辑处理二进制字节流,必然出现解析错误、输出乱码的问题。
可行实现方案
按二进制流的结构逐段解析即可,步骤如下:
- 先解析文件头:对照给出的数据结构说明,按字节偏移读取文件开头的固定长度头信息,拿到分辨率、帧率、像素位深、总帧数这类元参数,这一步用Python内置的
struct模块实现即可。 - 循环读取帧数据:跳过文件头后,按照「单帧字节数=宽×高×单像素占用字节数」的计算结果,逐块读取字节流,直到文件末尾。红外热成像数据一般是16位无符号整数存储的灰度值,单像素占2字节。
- 转存通用格式:解析得到的帧矩阵可以直接存为numpy的npy格式(保留原始16位数据精度,适合定量分析),也可以归一化后转存为tiff序列、avi/mp4通用视频格式,后续直接用numpy、opencv、PIL库就能加载。
可直接适配的基础读取代码模板如下,只需根据实际文件的头长度、参数偏移调整配置项即可:
import numpy as np import cv2 # 以下配置项根据自己的dat文件实际参数修改 HEADER_LENGTH = 1024 # 文件头占用的总字节长度 FRAME_WIDTH = 640 # 红外帧宽度 FRAME_HEIGHT = 512 # 红外帧高度 PIXEL_DEPTH = 2 # 单像素占用字节数,16位数据对应2字节 FRAME_RATE = 25 # 采集帧率 frame_list = [] with open("./Test_s.dat", "rb") as f: # 跳过文件头 f.seek(HEADER_LENGTH) single_frame_bytes = FRAME_WIDTH * FRAME_HEIGHT * PIXEL_DEPTH # 循环读所有帧 while True: frame_bin = f.read(single_frame_bytes) if len(frame_bin) < single_frame_bytes: break # 字节流转为像素矩阵 frame_mat = np.frombuffer(frame_bin, dtype=np.uint16).reshape(FRAME_HEIGHT, FRAME_WIDTH) frame_list.append(frame_mat) # 存为npy格式,后续用np.load直接读取即可,保留原始16位精度 np.save("ir_original_data.npy", np.array(frame_list)) # 可选:转存为8位可视化avi视频,仅用于预览,定量分析请用npy原数据 video_writer = cv2.VideoWriter( "ir_preview.avi", cv2.VideoWriter_fourcc(*"XVID"), FRAME_RATE, (FRAME_WIDTH, FRAME_HEIGHT), isColor=False ) for frame in frame_list: frame_8bit = cv2.normalize(frame, None, 0, 255, cv2.NORM_MINMAX, dtype=cv2.CV_8U) video_writer.write(frame_8bit) video_writer.release()
提示:如果文件头中已经存储了分辨率、帧率、帧数参数,可以不用硬编码配置项,对照数据结构文档中标注的各参数字节偏移、数据类型,用
struct.unpack直接从头信息中读取对应值即可,适配性更强。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

