跳转至

26 - 热红外成像

温度高于绝对零度的物体都会发出热辐射。在 8–14 µm 的热红外波段,地物的辐射主要由温度和发射率决定:

\[L = \varepsilon\,B(\lambda, T)\]

其中 B 是普朗克函数。冠层中受光叶片、阴影叶片、土壤和树干的温度各不相同,热红外影像因此包含丰富的空间信息。场景中的热辐射还会在叶片、土壤之间多次反射,LESS 在三维场景中一起计算。

热属性

热属性独立于光学属性设置,温度单位为 K:

import less

leaf_thermal = less.ThermalProperty(emissivity=0.98,
                                    temperature_sunlit=305.0, temperature_shaded=300.0)
soil_thermal = less.ThermalProperty(emissivity=0.95,
                                    temperature_sunlit=312.0, temperature_shaded=303.0)
trunk_thermal = less.ThermalProperty(emissivity=0.97, temperature=300.0)
asphalt = less.ThermalProperty(emissivity=[0.95, 0.97], wavelengths=[10600, 12000],
                               temperature=320.0)
  • temperature:组件的温度;
  • temperature_sunlit、temperature_shaded:受光和阴影部分的温度,两者需要同时给出。观测光线落到某一点时,LESS 检查该点能否直接看到太阳,据此选择使用哪一个温度。统计植被则按受光叶片的比例组合两个温度;
  • emissivity:发射率,可以是光谱数组。
  • transmittance:热透射率,默认为 0;反射率为 1 - emissivity - transmittance。

显式网格的半透射表面可以同时发射、漫反射和漫透射热辐射。例如, less.ThermalProperty(temperature=300, emissivity=0.6, transmittance=0.2) 的反射率为 0.2。发射率与透射率均可用数值光谱设置,共用 wavelengths, 并随传感器波段插值;每个波长都需满足二者之和不超过 1。 半透射设置目前用于给定温度的显式网格热成像;能量平衡求温度、统计植被和 发射率纹理仍需不透明热属性。解析验证见 A4 - 热辐射腔体。

热红外成像仪

thermal_sensor = less.ThermalImager(
    less.Orthographic(image_size=128),
    bands=[10600],          # nm
    quality=32,
)
传感器 波段 中心波长(nm)
Landsat TIRS B10 10.6 µm 10600
Landsat TIRS B11 12.0 µm 12000
ASTER B13 10.7 µm 10700
MODIS B31 11.0 µm 11000

结果是光谱辐亮度(W m⁻² sr⁻¹ nm⁻¹),可以换算为亮度温度。

森林的热红外影像

scene = less.Scene()
scene.size = 50.0
scene.terrain = less.Terrain(property=less.Lambertian(reflectance=0.15))
scene.terrain.set_property(soil_thermal)
scene.illumination = less.Illumination(
    source=less.Sun(zenith=30, azimuth=150),
    atmosphere=less.PrescribedAtmosphere(sky_temperature=260.0))

tree = less.Object("ash", mesh=less.asset_path("FREX.obj"))
tree.set_property("leaves", less.Prospect(cab=40, car=10))
tree.set_property("stem_branch", less.Lambertian(reflectance=0.08))
tree.set_property("leaves", leaf_thermal)
tree.set_property("stem_branch", trunk_thermal)
positions = less.place.random(scene, n=40, min_dist=4.0, seed=42)
n = len(positions)
scene.add(tree, positions=positions,
          scales=less.place.uniform_scale(n, 0.7, 1.3, seed=42),
          rotations=less.place.random_rotation(n, seed=42))

radiance = scene.simulate(thermal_sensor)
radiance.save("forest_thermal.tif")

brightness = radiance.to_brightness_temperature(unit="K")      # 默认单位为 °C
print(f"亮度温度: {brightness.data.min():.1f} ~ {brightness.data.max():.1f} K")
brightness.save("forest_brightness_temperature.png")

阴影土壤和叶片的温度较低,受光土壤最高。同一场景加一个光学传感器就能得到对应的 RGB 影像,用于对照:

rgb = scene.simulate(less.OpticalImager(
    less.Orthographic(image_size=128), bands=[650, 550, 450], quality=32))

天空的热辐射

天空向下的热辐射照亮场景,再被地物反射,低发射率表面尤其明显。天空热辐射的来源:

大气 天空热辐射
less.Atmosphere 由大气廓线计算
less.NoAtmosphere 没有
其他模型 sky_temperature(K)给出天空的等效亮度温度
其他模型,未给出 sky_temperature 使用模拟时传入的 Microclimate 的向下长波辐射

天空的等效温度:晴天约 250–270 K,多云约 270–290 K,阴天接近地面温度。

不同时刻

只改变温度和太阳位置,几何不变,可以直接再次模拟:

scene.terrain.set_property(less.ThermalProperty(
    emissivity=0.95, temperature_sunlit=295.0, temperature_shaded=293.0))
tree.set_property("leaves", less.ThermalProperty(
    emissivity=0.98, temperature_sunlit=294.0, temperature_shaded=293.0))
scene.illumination = less.Illumination(
    source=less.Sun(zenith=70, azimuth=90),
    atmosphere=less.PrescribedAtmosphere(sky_temperature=260.0))
morning = scene.simulate(thermal_sensor)

scene.terrain.set_property(less.ThermalProperty(
    emissivity=0.95, temperature_sunlit=318.0, temperature_shaded=305.0))
tree.set_property("leaves", less.ThermalProperty(
    emissivity=0.98, temperature_sunlit=308.0, temperature_shaded=301.0))
scene.illumination = less.Illumination(
    source=less.Sun(zenith=10, azimuth=180),
    atmosphere=less.PrescribedAtmosphere(sky_temperature=260.0))
noon = scene.simulate(thermal_sensor)

常见组分的温度范围(K):

组分 受光 阴影
冠层上部叶片 303–310 298–303
冠层下部叶片 300–305 297–301
裸土 310–320 300–308
草地 303–308 298–302
树干 298–303 —

由能量平衡得到温度

以上温度都是人为给定的。需要由气象条件和植物生理决定温度时,先运行能量平衡(第 32 章),之后热红外成像会自动使用求得的温度。下面用一小块玉米地演示:

plot = less.Scene()
plot.size = 3.0
plot.terrain = less.Terrain(property=less.Lambertian(reflectance=0.15))
plot.terrain.set_property(less.ThermalProperty(temperature="air", emissivity=0.95))
plot.terrain.set_property(less.BiophysicalProperty(two_sided=False, stomata_side="none",
                                                   ground_heat_fraction=0.3))
plot.illumination = less.Illumination(
    source=less.Sun(zenith=30, azimuth=150),
    atmosphere=less.SimpleSpectralAtmosphere(turbidity=2.0))

maize = less.Object("maize", mesh=less.asset_path("maize.obj"))
maize.set_property(less.Prospect(cab=45))
maize.set_property(less.ThermalProperty(temperature="air", emissivity=0.98))
maize.set_property(less.BiophysicalProperty(leaf_width=0.08, stomata_side="bottom",
                                            stomatal_resistance=150.0))
plot.add(maize, positions=less.place.grid(plot, spacing=1.0))

climate = less.Microclimate(air_temperature=28.0, humidity=50.0, wind_speed=2.0)
energy = plot.simulate(less.EnergyBalanceProcess(quality="preview"), microclimate=climate)
solved = plot.simulate(thermal_sensor, microclimate=climate)
print(solved.to_brightness_temperature(unit="K").data.mean())

temperature="air" 表示以气温作为初始温度。

ThermalImager 的 mode 参数控制使用哪个温度:

mode 温度来源
"auto"(默认) 有能量平衡结果时使用它,否则使用热属性中的温度
"property" 热属性中的温度
"precomputed" 已有的能量平衡结果

大气层顶与传感器

使用 less.Atmosphere 时,可以给出大气层顶或某一高度的辐亮度:

scene.illumination = less.Illumination(
    source=less.Sun(zenith=30, azimuth=150),
    atmosphere=less.Atmosphere.standard("midlatitude_summer"))

toa = scene.simulate(less.ThermalImager(
    less.Orthographic(image_size=64),
    bands=less.gaussian_bands([("LWIR_10.6", 10600, 1000)]),
    spectral_resolution=20, observation_level="toa", mode="property"))

gaussian_bands 用高斯形状的光谱响应定义波段(名称、中心波长、半高宽,nm)。

加入光子探测器模型,可以得到推扫热红外仪器的数字量:

dn = scene.simulate(less.ThermalImager(
    less.Pushbroom(resolution=64, num_lines=64, altitude=5000.0, swath_width=50.0),
    bands=[10600, 12000], observation_level="toa", mode="property",
    instrument=less.Instrument.thermal_photon(
        aperture_diameter=0.15, bandwidth=[1000, 1000], column_gain_sigma=0.01, seed=42),
))

Instrument.thermal_photon() 的量子效率、满阱、暗电流和读出噪声按碲镉汞或量子阱红外探测器的量级设置,不代表微测辐射热计。instrument.nedt(wavelength_nm, T_ref_K, projection=...) 给出均匀黑体场景下亮度温度的噪声等效温差。热红外成像支持正射和推扫投影。完整的推扫示例见 python -m less.examples thermal_pushbroom。

大气中可以加入一层平面平行的薄云,按像元的云量混合晴空和有云的情况:

cloudy = less.Atmosphere.standard(
    "midlatitude_summer",
    cloud=less.CloudLayer(cover=0.5, altitude_km=3.0, thickness_km=0.5, optical_depth=8.0),
    precipitable_water_g_cm2=2.1,
)

配套脚本:scripts/26_thermal_imaging.py

下一步