跳转至

12 - 热红外模拟

本章介绍如何使用 LESS 模拟热红外遥感图像。

热红外遥感原理

所有温度高于绝对零度的物体都会发射热辐射。在热红外波段(8-14 μm),地表物体的热辐射与其 温度发射率 有关:

L = ε × B(T, λ)

其中: - L:热辐亮度 (W/m²/sr/μm) - ε:发射率 (0-1) - B(T, λ):普朗克函数(黑体辐射) - T:物体温度 (K)

植被冠层中,不同组分(阳面叶片、阴面叶片、土壤、树干)的温度不同,这导致热红外图像中存在丰富的温度空间分异信息。

ThermalProperty —— 热属性

每个场景元素都可以设置热属性,独立于光学属性:

import less

# 叶片:阳面和阴面温度不同
leaf_thermal = less.ThermalProperty(
    emissivity=0.98,
    temperature_sunlit=305.0,     # 阳面温度 (K) ≈ 32°C
    temperature_shaded=300.0,     # 阴面温度 (K) ≈ 27°C
)

# 土壤:温差更大
soil_thermal = less.ThermalProperty(
    emissivity=0.95,
    temperature_sunlit=312.0,     # 阳面 ≈ 39°C
    temperature_shaded=303.0,     # 阴面 ≈ 30°C
)

# 树干:使用单一温度
trunk_thermal = less.ThermalProperty(
    emissivity=0.97,
    temperature=300.0,            # 统一温度 ≈ 27°C
)

阳面/阴面温度

LESS 根据每个三角面片的法线方向和太阳方向的关系,自动判断该面片处于阳面还是阴面:

  • 阳面 (sunlit):面片法线朝向太阳且未被遮挡 → 使用 temperature_sunlit
  • 阴面 (shaded):法线背向太阳或被遮挡 → 使用 temperature_shaded

这比使用单一温度更加真实。

ThermalImager —— 热红外成像仪

sensor_thermal = less.ThermalImager(
    less.Orthographic(image_size=512),
    bands=[10600],        # 10.6 μm = 10600 nm(Landsat TIRS B10)
    quality=128,
)

常用热红外波段:

传感器 波段 中心波长
Landsat TIRS B10 10.6 μm 10600 nm
Landsat TIRS B11 12.0 μm 12000 nm
ASTER B13 10.7 μm 10700 nm
MODIS B31 11.0 μm 11000 nm

完整示例:森林热红外模拟

import less
import numpy as np

# ── 创建场景 ──────────────────────────────────────────────────
scene = less.Scene()
scene.size = 50.0

# 土壤(光学 + 热)
terrain = less.Terrain()
terrain.set_property(less.Lambertian(reflectance=0.15))
terrain.set_property(less.ThermalProperty(
    emissivity=0.95,
    temperature_sunlit=312.0,
    temperature_shaded=303.0,
))
scene.terrain = terrain

# 光照(需要设置 sky_temperature 用于长波辐射)
scene.illumination = less.Illumination(source=less.Sun(zenith=30, azimuth=150), atmosphere=less.NoAtmosphere())

# ── 树木(光学 + 热)────────────────────────────────────────
tree = less.Object("ash", mesh=less.examples.asset_path("FREX.obj"))

# 光学属性
tree.set_property("leaves", less.Prospect(cab=40, car=10, cw=0.012, cm=0.008, N=1.5))
tree.set_property("stem_branch", less.Lambertian(reflectance=0.08))

# 热属性
tree.set_property("leaves", less.ThermalProperty(
    emissivity=0.98,
    temperature_sunlit=305.0,
    temperature_shaded=300.0,
))
tree.set_property("stem_branch", less.ThermalProperty(
    emissivity=0.97,
    temperature=300.0,
))

# 放置
rng = np.random.RandomState(42)
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))
sensor_thermal = less.ThermalImager(
    less.Orthographic(image_size=512),
    bands=[10600],
    quality=128,
    name="Thermal IR",
)
image_thermal = scene.simulate(sensor_thermal)
image_thermal.save("12_thermal.png")
image_thermal.save("12_thermal.tif")    # 保留原始辐射值

# ── 同时获取 RGB 用于对比 ────────────────────────────────────
sensor_rgb = less.OpticalImager(
    less.Orthographic(image_size=512),
    bands=[650, 550, 450],
    quality=128,
)
image_rgb = scene.simulate(sensor_rgb)
image_rgb.save("12_rgb.png")

# ── 分析热图像 ───────────────────────────────────────────────
data = image_thermal.data
print(f"热辐亮度范围: {data.min():.2f} ~ {data.max():.2f} W/m²/sr/μm")

print("Tutorial 12 完成!")

配套脚本:scripts/12_thermal.py

sky_temperature 的作用

sky_temperature 定义天空在热红外波段的等效辐射温度。它影响:

  1. 天空长波辐射:天空向下的热辐射贡献
  2. 反射分量:物体表面反射的天空热辐射(尤其是低发射率表面)

典型值: - 晴天:250-270 K - 多云:270-290 K - 完全阴天:≈地面温度

温差参数的设置建议

组分 阳面温度 (K) 阴面温度 (K) 温差
阳性树叶 303-310 298-303 3-7 K
阴性树叶 300-305 297-301 2-4 K
裸土 310-320 300-308 8-15 K
草地 303-308 298-302 3-6 K
树干 单一温度 298-303 - -

这些是手动指定的温度值。如果您需要物理驱动的温度模拟,请参考 第 13 章:能量平衡

多时相热红外模拟

利用数字孪生架构,可以快速模拟不同时刻的热红外图像:

# 清晨(温差小)
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.NoAtmosphere())

image_morning = scene.simulate(sensor_thermal)
image_morning.save("12_thermal_morning.png")

# 正午(温差大)
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.NoAtmosphere())

image_noon = scene.simulate(sensor_thermal)
image_noon.save("12_thermal_noon.png")

注意:这里只修改了属性和光照,没有修改几何,所以 不需要 rebuild

下一步

Turbid 热红外

TurbidBoundary 的热成像直接消费 resident 温度状态与自适应空间场。使用 ThermalImager(mode="property") 可观察属性温度,使用 mode="eb"mode="precomputed" 可观察能量平衡结果。Python 不再生成叶片或上传逐样本温度。

相关 API

  • less.ThermalProperty
  • less.ThermalImagerless.Orthographic
  • less.Illuminationless.Sunless.Atmosphere
  • less.EnergyBalanceProcessless.Microclimate
  • less.Product.save()