赞
踩
使用大疆御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),创建好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代码的时候会用到
编写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)
将.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)
前面转出来的.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)
上面的方法处理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),文中不可避免地可能会有一些错误或遗漏的地方。如果有什么问题请在评论区留言
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。