使用大疆御2行业进阶版(M2EA)拍摄,得到红外照片(R-JPEG),R-JPEG照片使用大疆红外热分析工具3(DJI Thermal Analysis Tool 3)打开设置才会显示温度值,但我们需要的是照片中每个像素表示温度,而不是RGB
下面我会展示将R-JPEG图像批量转成TIF,TIF图像中每个像素的数据不再表示颜色信息,而是表示了温度,最后将TIF拼接成完整影像
系统版本:windows 10 64位
visual studio版本:2019
大疆TSDK版本:dji_thermal_sdk_v1.4_20220929
大疆智图版本:DJI Terra 4.0.1
Pix4D mapper版本:4.4.12
PyCharm版本:2023
1.在visual studio 2019中配置大疆TSDK
(1)在visual studio 2019中新建新项目(我的为TSDK),创建好C++文件(我的C++文件名为TSDK.cpp)
(2)将下载解压缩好的大疆TSDK文件夹dji_thermal_sdk_v1.4_20220929\sample路径下的dji_irp.cpp里面的所有代码复制粘贴到创建好的C++文件中,即TSDK.cpp(复制粘贴后会提示有很多错误,不用担心,后面会解决)
(3)在项目TSDK下新建名为“Libs”的文件夹,然后在Libs文件夹里面分别新建一个名为“icn”和“lib”的子文件夹(两个文件夹下面要用到)
(4)将大疆TSDK文件夹dji_thermal_sdk_v1.4_20220929\tsdk-core\api路径下的所有文件复制粘贴到icn文件夹中。同时,将dji_thermal_sdk_v1.4_20220929\sample\argparse路径下的所有文件也复制粘贴放入icn文件夹中
(5)将dji_thermal_sdk_v1.4_20220929\tsdk-core\lib\windows\release_x64路径下所有后缀为.lib的文件复制粘贴到lib文件夹中
(6)visual studio 2019 界面上方选择 Debug 和 x64 ,然后右键生成TSDK项目(点击图示2处也可以),项目生成后会在TSDK项目文件夹下会生成一个名为 x64 的文件夹
(7)将dji_thermal_sdk_v1.4_20220929\tsdk-core\lib\windows\release_x64路径下所有后缀为.dll的文件和后缀为.ini的文件复制粘贴到项目文件夹TSDK\x64\Debug路径下
(8)在TSDK项目中选择 调试 > TSDK调试属性 > C/C++ > 常规 中,将 附加包含目录 设置为 icn 文件夹
在TSDK项目中选择 调试 > TSDK调试属性 > 连接器 > 常规 中,将 附加库目录 设置为 lib 文件夹
在TSDK项目中选择 调试 > TSDK调试属性 > 连接器 > 输入 中,将 附加依赖项 设置为 libdirp.lib ,配置结束
点击 本地windows调试器 ,会在TSDK\x64\Debug文件夹下生成两个文件(TSDK.exe和TSDK.pdb),TSDK.exe在后面编写python代码的时候会用到
2.编写python代码调用TSDK
编写python代码调用TSDK.exe,批量处理红外照片(R_JPEG),生成存储温度信息的.raw文件。运行代码即可得到结果
import os
# TSDK.exe的储存位置,根据自己的情况设置
tsdk = r'F:\TSDK\x64\Debug\TSDK.exe'
# 拍摄的R_JPG的储存位置,根据自己的情况设置
path = 'M2EA/0824-1/'
# 处理结果的储存位置
save_path = 'M2EA_output/0804-1/'
os.makedirs(save_path, exist_ok=True)
# 参数根据实际情况设置
distance = 25.0
emissivity = 0.95
humidity = 45
reflection = 51.8
def use_tsdk(tsdk, path, save_path):
print('开始处理')
# 获取指定目录下所有文件名列表
imgnamelist = os.listdir(path)
for imgname in imgnamelist:
# 判断文件名中是否包含"D",以过滤掉非温度图像,你的图像文件名可能包含的是别的字母,根据自己的情况设置
if "D" in imgname:
portion = os.path.splitext(imgname)
coreimgname = portion[0]
# 构建TSDK.exe的执行参数字符串:选择的模式是measure,输出的结果是温度信息,不是原始信息
param = '-s ' + path + imgname + ' -a measure -o ' + save_path + coreimgname + '.raw' + ' --distance ' + str(
distance) + ' --emissivity ' + str(emissivity) + ' --humidity ' + str(humidity) + '--reflection ' + str(
reflection)
# 调用TSDK.exe并获取返回值
r_v = os.system(tsdk + ' ' + param)
# 输出的为tsdk.exe运行的返回值
print(r_v)
print('处理完成')
# 调用函数
use_tsdk(tsdk, path, save_path)
3.raw文件转TIF文件
将.raw文件中每个数据的值除以10以后即为温度值(即最小精度0.1℃),每个数据即是对应坐标点的测量温度值,转为.tif文件以供后续使用
import os
import cv2
import numpy as np
save_path = 'M2EA_output/0804-1/'
def raw_to_tif(path, rows, cols, channels):
"""
将指定目录下的.raw文件转换为.tif文件,并删除原始的.raw文件。
参数:
- path: 存储.raw文件的目录路径
- rows: 图像的行数
- cols: 图像的列数
- channels: 图像的通道数
注意:
- 输入的.raw文件应为16位无符号整数格式
- 转换后的.tif文件存储在与.raw文件相同的目录下,文件名与.raw文件相同,扩展名为.tif
- 转换后的.tif文件使用TIFF格式,压缩方式为LZW压缩
"""
print('开始转换为 .tif')
# 获取指定目录下所有文件名列表
files = os.listdir(path)
for file in files:
portion = os.path.splitext(file)
# 判断文件扩展名是否为.raw
if portion[1] == '.raw':
realPath = path + file
# 从.raw文件读取数据,数据类型为uint16
img = np.fromfile(realPath, dtype='uint16')
# 将数据除以10,得到温度值
img = img / 10
# 重塑数组形状为(rows, cols, channels)
img = img.reshape(rows, cols, channels)
# 构建输出.tif文件的文件名
fileName = portion[0] + '.tif'
tif_fileName = os.path.join(path, fileName)
# 使用OpenCV保存.tif文件,压缩方式为LZW压缩
cv2.imwrite(tif_fileName, img, (int(cv2.IMWRITE_TIFF_COMPRESSION), 1))
# 删除原始的.raw文件,如果不需要删除,可以注释下面这行
os.remove(realPath)
else:
print(file + ' 不是 .raw 文件')
print('转换为 .tif 完成')
# 调用函数,传入指定的参数
raw_to_tif(save_path, 512, 640, 1)
4.exif信息写入TIF文件
前面转出来的.tif文件没有exif信息,无法定位。下面将exif信息从R_JPG图像中提取出来,写入.tif文件
# 导入 Image 类,该类用于读取和修改图像的 Exif 信息
from pyexiv2 import Image
import os
# 输入的jpg路径
path = 'M2EA/0824-1/'
# 输入的tif路径
save_path = "M2EA_output/0804-1/"
def exifrw(path, exif_path):
print('exifr&w start')
# 初始化变量 i,用于记录无法处理的文件数量
i = 0
# 获取路径下的所有文件列表
files = os.listdir(path)
# 获取输出路径下的所有文件列表
read_files = os.listdir(exif_path)
# 遍历输出路径下的文件
for read_file in read_files:
# 检查文件名中是否包含 "D"
if "D" in read_file:
# 分离文件名和扩展名
portion = os.path.splitext(read_file)
# 用 ".tif" 替换 ".rjpgd" 得到对应的 ".tif" 文件名
file = portion[0] + '.tif'
# 如果对应的 ".tif" 文件存在于输入路径中
if file in files:
# 构建 ".tif" 文件的完整路径
file_path = os.path.join(path, file)
# 读取 ".tif" 文件的 Exif 信息
img = Image(file_path)
# 构建对应的 ".rjpgd" 文件的路径
exif_file = os.path.join(exif_path, read_file)
# 读取 ".rjpgd" 文件的 Exif 信息
imge = Image(exif_file)
# 获取 ".rjpgd" 文件的 Exif 信息
exif = imge.read_exif()
# 将 ".tif" 文件的 Exif 信息修改为 ".rjpgd" 文件的 Exif 信息
img.modify_exif(exif)
# 关闭 ".rjpgd" 和 ".tif" 文件
imge.close()
img.close()
# 如果对应的 ".tif" 文件不存在
else:
# 记录无法处理的文件数量
i = i + 1
# 打印未完成处理的文件名
print(str(file) + "unfinish")
# 打印处理完成的提示
print('exifr&w finish')
# 打印无法处理的文件数量
print(str(i) + " files can not be processed")
# 打印结束提示
print('end')
# 调用函数,传入输出路径和输入路径
exifrw(save_path, path)
5.提取pos信息并编辑
上面的方法处理exif信息只能读取地理信息,无法读取精度及航向角等信息(使用pix4d mapper可以查看到TIF文件里面没有这些信息),拼接的图像不准,可以用大疆智图导出pos信息,经过编辑,导入pix4D mapper
TIF文件里面没有俯仰角、翻滚角、航偏角等信息
(1)使用大疆智图导出pos信息
(2)使用python代码编辑pos信息
import os
# 输入路径,存储 pos.txt 文件的目录
path = 'post/'
# 大疆智图导出的 pos.txt 文件所在的路径
pos_path = 'post/'
# 构建 pos.txt 文件的完整路径
posread = os.path.join(pos_path, "pos.txt")
# 以 utf8 编码打开 pos.txt 文件
f = open(posread, encoding='utf8')
# 构建输出文件 posT.txt 的完整路径
poswrite = os.path.join(path, "posT.txt")
# 遍历 pos.txt 文件的每一行
for line in f:
# 判断当前行是否包含 "D"
if "D" in line:
# 获取 name 字段
i1 = line.find(",") # 获取 ',' 的索引
line1 = line[i1 - 12:i1 - 4] # 获取剩余部分
# 获取 lat 字段
line2 = line[i1 + 1:]
i2 = line2.find(",") # 获取 ',' 的索引
line3 = line2[i2 + 1:] # 获取 'lat' 字段
line2 = line2[:i2] # 截取 'lat' 字段之前的部分
# 获取 lon 字段
i3 = line3.find(",")
line4 = line3[i3 + 1:]
line3 = line3[:i3]
# 获取 altitude 字段
i4 = line4.find(",")
line5 = line4[i4 + 1:]
line4 = line4[:i4]
# 获取 yaw 字段
i5 = line5.find(",")
line6 = line5[i5 + 1:]
line5 = line5[:i5]
# 获取 pitch 字段
i6 = line6.find(",")
line7 = line6[i6 + 1:]
line6 = line6[:i6]
# 获取 roll 字段
i7 = line7.find(",")
line8 = line7[i7 + 1:]
line7 = line7[:i7]
# 获取 horizontal 字段
i8 = line8.find(",")
line9 = line8[i8 + 1:]
line8 = line8[:i8]
# 获取 vertical 字段
i9 = len(line9)
line9 = line9[:i9 - 1]
# 构建新的行字符串
line = line1 + '.tif ' + line2 + ' ' + line3 + ' ' + line4 + ' ' + line6 + ' ' + line5 + ' ' + line7 + ' ' + line8 + ' ' + line9 # for pix
# 打印新的行字符串
print(line)
# 将新的行字符串写入 posT.txt 文件
with open(poswrite, "a") as fs:
fs.write(line + "\n")
# 关闭输入文件
f.close()
(3)将TIF文件和编辑后的pos信息导入pix4D mapper,使用pix4D mapper进行图像拼接成完整的TIF
第一次处理红外照片(R_JPEG),文中不可避免地可能会有一些错误或遗漏的地方。如果有什么问题请在评论区留言
版权声明:本文为博主作者:君不见~原创文章,版权归属原作者,如果侵权,请联系我们删除!
原文链接:https://blog.csdn.net/qq_23865133/article/details/135813617