26 - 热红外成像¶
温度高于绝对零度的物体都会发出热辐射。在 8–14 µm 的热红外波段,地物的辐射主要由温度和发射率决定:
其中 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