Python——读取FLIR热像仪记录的PTW格式文件并转换为RAW格式或Numpy格式
前言
提示:在此记录一下解决这个问题的过程以供他人参考或自己未来复盘:
最近需要处理某款FLIR热像仪产生的数据,这些数据被记录为了PTW格式。然而PTW格式只有厂家自带的软件才能读取,尽管能读取但又无法转存为RAW格式或其他格式用来自己处理(能转存为ascii码保存,也许也能从这方面下手),而且该软件的处理功能又十分鸡肋,所以迫切需要自己写一个。
提示:以下是本篇文章正文内容,下面案例可供参考
一、现在有什么方法可以解决上述问题?
1. 实验室现有的ptw2raw.exe代码
个人未采纳原因:
1??数据量大时候无法处理(可能是因为内存) 2??代码不开源难以更改 3??仅仅支持Windows系统,不同设备需要用U盘把数据拷来拷去很麻烦 4??无法批量化处理 5??需要输入参数而无法自动识别
2. pyradi开源代码(我主要参考的代码)
简要介绍:
将常用的红外数据处理方式封装为工具包,以方便反复调用。其中包含有读取PTW格式文件的子函数。 ??开源地址:https://github.com/NelisW/pyradi ??文档地址:http://nelisw.github.io/pyradi-docs/_build/html/index.html
个人未采纳原因:
1??环境需要手动配置,且配置起来很麻烦 2??原生的代码存在bug,读取PTW文件的代码无法直接运行,感觉像是测试中未完成的代码直接上线了,下面给出修改办法,把报错的子函数全部改为下面的形式
原代码存在问题的部分:
def mybyte(x):
ans = ord(x)
return ans
修改办法:
def mybyte(x):
try:
ans = ord(x)
except:
ans = 0
return ans
3??可能考虑到工具箱中的函数彼此要来回调用,所以对我要实现的功能来说是一个子函数的东西被切成了许多小的子函数,逻辑看起来十分混乱,使用不便 4??在实际使用过程中256*320大小的图像1800帧需要读取16分钟,18000帧的图像五个小时读取不完,随着数据量增加所需时间指数级上升 5??进一步读源码发现数据拼接使用了动态内存分配(时间随数据指数级上升的主要原因);大量使用循环,且循环里有很多不需要循环的功能浪费了很多时间
提示:本人参考上述工具包中的读取PTW文件部分进行了大量整合更改优化,最终实现了4s读取18000帧数据;无需配置上述工具包,仅需python自带和常用的包并参考下一章给出的三段代码即可实现
3. Matlab GUI
简要介绍:
具有下面这些功能且具有图形界面,应该是需要自己下载的
- 对比度方法(绝对、运行、标准、归一化对比度)
- 微分绝对对比度(DAC)
- 插值微分绝对对比度 (IDAC)
- Skewness & kurtosis
- 匹配的过滤器
- 傅立叶变换
- 小波变换 (without the need of the wavelet toolbox)
- 主要成分热成像 (PCT)
- 热信号重建 (TSR) with derivatives
- 多尺度retinex增强
- Markov error contrast
- Thermal harmonic distortion
- Dynamic Thermal Topography
- 其他基本图像处理方法
??参考地址:https://ww2.mathworks.cn/matlabcentral/fileexchange/54032-prophetanity-thermographic-image-processing-gui?s_tid=srchtitle_tsr_40
未采纳原因
1??没开源 2??似乎也不能读PTW格式文件 3??看评论也说数据量大会崩溃
二、到底什么是PTW格式文件?
提示:我也不知道
pyradi的源码注释中写到header代表的意义参考了‘DL002U-D Altair Reference Guide’,但全网都没有搜到,只能根据源码中读取ptw_header的部分进行一个简略的倒推。
如图所示,红色部分的数据代表了整个这次拍摄的各种实验参数,比如图像长宽或总帧数各种header长度等等详细信息;而一蓝两橘代表的是某一帧的数据,其中蓝色部分代表的是该帧帧头,里面存储了当前帧的一些信息,而黄色部分代表的是图像数据,每两位代表一个像素的数值(pyradi在这里就是每次读取两位做一次转化存在大矩阵里也浪费了一些时间)
三、重新整合重构的代码
提示:改进后的代码分为两个子函数和一个主函数 ‘my read header’用来读取各种帧头的信息(几乎直接使用了pyradi的代码) ’my read frame‘用来读取所有帧数据(所有改动整合在了这里) ’my read ptw‘是主函数,如有需求可在后续加入其他功能
my read header文件(里面有些函数也没用上,但因为不参与运算所以也没删掉)
import struct
import sys
import string
def myint(x):
try:
ans = struct.unpack('h',x)[0]
except:
ans = 0
return ans
def mylong(x):
if sys.version_info[0] > 2:
ans = x[0] + (x[1]<<8) + (x[2]<<16) + (x[3]<<32)
else:
ans = ord(x[0]) + (ord(x[1])<<8) + (ord(x[2])<<16) + (ord(x[3])<<32)
return ans
def myfloat(x):
ans = struct.unpack('f',x)[0]
return ans
def mydouble(x):
ans = struct.unpack('d',x)[0]
return ans
def mybyte(x):
try:
ans = ord(x)
except:
ans = 0
return ans
def myRGB(x):
R = x[0] if sys.version_info[0] > 2 else ord(x[0])
G = x[1] if sys.version_info[0] > 2 else ord(x[1])
B = x[2] if sys.version_info[0] > 2 else ord(x[2])
ans = '#{:02x}{:02x}{:02x}'.format(R,G,B)
return ans
def terminateStrOnZero (str):
"""Iterate through string and terminate on first zero
"""
idx=0
while idx < len(str) and str[idx] != '\00':
idx += 1
return str[:idx]
def showHeader(Header):
"""Utility function to print the PTW header information to stdout
Args:
| header (class object) ptw file header structure
Returns:
| None
Raises:
| No exception is raised.
"""
print('{} version {}'.format(Header.h_Signature, Header.h_Version))
print('Main Header Size {}'.format(Header.h_MainHeaderSize))
print('Frame Header Size {}'.format(Header.h_FrameHeaderSize))
print('Frame + Frame Header Size {}'.format(Header.h_SizeOfOneFrameAndHeader))
print('Frame Size {}'.format(Header.h_SizeOfOneFrame))
print('Number of Frames {}'.format(Header.h_NumberOfFieldInFile))
print('Year {} Month {} Day {}'.format(Header.h_FileSaveYear, Header.h_FileSaveMonth,
Header.h_FileSaveDay))
print('( {} / {} / {} )'.format(str(Header.h_FileSaveYear).zfill(2),
str(Header.h_FileSaveMonth).zfill(2), str(Header.h_FileSaveDay).zfill(2)))
print('Hour {} Minute {} Second {}'.format(Header.h_FileSaveHour, Header.h_FileSaveMinute,
Header.h_FileSaveSecond))
print('( {} : {} : {} )'.format(str(Header.h_FileSaveHour).zfill(2),
str(Header.h_FileSaveMinute).zfill(2), str(Header.h_FileSaveSecond).zfill(2)))
print('Camera Name {}'.format(Header.h_CameraName))
print('Lens {}'.format(Header.h_LensName))
print('Filter {}'.format(Header.h_FilterName))
print('Aperture Name {}'.format(Header.h_ApertureName))
if Header.h_Signature == 'IRUS':
print('{}'.format(Header.h_IRUSBilletSpeed))
print('{}'.format(Header.h_IRUSBilletDiameter))
print('{}'.format(Header.h_IRUSBilletShape))
print('Emissivity {:.6f}'.format(Header.h_Emissivity))
print('Ambient Temperature {:.6f} (K)'.format(Header.h_Ambiant))
print('Ambient Temperature {:.6f} (degC)'.format(Header.h_Ambiant - 273.15))
print('Distance to target {}'.format(Header.h_Distance))
if Header.h_Signature == 'IRUS':
print('{}'.format(Header.h_IRUSInductorCoil))
print('{}'.format(Header.h_IRUSInductorPower))
print('{}'.format(Header.h_IRUSInductorVoltage))
print('{}'.format(Header.h_IRUSInductorFrequency))
print('{}'.format(Header.h_IRUSSynchronization))
print('Atm Transmission {}'.format(Header.h_AtmTransmission))
print('Ext Coef {}'.format(Header.h_ExtinctionCoeficient))
print('Target {}'.format(Header.h_Object))
print('Optic {}'.format(Header.h_Optic))
print('Atmo {}'.format(Header.h_Atmo))
print('Atm Temp {:.6f}'.format(Header.h_AtmosphereTemp))
print('Cut on Wavelength {:.6f}'.format(Header.h_CutOnWavelength))
print('Cut off Wavelength {:.6f}'.format(Header.h_CutOffWavelength))
print('PixelSize {}'.format(Header.h_PixelSize))
print('PixelPitch {}'.format(Header.h_PixelPitch))
print('Detector Apperture {}'.format(Header.h_DetectorApperture))
print('Optic Focal Length {}'.format(Header.h_OpticsFocalLength))
print('Housing Temp1 {:.6f} (K)'.format(Header.h_HousingTemperature1))
print('Housing Temp2 {:.6f} (K)'.format(Header.h_HousingTemperature2))
print('Sensor Temp4 {:.6f} (K)'.format(Header.h_sensorTemp4))
print('Detector/FPA Temp {:.6f} (K)'.format(Header.h_detectorTemp))
print('Camera Serial Number {}'.format(Header.h_CameraSerialNumber))
print('Min Threshold {}'.format(Header.h_MinimumLevelThreshold))
print('Max Threshold {}'.format(Header.h_MaximumLevelThreshold))
print('Gain {}'.format(Header.h_LockinGain))
print('Offset {}'.format(Header.h_LockinOffset))
print('HZoom {}'.format(Header.h_HorizontalZoom))
print('VZoom {}'.format(Header.h_VerticalZoom))
print('Field {}'.format(Header.h_PixelsPerLine, 'X', Header.h_LinesPerField))
print('AD converter {} bit'.format(Header.h_ADDynamic))
if Header.h_Signature == 'SATIR':
print('{}'.format(Header.h_SATIRTemporalFrameDepth))
print('{}'.format(Header.h_SATIRLocationLongitude))
print('{}'.format(Header.h_SATIRLocationLatitude))
print('{}'.format(Header.h_SATIRLocationAltitude))
if Header.h_ExternalSynch:
print('Ext Sync ON')
else:
print('Ext Sync OFF')
print('Header.h_Signature = {}'.format(Header.h_Signature))
if Header.h_Signature == 'CED':
print('CEDIP Period {:.6f} Hz'.format(1. / Header.h_CEDIPAquisitionPeriod))
print('CEDIP Integration {:.6f} msec'.format(Header.h_CEDIPIntegrationTime * 1000))
if Header.h_Signature == 'WOLF':
print('{}'.format(Header.h_WOLFSubwindowCapability))
if Header.h_Signature == 'ORI':
print('{}'.format(Header.h_ORIONIntegrationTime))
print('{}'.format(Header.h_ORIONFilterNames))
print('NUC {}'.format(Header.h_NucTable))
print('Comment {}'.format(Header.h_Comment))
print('Calibration File Name {}'.format(Header.h_CalibrationFileName))
print('Tools File Name {}'.format(Header.h_ToolsFileName))
print('Palette Index {}'.format(Header.h_PaletteIndexValid))
print('Palette Current {}'.format(Header.h_PaletteIndexCurrent))
print('Palette Toggle {}'.format(Header.h_PaletteToggle))
print('Palette AGC {}'.format(Header.h_PaletteAGC))
print('Unit Index {}'.format(Header.h_UnitIndexValid))
print('Current Unit Index {}'.format(Header.h_CurrentUnitIndex))
print('Zoom Pos {}'.format(Header.h_ZoomPosition))
print('Key Framenum {}'.format(Header.h_KeyFrameNumber))
print('Num Keyframes {}'.format(Header.h_KeyFramesInFilm))
print('Player lock {}'.format(Header.h_PlayerLocked))
print('Frame Select {}'.format(Header.h_FrameSelectionValid))
print('ROI Start {}'.format(Header.h_FrameofROIStart))
print('ROI Stop {}'.format(Header.h_FrameofROIEnd))
print('Player inf loop {}'.format(Header.h_PlayerInfinitLoop))
print('Player Init Frame {}'.format(Header.h_PlayerInitFrame))
print('Isoterm0 {}'.format(Header.h_Isoterm0Active))
print('Isoterm0 DL Min {}'.format(Header.h_Isoterm0DLMin))
print('Isoterm0 DL Max {}'.format(Header.h_Isoterm0DLMax))
print('Isoterm0 Color RGB {}'.format(Header.h_Isoterm0Color))
print('Isoterm1 {}'.format(Header.h_Isoterm1Active))
print('Isoterm1 DL Min {}'.format(Header.h_Isoterm1DLMin))
print('Isoterm1 DL Max {}'.format(Header.h_Isoterm1DLMax))
print('Isoterm1 Color RGB {}'.format(Header.h_Isoterm1Color))
print('Isoterm2 {}'.format(Header.h_Isoterm2Active))
print('Isoterm2 DL Min {}'.format(Header.h_Isoterm2DLMin))
print('Isoterm2 DL Max {}'.format(Header.h_Isoterm2DLMax))
print('Isoterm2 Color RGB {}'.format(Header.h_Isoterm2Color))
print('Zero {}'.format(Header.h_ZeroActive))
print('Zero DL {}'.format(Header.h_ZeroDL))
print('Palette Width {}'.format(Header.h_PaletteWidth))
print('PaletteF Full {}'.format(Header.h_PaletteFull))
print('PTR Frame Buffer type {}'.format(Header.h_PTRFrameBufferType))
print('Thermoelasticity {}'.format(Header.h_ThermoElasticity))
print('Demodulation {}'.format(Header.h_DemodulationFrequency))
print('Coordinate Type {}'.format(Header.h_CoordinatesType))
print('X Origin {}'.format(Header.h_CoordinatesXorigin))
print('Y Origin {}'.format(Header.h_CoordinatesYorigin))
print('Coord Show Orig {}'.format(Header.h_CoordinatesShowOrigin))
print('Axe Colour RGB {}'.format(Header.h_AxeColor))
print('Axe Size {}'.format(Header.h_AxeSize))
print('Axe Valid {}'.format(Header.h_AxeValid))
print('Distance offset {}'.format(Header.h_DistanceOffset))
print('Histogram {}'.format(Header.h_HistoEqualizationEnabled))
print('Histogram % {}'.format(Header.h_HistoEqualizationPercent))
print('Calibration File Name {}'.format(Header.h_CalibrationFileName))
print('PTRFrame Valid {}'.format(Header.h_PTRTopFrameValid))
print('Subsampling {}'.format(Header.h_SubSampling))
print('Camera flip H {}'.format(Header.h_CameraHFlip))
print('Camera flip V {}'.format(Header.h_CameraHVFlip))
print('BB Temp {}'.format(Header.h_BBTemp))
print('Capture Wheel Index {}'.format(Header.h_CaptureWheelIndex))
print('Capture Wheel Focal Index {}'.format(Header.h_CaptureFocalIndex))
class PTWFrameInfo:
"""Class to store the ptw file header information.
"""
def __init__(self):
self.FileName = ''
self.h_Signature = ''
self.h_format = 'unknown'
self.h_unit = ''
self.h_Version = ''
self.h_EofAsciiCode = 0
self.h_MainHeaderSize = 0
self.h_FrameHeaderSize = 0
self.h_SizeOfOneFrameAndHeader = 0
self.h_SizeOfOneFrame = 0
self.h_NumberOfFieldInFile = 0
self.h_CurrentFieldNumber = 0
self.h_FileSaveYear = 0
self.h_FileSaveMonth = 0
self.h_FileSaveDay = 0
self.h_FileSaveHour = 0
self.h_FileSaveMinute = 0
self.h_FileSaveSecond = 0
self.h_FileSaveCent = 0
self.h_Millieme = 0
self.h_CameraName = ''
self.h_LensName = ''
self.h_FilterName = ''
self.h_ApertureName = ''
self.h_IRUSBilletSpeed = 0
self.h_IRUSBilletDiameter = 0
self.h_IRUSBilletShape = 0
self.h_Emissivity = 0
self.h_Ambiant = 0
self.h_Distance = 0
self.h_IRUSInductorCoil = 0
self.h_IRUSInductorPower = 0
self.h_IRUSInductorVoltage = 0
self.h_IRUSInductorFrequency = 0
self.h_IRUSSynchronization = 0
self.h_AtmTransmission = 0
self.h_ExtinctionCoeficient = 0
self.h_Object = 0
self.h_Optic = 0
self.h_Atmo = 0
self.h_AtmosphereTemp = 0
self.h_CutOnWavelength = 0
self.h_CutOffWavelength = 0
self.h_PixelSize = 0
self.h_PixelPitch = 0
self.h_DetectorApperture = 0
self.h_OpticsFocalLength = 0
self.h_HousingTemperature1 = 0
self.h_HousingTemperature2 = 0
self.h_CameraSerialNumber = ''
self.h_MinimumLevelThreshold = 0
self.h_MaximumLevelThreshold = 0
self.h_EchelleSpecial = 0
self.h_EchelleUnit = 0
self.h_EchelleValue = 0
self.h_Units = ''
self.h_Lockin = 0
self.h_LockinGain = 0
self.h_LockinOffset = 0
self.h_HorizontalZoom = 0
self.h_VerticalZoom = 0
self.h_PixelsPerLine = 0
self.h_LinesPerField = 0
self.h_Rows = 0
self.h_Cols = 0
self.h_framepointer = 1
self.h_firstframe = 1
self.h_cliprect = [0, 0, 1, 1]
self.h_lastframe = 0
self.h_FrameSize = 0
self.h_ADDynamic = 0
self.h_SATIRTemporalFrameDepth = 0
self.h_SATIRLocationLongitude = 0
self.h_SATIRLocationLatitude = 0
self.h_SATIRLocationAltitude = 0
self.h_ExternalSynch = 0
self.h_CEDIPAquisitionPeriod = 0
self.h_CEDIPIntegrationTime = 0
self.h_WOLFSubwindowCapability = 0
self.h_ORIONIntegrationTime = 0
self.h_ORIONFilterNames = ''
self.h_NucTable = 0
self.h_Reserve6 = ''
self.h_Comment = ''
self.h_CalibrationFileName = ''
self.h_ToolsFileName = ''
self.h_PaletteIndexValid = 0
self.h_PaletteIndexCurrent = 0
self.h_PaletteToggle = 0
self.h_PaletteAGC = 0
self.h_UnitIndexValid = 0
self.h_CurrentUnitIndex = 0
self.h_ZoomPosition = 0
self.h_KeyFrameNumber = 0
self.h_KeyFramesInFilm = 0
self.h_PlayerLocked = 0
self.h_FrameSelectionValid = 0
self.h_FrameofROIStart = 0
self.h_FrameofROIEnd = 0
self.h_PlayerLockedROI = 0
self.h_PlayerInfinitLoop = 0
self.h_PlayerInitFrame = 0
self.h_Isoterm0Active = 0
self.h_Isoterm0DLMin = 0
self.h_Isoterm0DLMax = 0
self.h_Isoterm0Color = 0
self.h_Isoterm1Active = 0
self.h_Isoterm1DLMin = 0
self.h_Isoterm1DLMax = 0
self.h_Isoterm1Color = 0
self.h_Isoterm2Active = 0
self.h_Isoterm2DLMin = 0
self.h_Isoterm2DLMax = 0
self.h_Isoterm2Color = 0
self.h_ZeroActive = 0
self.h_ZeroDL = 0
self.h_PaletteWidth = 0
self.h_PaletteFull = 0
self.h_PTRFrameBufferType = 0
self.h_ThermoElasticity = 0
self.h_DemodulationFrequency = 0
self.h_CoordinatesType = 0
self.h_CoordinatesXorigin = 0
self.h_CoordinatesYorigin = 0
self.h_CoordinatesShowOrigin = 0
self.h_AxeColor = 0
self.h_AxeSize = 0
self.h_AxeValid = 0
self.h_DistanceOffset = 0
self.h_HistoEqualizationEnabled = 0
self.h_HistoEqualizationPercent = 0
self.h_CalibrationFileName = ''
self.h_PTRTopFrameValid = 0
self.h_SubSampling = 0
self.h_CameraHFlip = 0
self.h_CameraHVFlip = 0
self.h_BBTemp = 0
self.h_CaptureWheelIndex = 0
self.h_CaptureFocalIndex = 0
self.h_Reserved7 = ''
self.h_Reserved8 = ''
self.h_Framatone = 0
self.data = []
self.minval = 0
self.maxval = 0
self.h_frameMinute = 0
self.h_frameHour = 0
self.h_frameSecond = 0
self.h_detectorTemp = 0.0
self.h_sensorTemp4 = 0.0
def readPTWHeader(ptwfilename):
"""Given a ptw filename, read the header and return the header to caller
Args:
| filename (string) with full path to the ptw file.
Returns:
| Header (class) containing all PTW header information.
Raises:
| No exception is raised.
Reference:
h_variables of the header and byte positions are obtained
from DL002U-D Altair Reference Guide
"""
headerinfo = ''
Header = PTWFrameInfo()
Header.FileName = ptwfilename
fid = open(ptwfilename, 'rb')
headerinfo = fid.read(16)
fid.close()
MainHeaderSize = mylong(headerinfo[11:15])
fid = open(ptwfilename, 'rb')
headerinfo = fid.read(MainHeaderSize)
if sys.version_info[0] > 2:
Header.h_Signature = headerinfo[0:3].decode('utf-8')
else:
Header.h_Signature = headerinfo[0:3]
if Header.h_Signature == 'AIO':
Header.h_format = 'agema'
elif Header.h_Signature == 'CED':
Header.h_format = 'cedip'
Header.h_unit = 'dl'
if sys.version_info[0] > 2:
Header.h_Version = headerinfo[5:10].decode('utf-8')
else:
Header.h_Version = headerinfo[5:10]
if not Header.h_Version[-1] in string.printable:
Header.h_Version = Header.h_Version[:-1]
Header.h_EofAsciiCode = mybyte(headerinfo[10:11])
Header.h_MainHeaderSize = mylong(headerinfo[11:15])
Header.h_FrameHeaderSize = mylong(headerinfo[15:19])
Header.h_SizeOfOneFrameAndHeader = mylong(headerinfo[19:23])
Header.h_SizeOfOneFrame = mylong(headerinfo[23:27])
Header.h_NumberOfFieldInFile = mylong(headerinfo[27:31])
Header.h_CurrentFieldNumber = mylong(headerinfo[31:35])
Header.h_FileSaveYear = myint(headerinfo[35:37])
Header.h_FileSaveDay = ord(headerinfo[37:38])
Header.h_FileSaveMonth = ord(headerinfo[38:39])
Header.h_FileSaveMinute = ord(headerinfo[39:40])
Header.h_FileSaveHour = ord(headerinfo[40:41])
Header.h_FileSaveCent = ord(headerinfo[41:42])
Header.h_FileSaveSecond = ord(headerinfo[42:43])
Header.h_Millieme = ord(headerinfo[43:44])
if sys.version_info[0] > 2:
stripchar = terminateStrOnZero(headerinfo[44:64]).decode('utf-8')[-1]
Header.h_CameraName = terminateStrOnZero(headerinfo[44:64]).decode('utf-8').rstrip(stripchar)
Header.h_LensName = terminateStrOnZero(headerinfo[64:84]).decode('utf-8').rstrip(stripchar)
Header.h_FilterName = terminateStrOnZero(headerinfo[84:104]).decode('utf-8').rstrip(stripchar)
Header.h_ApertureName = terminateStrOnZero(headerinfo[104:124]).decode('utf-8').rstrip(stripchar)
else:
Header.h_CameraName = terminateStrOnZero(headerinfo[44:64])
Header.h_LensName = terminateStrOnZero(headerinfo[64:84])
Header.h_FilterName = terminateStrOnZero(headerinfo[84:104])
Header.h_ApertureName = terminateStrOnZero(headerinfo[104:124])
Header.h_IRUSBilletSpeed = myfloat(headerinfo[124:128])
Header.h_IRUSBilletDiameter = myfloat(headerinfo[128:132])
Header.h_IRUSBilletShape = myint(headerinfo[132:134])
Header.h_Reserved134 = mybyte(headerinfo[134:141])
Header.h_Emissivity = myfloat(headerinfo[141:145])
Header.h_Ambiant = myfloat(headerinfo[145:149])
Header.h_Distance = myfloat(headerinfo[149:153])
Header.h_IRUSInductorCoil = ord(headerinfo[153:154])
Header.h_IRUSInductorPower = mylong(headerinfo[154:158])
Header.h_IRUSInductorVoltage = myint(headerinfo[158:160])
Header.h_IRUSInductorFrequency = mylong(headerinfo[160:164])
Header.h_Reserved164 = mybyte(headerinfo[164:169])
Header.h_IRUSSynchronization = ord(headerinfo[169:170])
Header.h_AtmTransmission = myfloat(headerinfo[170:174])
Header.h_ExtinctionCoeficient = myfloat(headerinfo[174:178])
Header.h_Object = myint(headerinfo[178:180])
Header.h_Optic = myint(headerinfo[180:182])
Header.h_Atmo = myint(headerinfo[182:184])
Header.h_AtmosphereTemp = myfloat(headerinfo[184:188])
Header.h_CutOnWavelength = myfloat(headerinfo[188:192])
Header.h_CutOffWavelength = myfloat(headerinfo[192:196])
Header.h_PixelSize = myfloat(headerinfo[196:200])
Header.h_PixelPitch = myfloat(headerinfo[200:204])
Header.h_DetectorApperture = myfloat(headerinfo[204:208])
Header.h_OpticsFocalLength = myfloat(headerinfo[208:212])
Header.h_HousingTemperature1 = myfloat(headerinfo[212:216])
Header.h_HousingTemperature2 = myfloat(headerinfo[216:220])
if sys.version_info[0] > 2:
stripchar = terminateStrOnZero(headerinfo[220:231]).decode('utf-8')[-1]
Header.h_CameraSerialNumber = terminateStrOnZero(headerinfo[220:231]).decode('utf-8').rstrip(stripchar)
else:
Header.h_CameraSerialNumber = terminateStrOnZero(headerinfo[220:231])
Header.h_Reserved231 = mybyte(headerinfo[231:239])
Header.h_DetectorCode = myint(headerinfo[239:243])
Header.h_DetectorGain = myint(headerinfo[245:247])
Header.h_MinimumLevelThreshold = myint(headerinfo[245:247])
Header.h_MaximumLevelThreshold = myint(headerinfo[247:249])
Header.h_EchelleSpecial = myint(headerinfo[277:279])
Header.h_EchelleUnit = headerinfo[279:289]
Header.h_EchelleValue = headerinfo[289:357]
if (Header.h_EchelleSpecial == 0):
Header.h_Units = 'dl'
else:
Header.h_Units = Header.h_EchelleUnit
Header.h_LockinGain = myfloat(headerinfo[357:361])
Header.h_LockinOffset = myfloat(headerinfo[361:365])
Header.h_HorizontalZoom = myfloat(headerinfo[365:369])
Header.h_VerticalZoom = myfloat(headerinfo[369:373])
Header.h_PixelsPerLine = myint(headerinfo[377:379])
Header.h_LinesPerField = myint(headerinfo[379:381])
if Header.h_LinesPerField == 0:
Header.h_LinesPerField = 128
if Header.h_PixelsPerLine == 0:
Header.h_PixelsPerLine = 128
Header.h_Rows = Header.h_LinesPerField
Header.h_Cols = Header.h_PixelsPerLine
Header.h_cliprect = [0, 0, Header.h_Cols - 1, Header.h_Rows - 1]
Header.h_lastframe = Header.h_NumberOfFieldInFile
Header.h_FrameSize = Header.h_FrameHeaderSize + Header.h_Cols * Header.h_Rows * 2
Header.h_ADDynamic = myint(headerinfo[381:383])
Header.h_SATIRTemporalFrameDepth = myint(headerinfo[383:385])
Header.h_SATIRLocationLongitude = myfloat(headerinfo[385:389])
Header.h_SATIRLocationLatitude = myfloat(headerinfo[389:393])
Header.h_SATIRLocationAltitude = myfloat(headerinfo[393:397])
if sys.version_info[0] > 2:
Header.h_ExternalSynch = headerinfo[397]
else:
Header.h_ExternalSynch = ord(headerinfo[397])
Header.h_CEDIPAquisitionPeriod = myfloat(headerinfo[403:407])
Header.h_CEDIPIntegrationTime = myfloat(headerinfo[407:411])
Header.h_WOLFSubwindowCapability = myint(headerinfo[411:413])
Header.h_ORIONIntegrationTime = headerinfo[413:437]
Header.h_ORIONFilterNames = headerinfo[437:557]
Header.h_NucTable = myint(headerinfo[557:559])
Header.h_Reserve6 = headerinfo[559:563]
if sys.version_info[0] > 2:
stripchar = terminateStrOnZero(headerinfo[563:1563]).decode('utf-8')[-1]
Header.h_Comment = terminateStrOnZero(headerinfo[563:1563]).decode('utf-8').rstrip(stripchar)
stripchar = terminateStrOnZero(headerinfo[1563:1663]).decode('utf-8')[-1]
Header.h_CalibrationFileName = terminateStrOnZero(headerinfo[1563:1663]).decode('utf-8').rstrip(stripchar)
stripchar = terminateStrOnZero(headerinfo[1663:1919]).decode('utf-8')[-1]
Header.h_ToolsFileName = terminateStrOnZero(headerinfo[1663:1919]).decode('utf-8').rstrip(stripchar)
else:
Header.h_Comment = terminateStrOnZero(headerinfo[563:1563])
Header.h_CalibrationFileName = terminateStrOnZero(headerinfo[1563:1663])
Header.h_ToolsFileName = terminateStrOnZero(headerinfo[1663:1919])
Header.h_PaletteIndexValid = ord(headerinfo[1919:1920])
Header.h_PaletteIndexCurrent = myint(headerinfo[1920:1922])
Header.h_PaletteToggle = ord(headerinfo[1922:1923])
Header.h_PaletteAGC = ord(headerinfo[1923:1924])
Header.h_UnitIndexValid = ord(headerinfo[1924:1925])
Header.h_CurrentUnitIndex = myint(headerinfo[1925:1927])
if sys.version_info[0] > 2:
stripchar = terminateStrOnZero(headerinfo[1927:1935]).decode('utf-8')[-1]
Header.h_ZoomPosition = terminateStrOnZero(headerinfo[1927:1935]).decode('utf-8').rstrip(
stripchar)
Header.h_KeyFramesInFilm = terminateStrOnZero(headerinfo[1936:2056]).decode('utf-8').rstrip(
stripchar)
else:
Header.h_ZoomPosition = terminateStrOnZero(headerinfo[1927:1935])
Header.h_KeyFramesInFilm = terminateStrOnZero(headerinfo[1936:2056])
Header.h_KeyFrameNumber = ord(headerinfo[1935:1936])
Header.h_PlayerLocked = ord(headerinfo[2056:2057])
Header.h_FrameSelectionValid = ord(headerinfo[2057:2058])
Header.h_FrameofROIStart = mylong(headerinfo[2058:2062])
Header.h_FrameofROIEnd = mylong(headerinfo[2062:2066])
Header.h_PlayerLockedROI = ord(headerinfo[2066:2067])
Header.h_PlayerInfinitLoop = ord(headerinfo[2067:2068])
Header.h_PlayerInitFrame = mylong(headerinfo[2068:2072])
Header.h_Isoterm0Active = ord(headerinfo[2072:2073])
Header.h_Isoterm0DLMin = myint(headerinfo[2073:2075])
Header.h_Isoterm0DLMax = myint(headerinfo[2075:2077])
Header.h_Isoterm0Color = myRGB(headerinfo[2077:2081])
Header.h_Isoterm1Active = ord(headerinfo[2081:2082])
Header.h_Isoterm1DLMin = myint(headerinfo[2082:2084])
Header.h_Isoterm1DLMax = myint(headerinfo[2084:2086])
Header.h_Isoterm1Color = myRGB(headerinfo[2086:2090])
Header.h_Isoterm2Active = ord(headerinfo[2090:2091])
Header.h_Isoterm2DLMin = myint(headerinfo[2091:2093])
Header.h_Isoterm2DLMax = myint(headerinfo[2093:2095])
Header.h_Isoterm2Color = myRGB(headerinfo[2095:2099])
Header.h_ZeroActive = ord(headerinfo[2099:2100])
Header.h_ZeroDL = myint(headerinfo[2100:2102])
Header.h_PaletteWidth = myint(headerinfo[2102:2104])
Header.h_PaletteFull = ord(headerinfo[2104:2105])
Header.h_PTRFrameBufferType = ord(headerinfo[2105:2106])
Header.h_ThermoElasticity = mydouble(headerinfo[2106:2114])
Header.h_DemodulationFrequency = myfloat(headerinfo[2114:2118])
Header.h_CoordinatesType = mylong(headerinfo[2118:2122])
Header.h_CoordinatesXorigin = mylong(headerinfo[2122:2126])
Header.h_CoordinatesYorigin = mylong(headerinfo[2126:2130])
Header.h_CoordinatesShowOrigin = ord(headerinfo[2130:2131])
Header.h_AxeColor = myRGB(headerinfo[2131:2135])
Header.h_AxeSize = mylong(headerinfo[2135:2139])
Header.h_AxeValid = ord(headerinfo[2139:2140])
Header.h_DistanceOffset = myfloat(headerinfo[2140:2144])
Header.h_HistoEqualizationEnabled = ord(headerinfo[2144:2145])
Header.h_HistoEqualizationPercent = myint(headerinfo[2145:2147])
if sys.version_info[0] > 2:
stripchar = terminateStrOnZero(headerinfo[2147:2403]).decode('utf-8')[-1]
Header.h_CalibrationFileName = terminateStrOnZero(headerinfo[2147:2403]).decode('utf-8').rstrip(stripchar)
else:
Header.h_CalibrationFileName = terminateStrOnZero(headerinfo[2147:2403])
Header.h_PTRTopFrameValid = ord(headerinfo[2403:2404])
Header.h_SubSampling = mylong(headerinfo[2404:2408])
Header.h_CameraHFlip = ord(headerinfo[2408:2409])
Header.h_CameraHVFlip = ord(headerinfo[2409:2410])
Header.h_BBTemp = myfloat(headerinfo[2410:2414])
Header.h_CaptureWheelIndex = ord(headerinfo[2414:2415])
Header.h_CaptureFocalIndex = ord(headerinfo[2415:2416])
Header.h_Reserved7 = headerinfo[2416:3028]
Header.h_Reserved8 = headerinfo[3028:3076]
Header.h_Framatone = ord(headerinfo[3076:3077])
fid.seek(Header.h_MainHeaderSize, 0)
fid.seek(Header.h_FrameHeaderSize, 1)
firstline = fid.read(Header.h_Cols)
if (firstline[1:4] == [1220, 3907, 1204, 2382]):
Header.h_Lockin = 1
Header.h_Rows = Header.h_Rows - 1
print('* LOCKIN')
else:
Header.h_Lockin = 0
fid.close()
return Header
myreadframe文件
from myreadhead import myint
import numpy as np
from tqdm import tqdm
def GetPTWFrameFromFile(header):
errorresult = np.asarray([0])
if header.h_format!='cedip':
print('ReadJade Error: file format is not supported')
return errorresult
frameNunber = header.h_NumberOfFieldInFile
rows = header.h_Rows
cols = header.h_Cols
dataAll = np.eye(frameNunber*rows, cols)
dataAll = dataAll.reshape(frameNunber, rows, cols)
fid = open(header.FileName,'rb')
fid.seek (header.h_MainHeaderSize,0)
for i in tqdm(range(frameNunber)):
fid.seek(header.h_FrameHeaderSize, 1)
bytesdata = fid.read(2 * cols * rows)
header.data = np.frombuffer(bytesdata, dtype=np.uint16).reshape(cols, rows,order='F')
if(header.h_Lockin):
fid.seek (2*header.h_Cols,1)
if(header.h_EchelleSpecial):
low = min(header.h_EchelleScaleValue)
high = max(header.h_EchelleScaleValue)
header.data = header.data * (high-low)/ 2.0**16 + low
header.data = header.data.conj().transpose()
dataAll[i, :, :] = header.data
fid.close()
return dataAll
import myreadhead as ryptw
import myreadframe as ryfrm
from matplotlib import pyplot as plt
import numpy as np
from scipy import io
header = ryptw.readPTWHeader('cap1.ptw')
ryptw.showHeader(header)
data_all = ryfrm.GetPTWFrameFromFile(header)
print(data_all.shape)
np.save("cap1.npy", data_all)
data_all.astype(np.uint16)
data_all.tofile('cap1.raw')
import numpy as np
from scipy import io
io.savemat('cap1.mat', {'ndarray': data_all})
plt.imshow(data_all[22])
plt.show()
功能
1??仅需要输入ptw文件位置和输出文件要保存的位置即可无脑转换为raw 2??热像仪后面插了其他线的lockin模式也什么都不用管 无脑转
TODO
后续可能会把需要用到的处理数据的功能写进主函数里。
|