跳转至

03 - 第一次模拟

本章用一块平坦的裸地完成第一次模拟,生成一张从正上方观测的 RGB 图像,然后在地面上放一株玉米。

完整代码

import less

# 1. 场景:10 m × 10 m
scene = less.Scene()
scene.size = 10.0

# 2. 地面:朗伯反射,反射率 0.3
scene.terrain = less.Terrain(property=less.Lambertian(reflectance=0.3))

# 3. 光照:太阳天顶角 30°,方位角 150°(东南),简化光谱大气
scene.illumination = less.Illumination(
    source=less.Sun(zenith=30, azimuth=150),
    atmosphere=less.SimpleSpectralAtmosphere(turbidity=2.0),
)

# 4. 传感器:正射投影,256 × 256 像素,红、绿、蓝三个波段
sensor = less.OpticalImager(
    less.Orthographic(image_size=256),
    bands=[650, 550, 450],
    quality=64,
)

# 5. 模拟并保存
image = scene.simulate(sensor)
image.save("bare_soil_rgb.png")
print(image.data.shape)

配套脚本:scripts/03_first_simulation.py

逐步说明

场景和地面

less.Scene() 创建一个空场景,scene.size = 10.0 把地面范围设为 10 m × 10 m。less.Terrain 是地面,这里用最简单的朗伯反射:各个方向反射一样多,反射率 0.3 表示反射 30% 的入射光。

光照

Illumination 由太阳和大气组成。Sun 给出太阳的方向和大气层顶的太阳光谱;SimpleSpectralAtmosphere 计算到达地面的太阳直射光和天空散射光,turbidity 越大,天空越浑浊。其他大气模型见光照与大气。

传感器

OpticalImager 由投影方式和波段组成:

  • Orthographic(image_size=256):从正上方平行观测,输出 256 × 256 像素,默认覆盖整个场景;
  • bands=[650, 550, 450]:三个波段的中心波长(nm),结果中的波段顺序与列表一致;
  • quality:每个像素使用的采样数。数值越大,图像噪声越小,计算也越久。
quality 用途
16–64 快速预览
128–256 一般分析
512 以上 定量研究、出版图件

正射投影的观测光线互相平行,相当于从极高处向下看:

正射投影

模拟

scene.simulate(sensor) 第一次运行时会先构建场景,再进行光线追踪。之后改变光照、属性或传感器再次模拟时,已经建好的几何会被直接复用。

查看结果

image.data 是一个 NumPy 数组,形状为(行, 列, 波段),数值为辐亮度,单位 W m⁻² sr⁻¹ nm⁻¹:

data = image.data
print(data.dtype, data.min(), data.max())

图像的第一行在北,第一列在西。保存时:

image.save("bare_soil.png")   # 8 位 PNG,用于查看
image.save("bare_soil.tif")   # 保留原始辐亮度

把辐亮度换算为反射率因子(BRF):

brf = image.to_brf()
print(brf.data.mean(axis=(0, 1)))   # 平地的 BRF 接近 0.3

修改参数再模拟

改变太阳位置或地面反射率时,直接再次调用 simulate():

scene.illumination = less.Illumination(
    source=less.Sun(zenith=60, azimuth=90),
    atmosphere=less.SimpleSpectralAtmosphere(turbidity=2.0),
)
image_low_sun = scene.simulate(sensor)

scene.terrain.set_property(less.Lambertian(reflectance=0.1))
image_dark = scene.simulate(sensor)

放一株玉米

LESS 自带一个玉米植株模型 maize.obj。用 PROSPECT 叶片模型设置叶片光学属性后放到场景中心:

maize = less.Object("maize", mesh=less.asset_path("maize.obj"))
maize.set_property(less.Prospect(cab=40, car=8, cw=0.012, cm=0.006, N=1.5))
scene.add(maize, positions=[[5.0, 5.0, 0.0]])

image_maize = scene.simulate(sensor)
image_maize.save("one_maize.png")

添加物体后再次模拟时,LESS 会自动重新构建几何。

下一步