1. 先解决一个很多人绕不开的问题:R-JPEG到底“特殊”在哪
我第一次拿到大疆H20T飞回来的数据时,也愣了一下:存储卡里全是带.RJPG后缀的文件,而不是常见的.JPG或.TIFF。电脑自带看图器能打开,但颜色诡异得像一张被压缩过度的夜景图;扔进Pix4D mapper,软件的传感器库直接弹了一个“Unknown camera model”的提示。那一瞬间就知道,这次外业拷回来的不是普通的照片,而是夹杂了辐射温度信息的“混合体”。
R-JPEG(Radiance JPEG)是DJI热成像相机专用的一种图像封装格式。它之所以不直接输出一个大家都认得的16位TIFF温度矩阵,是因为红外人眼不可见,工程上必须让人能快速看到画面、又能让软件准确读到每个像素的温度值,于是DJI在普通JPEG的底层加了一层私有数据,并在EXIF/XMP区域写了大量辐射定标参数。通俗点说,一张R-JPEG里同时住了两个灵魂:一个是用伪彩渲染过的8位可视化图像,一个是原始辐射温度数据。
1.1 16位数据通道里,温度和“伪彩颜色”是怎么共存的
大疆红外相机输出的R-JPEG,每个像素实际对应一个16位的原始值,这个值不是随意排列的。根据DJI Thermal SDK公开的资料,可以按位段拆解:
| 位段 | 内容 | 说明 |
|---|---|---|
| bit 0 - bit 13 | 辐射温度码值 | 温度分辨率0.04°C,数值本身对应开尔文温标的某种线性映射 |
| bit 14 | 调色板/伪彩索引 | 记录当前设备设置的是白热、黑热还是铁红等模式 |
| bit 15 | 像素有效性标记 | 用于标记坏点或无效像素,处理时通常要忽略 |
| 高8位(第16位以上) | 伪彩亮度映射 | 专门供普通看图软件显示的8位亮度图 |
也就是说,你在电脑上看到的伪彩图,只是高8位的那一层;真正的温度数据,被压在低14位里。如果用普通看图软件把它另存为JPG或PNG,低位温度信息和XMP里的定标参数会被直接丢弃,再拿去Pix4D mapper拼接,处理出来的只是一张没有物理意义的“热像风格图”,温度热图就更无从谈起。
很多人踩的第一个坑就在这里:拿到R-JPEG以后,习惯性地用ACDSee或Photoshop批量转成普通JPG,再导入Pix4D。结果跑出来的正射图确实有颜色梯度,但你在某一点上查到的“温度”,实际只是伪彩灰度值,既不是摄氏度也不是华氏度,等于整批数据作废。
1.2 大疆TSDK在整条处理链路里扮演的角色
大疆TSDK(Thermal SDK,注意不是行业里常说的飞行控制SDK)是DJI官方提供的一套温度解析库,支持C++和Python绑定,主要解决一件事情:把R-JPEG里的原始码值换算成真实温度,并允许开发者导出CSV、16位TIFF等更通用的数据格式。
在生成红外正射影像这条链路里,TSDK的位置很关键:
- 它可以批量读取R-JPEG里的辐射温度码值;
- 通过XMP中的普朗克定标系数(Planck方程参数)把码值换算成绝对温度;
- 输出带坐标信息或可直接导入Pix4D mapper的TIFF文件;
- 输出任意点、区域(圆形/矩形)的最高温、最低温、平均温等统计数据。
但TSDK只做“读懂温度”这个层面的工作,它不会帮你做空三解算,也不会把几十上百张红外图拼成正射影像。正射拼接和温度图层生成,最终还是要交给Pix4D mapper这种摄影测量软件。所以完整技术路线是:R-JPEG原始数据 → TSDK批量解析/转换(可选,但推荐) → Pix4D mapper重建 → 温度热图渲染与交付。
1.3 为什么不建议直接拿普通JPEG流程去拼红外图
红外影像和可见光影像在拼接算法上最大的区别在于“纹理”。可见光照片里大家找特征点靠的是墙角、窗户、树影这些高对比区域,而热红外图像里,同一块柏油路面、同一片草地,温度差异往往只有1~2°C,在伪彩图上可能只有几个灰度级差。Pix4D mapper的特征点提取算法在8位伪彩图上能提取到的稳定特征点数量,会明显少于同场景可见光影像。
所以专业做法是:要么给Pix4D mapper直接喂R-JPEG格式,让它利用原始温度信息辅助匹配;要么先通过TSDK把温度图导出成高动态范围的16位TIFF,再用Pix4D的“热成像”处理模板去跑。两种方式我都实测过,单论最终温度正射的准确度,TSDK预处理后再进Pix4D会更稳定,因为温度值经过了官方库的辐射定标,而不是依赖第三方软件自己的解析逻辑。
2. 外业采集:先拿到一批“温度上可靠”的R-JPEG
很多人把重心放在后处理软件上,却忽略了外业采集阶段对温度数据质量的影响。红外测绘有一个特点:原始数据一旦没拍好,后期无论怎么调参都救不回来,因为辐射信息已经不准了。
2.1 航线设计:重叠率不能照抄可见光那套
飞行高度和地面分辨率(GSD)之间有一个基本公式:GSD =(传感器像元尺寸 × 飞行高度)/ 镜头焦距。
红外传感器像元尺寸通常比可见光的大,比如Mavic 2 Enterprise Advanced的热成像相机是640×512分辨率,视场角相对较窄。相同飞行高度下,红外影像的GSD比配套的4/3英寸可见光相机大不少。这意味着如果航线是按可见光相机的GSD设计的,红外相机的地面覆盖范围会更小,重叠度可能不够。
我的建议是:
- 航向重叠度:至少80%,复杂场景上到85%;
- 旁向重叠度:75%以上,地形起伏大的区域建议提高到80%;
- 飞行高度:按红外GSD需求反推,GSD尽量控制在5~10cm/pixel之间,太稀疏会导致后期温度图上细节严重丢失。
红外图像弱的纹理特性决定了它对重叠度非常敏感。重叠度不足时,Pix4D mapper就算强行跑出正射,接边处也容易出现错位、重影,温度信息在这些地方会出现明显跳变。
2.2 快门设置:别让自动曝光毁了整批温度
红外相机成像时,辐射温度数据本身和曝光参数是解耦的,但伪彩显示层会受自动增益控制(AGC)影响。简单来说,设备为了让你在屏幕上能看到清晰画面,会自动调整灰度拉伸范围,这会导致同一目标在画面里的“颜色”随周围环境变化,但低位温度值不会变。
拍摄时需要注意:
- 有手动模式的机型,把热成像切换到手动增益或锁定增益;
- 如果使用全自动模式,尽量保证每一架次拍摄场景温差不要太剧烈,避免个别画面自动拉伸后伪彩差异巨大,给后续特征匹配制造额外干扰;
- 关闭不必要的数码变焦,数码变焦会明显降低热成像的有效分辨率。
2.3 起飞前必须做的“温度校准”动作
红外相机传感器和可见光CMOS不一样,它受温度漂移影响更大。无人机在停机坪放了半小时,电池装上后相机核心温度会慢慢升高,这时候直接起飞拍出来的第一批照片,整体温度读数可能比真实值高或低好几度。
我习惯的做法是:开机上电后,至少等待3~5分钟,让红外传感器完成预热和一次自动快门校正(NUC)。如果条件允许,起飞前在空中悬停状态下再触发一次快门校正,确认画面里没有突然出现的竖条纹和固定图案噪声,再正式进入航线。这一步我在多次红外巡检项目中验证过,能显著减少批次内温度不一致的问题。
3. 用TSDK把R-JPEG批量“翻译”成温度数据
不同人拿到R-JPEG以后走的路不一样。如果你用的是Pix4Dmapper 4.5.6以上版本,它已经内置了对DJI热红外R-JPEG的解析能力,可以直接把R-JPEG拖进去跑。但在工业交付项目中,我还是建议先用TSDK做一遍辐射定标与转换,一来是为了排除软件版本差异带来的解析偏差,二来是可以提前发现坏帧、温度异常帧。
3.1 搭建TSDK解析环境
大疆TSDK支持Windows和Linux,官方提供C++库和Python绑定。常规做法是在Python环境下安装dji_thermal_sdk相关包,具体安装命令用pip即可,不同版本的SDK对应的安装包名略有差异,以官方发布页为准。
安装完成后,可以先用单张R-JPEG试一下能不能正确解析:
from dji_thermal_sdk import RJPEG rjpeg = RJPEG("DJI_0001.RJPG") print(rjpeg.get_sensor_temperature()) # 传感器温度 print(rjpeg.get_emissivity()) # 发射率 print(rjpeg.get_reflected_temperature()) # 反射温度运行成功,说明环境和SDK版本没问题,可以进入批量阶段。如果SDK报“file format not supported”,先检查文件后缀是.RJPG还是被系统改名成了.jpg,另外确认下载的SDK版本对应你使用的相机型号。
3.2 批量导出温度矩阵:存储为GeoTIFF
把整架次几百张R-JPEG逐张用TSDK读取,再写回带地理坐标的GeoTIFF,是衔接Pix4D mapper的最佳方式。这里有两种常见做法:
做法一:直接用TSDK的转换工具导出16位温度TIFF,再用ExifTool把原R-JPEG中的GPS坐标、飞行姿态信息复制到TIFF里。原因很简单,TSDK导出的TIFF不一定保留完整的EXIF/GPS信息,而Pix4D很依赖影像的初始位置来做航带分配和空三初始化。
# 示例命令,具体参数以你的SDK版本为准 dji_irp -s DJI_0001.RJPG -t DJI_0001_temp.tiff --measure tiff # 复制原始GPS和属性信息到TIFF exiftool -tagsfromfile DJI_0001.RJPG -all:all DJI_0001_temp.tiff做法二:用Python逐张解析后,将温度矩阵写到TIFF里,同时把R-JPEG的EXIF信息一并写入:
import numpy as np import tifffile from dji_thermal_sdk import RJPEG rjpeg = RJPEG("DJI_0001.RJPG") temp_matrix = rjpeg.get_temperature_matrix() # 返回二维温度矩阵,单位摄氏度 tifffile.imwrite( "DJI_0001_temp.tiff", temp_matrix.astype(np.float32), metadata={"software": "DJI TSDK"} )导出后,别忘了做一次质量筛查:把温度矩阵的统计值(最大、最小、均值)打印出来,看看有没有出现-1000°C这种明显离谱的值,或者整片都为0的空洞数据。这些异常帧如果在导入Pix4D前不剔除,会给后面的空三加密带来很大麻烦。
3.3 如何验证解析出的温度是可信的
软件算出来的温度值不能盲信。我在现场常用的验证方法很简单:找一个表面材质均匀、面积足够大的目标(水泥地面、沥青屋顶都行),用接触式点温枪或黑体仪打一个点,和TSDK解析出来的对应像素温度比一比。
误差范围一般控制在±2°C以内可以接受,如果系统性地偏高或偏低,优先检查两处:
- 发射率设置:大疆热像仪菜单里默认发射率通常按0.95设置,实际被测物如果是抛光金属、玻璃这类低发射率表面,温度值会出现很大误差,需要按材质重新设置;
- 反射温度设置:晴天在户外作业时,大气反射对测温影响明显,TSDK解析时用到的反射温度参数(Reflected Apparent Temperature)需要在采集时记录,并在后期解析时手动传入。
4. Pix4D mapper重建红外正射:从工程创建到成果导出
温度矩阵准备好之后,接着就是Pix4D的工作了。这一章节,我直接按我日常项目的操作顺序给大家过一遍。
4.1 新建工程:让软件认出这是热红外数据
启动Pix4Dmapper,新建工程,在添加影像时,把整架次的R-JPEG或转换好的TIFF文件拖进去。
如果直接拖入R-JPEG,Pix4D有时会弹出一个对话框问“是否将影像视为热红外数据”,选“是”即可。如果导入的是TSDK输出的GeoTIFF,软件会自动按单波段影像处理,但需要在“图像属性”里把相机类型手动指定为热成像传感器。
相机型号选择上,Pix4D较新版本内置了大疆H20T、M2EA等机型的热成像相机参数。如果列表里找不到对应型号,就选“DJI Thermal”或“Generic Thermal”,然后手动填入焦距、像元尺寸等参数。这些参数可以从相机的标定文件或DJI官方规格表里查。
坐标系设置建议与同期可见光正射项目保持一致,便于后续叠加分析。
4.2 处理模板的选择
Pix4Dmapper提供了几种处理模板,做红外正射时不要选“3D Maps”这种面向纹理丰富的可见光场景的模板,直接选“Thermal Mapping”或“Ag Multispectral”中带热红外支持的模板。
关键参数上,我一般这样设置:
- 初始化处理:开启“特征点提取”,特征点数阈值可以适当调低一些,因为红外影像的角点和纹理确实弱,阈值定太高会导致匹配点过少;
- 点云和纹理:这一步不是重点,但“点云密度”建议选低,既能显著节省时间,又不会影响正射镶嵌精度;
- 正射影像镶嵌图:勾选输出GeoTIFF,像素尺寸按红外GSD实际值填写,不要强行把它改成可见光的GSD,否则只是把影像重采样放大,不会增加真实信息。
处理过程中,最值得关注的是“初始化处理”阶段出来的图像匹配关系。如果软件提示“Calibration failed”或者大量影像无法匹配,最常见的三个原因:
- 重叠度确实不够,回看航线设计;
- 影像中存在大量的水面、纯色屋顶,导致特征点不足,这样的情况需要考虑加飞或改用可见光辅助匹配;
- 混合了不同批次、不同曝光参数差异过大的数据。
4.3 空三通过以后:检查温度正射的质量
空三完成之后,Pix4D会生成正射影像和DSM。切到“正射影像”界面,先用肉眼检查接边和错位,再用量测工具在某几个明显目标上打点,对比单张R-JPEG里该点位的温度值和正射镶嵌图的温度值,两者应基本一致。
这里容易遇到一个问题:Pix4D默认的输出正射图可能只是把温度值当作普通灰度显示,看起来就像一张黑白照片。这是正常的,温度热图的渲染只是“显示层”的事情,底层GeoTIFF里存储的仍然是真实的温度值。
5. 把温度正射影像渲染成专业交付的热图
做工程交付时,客户要看到的不是灰度图,而是“一眼扫过去就知道哪里高温、哪里低温”的热图。这里就把渲染环节的几种常见做法拆开说。
5.1 Pix4D内部的温度渲染与色带调整
Pix4Dmapper的“正射影像编辑器”里带有温度渲染功能。找到温度显示色带,可以在Iron(铁红)、Rainbow(彩虹)、White Hot(白热)、Black Hot(黑热)等预置方案之间切换。
对光伏巡检来说,我最常用Iron和Rainbow两种:
- Iron:高温呈亮白/黄色,低温呈暗色,适合快速识别热斑;
- Rainbow:颜色跨度大,适合判断温度梯度。
色带范围不要直接使用整张正射的全温度范围,先做一个直方图统计,再把显示范围压缩到感兴趣物体所在的温度区间。比如巡检光伏板时组件表面温度通常在35~75°C,把色带范围设为30~80°C,差异会被拉得足够大,热斑一眼就能看出来。如果从全图-10°C到140°C的范围去显示,所有的组件看上去都是同一个颜色。
5.2 导出到QGIS做自定义伪彩色渲染
Pix4D导出的温度正射GeoTIFF本质上是单波段浮点栅格。在QGIS里做伪彩色是最灵活的:
- 图层属性 → 符号系统 → 单波段伪彩色;
- 渲染类型选择“线性”,色彩渐变选“白-黄-红-深红”或“蓝-青-黄-红”;
- 设置最小值和最大值,通常不取全幅最低最高,而用直方图里的2%~98%分位截断;
- 勾选“标签”显示当前温度值图例;
- 叠加到底图上,将混合模式设为“正片叠底”或“滤色”,适当调整透明度。
如果想输出更平滑的热图过渡,可以在QGIS里做一次低通滤波(栅格 → 分析 → 焦点统计),窗口选3×3,把单个坏像元的椒盐噪声抹掉,温度区域的连续感会好很多。
5.3 用栅格计算器提取“超温区域”
热图渲染只是第一步,工程上真正要交付的是“哪些区域温度超标”的结论。在QGIS的栅格计算器里,一条表达式就能把超温区域变成二值掩膜:
"temp_tif" > 70得到的栅格值是1和0,再把1的像元转为矢量多边形,转成KML或SHP交付给现场班组,第二天就能直接拿着这个文件飞过去对异常点位进行复核。这个流程是温度热图分析里最有工程价值的环节,也是红外正射区别于可见光正射的核心价值点。
6. 可能导致整批数据作废的细节,我帮你提前列出来
最后这部分,不是凑字数,是真的拿项目换来的教训。每一条,我的团队都曾在实际项目中踩过。
6.1 开机预热:温漂是看不见的数据杀手
红外相机刚开机时,传感器温度和散热系统还没稳定,画面里的温度读数是漂移的。我遇到过一批数据,前20张照片解析出来的整幅均温比后80张低了将近3°C,如果混在一起建图,整个正射影像会出现一半区域整体偏蓝、一半偏黄的情况。后来复盘,就是起飞前等待时间太短。
所以任何一次红外数据采集,上电后必须等待传感器稳定,起飞后悬停一分钟再进航线。这个细节写在作业手册里,每次出外业都要检查。
6.2 低发射率表面的“假低温”
抛光金属板、玻璃幕墙、平静水面,这些物体表面反射率高,发射率低,热像仪测到的温度里混入了环境反射温度。在R-JPEG解析阶段如果沿用默认发射率0.95,这些区域的温度值会显著偏低,甚至出现温度倒挂。
处理方式:外业时记录每个架次主要目标的实际发射率,回到内业用TSDK重算温度时把发射率参数改过来。如果目标种类太多,至少要在报告里明确标注哪些区域的绝对温度不可靠,只做相对比较。
6.3 红外匹配点不足:不要让Pix4D硬拼
大片平整的田地、水面、屋顶,热红外图上纹理极弱。Pix4D初始化处理阶段,如果提示“Too few matches”,不要急着反复调参与重跑,先检查数据本身。
我的做法是:在同一航线上开启可见光相机同步采集,在Pix4D工程里把可见光影像和红外影像一起导入,让软件先利用可见光影像完成空三,随后通过相机间已知的安装关系把红外影像的位置姿态推算出来。这样得到的红外正射位置精度和稳定性都靠谱很多。
如果手头没有同步可见光数据,那就只能在航线设计时加大重叠度,以及保证每张红外图里尽量包含地面标志物、道路边缘、建筑物轮廓这类能提供匹配点的区域。
6.4 直接全自动处理了整批TIFF?注意一下位深
TSDK导出温度矩阵时,不同版本默认的保存位深可能不一样,有的是16位整型,有的是32位浮点。Pix4D导入时如果自动识别为8位,温度梯度会被压缩,极可能就是你在正射图上看不出温度层次的原因。
建议统一导出为32位浮点GeoTIFF,用QGIS或Pix4D的量测工具检查某点温度值是否和单帧R-JPEG吻合,确认位深没丢再进入正式处理。
从我个人的经验看,R-JPEG到温度热图的这条链路,真正难的不是某一个软件怎么点,而是理解每一步在数据流里的作用。TSDK帮你把隐藏的16位数据翻译成人能读懂的温度,Pix4D把这些离散的温度帧拼接成一整块带有地理坐标的温度画布,最后再通过渲染把温度信息变成一眼能看懂的工程图。这套流程跑顺之后,无论是光伏巡检、建筑外墙排查、电气设备测温还是农业灌排监测,都能直接套用。