三维辐射传输模型往往有复杂的输入参数,因此一般的模型都有相应的GUI软件,虽然GUI方便学习和使用,但是难以进行批处理以及嵌入其他程序中。在LESS中,已经提供了一个基于GUI的批处理工具,目前可以对场景中的观测参数、太阳参数以及光谱参数等进行批量修改和模拟,但是仍然无法批量地修改场景中的三维元素,例如树的结构或者树的位置,而批量修改三维结构在一些应用中也是非常常见的需求。
经过与不少用户的交流,也花了不少时间,为了实现更方便的批量模拟,于是开发了这样一套基于Python的SDK接口pyLessSDK, 可以实现场景中任意元素的修改,进而实现批处理。同时,通过Python调用的形式,整个模拟过程无需打开GUI程序,更方便将模拟过程与其他处理过程进行整合。
pyLessSDK经过一段时间的调试,以及一些用户的测试,已经逐步趋于稳定(虽然bug是难以避免的),更详细的说明和使用文档可以参考LESS的用户手册(点原文链接)。
LESS Python SDK主要功能
该SDK的主要类图如下:
基本模拟过程
以下代码展示了利用python创建一个默认模拟工程,并直接进行模拟的示例。首先导入SimulationHelper和Simulation两个类,前者是模拟工程的辅助类,后者代表整个模拟工程。Simulation包含一个SimulatinHelper和一个Scene成员变量。SimulatinHelper主要提供创建新的模拟工程以及获取一些系统参数(例如python的路径等)等功能,例如create_new_sim函数根据一个输入的目录路径创建一个新的模拟工程,并用标准模板初始化该工程(设定默认参数等),如果模拟工程已经存在,则跳过。Simulation实例从一个模拟工程路径和一个SimulatinHelper实例构造而来,得到Simulation实例后(即sim),需要通过read_sim_project函数读取模拟工程的参数到sim对象中,然后可以调用save_sim_project()函数保存工程(此处没有修改参数,也可以不保存),最终调用start()函数执行模拟。
# coding: utf-8from SimulationHelper import SimulationHelperfrom Simulation import Simulationfrom PostProcessing import PostProcessingimport ossim_dir = r"D:\LESS\simulations\Ex01"sim_helper = SimulationHelper(r"D:\LESS") # 创建SimulationHelper,参数为LESS的安装根目录sim_helper.create_new_sim(sim_dir) # 新建模拟工程sim = Simulation(sim_dir, sim_helper) # 初始化Simulation对象sim.read_sim_project() # 读取模拟工程的内容sim.save_sim_project() # 保存工程sim.start() # 开始模拟
以上代码是一个最简单的模拟过程,无需打开GUI程序即可实现。最终的模拟结果是一副图像(spectral_VZ=0_VA=180),保存的位置为D:\LESS\simulations\Ex01\Results\,默认保存为ENVI格式,像素值的类型为辐亮度(Radiance)。
为了将辐亮度转为反射率,可以使用PostProcessing中的radiance2brf函数,该函数具有三个参数,第一个为模拟工程的路径,用以获取辐照度等信息;第二个为输入文件路径,即辐亮度文件,也是上一步中模拟得到的文件;第三个为输出文件路径,即BRF文件。模拟结束后得到下图所示BRF文件。(代码中的高亮加粗代码为新增代码)
# coding: utf-8from SimulationHelper import SimulationHelperfrom Simulation import Simulationfrom PostProcessing import PostProcessingimport ossim_dir = r"D:\LESS\simulations\Ex01"sim_helper = SimulationHelper(r"D:\LESS") # 创建SimulationHelper,参数为LESS的安装根目录sim_helper.create_new_sim(sim_dir) # 新建模拟工程sim = Simulation(sim_dir, sim_helper) # 初始化Simulation对象sim.read_sim_project() # 读取模拟工程的内容# 模拟的输出文件sim.save_sim_project() # 保存工程sim.start() # 开始模拟PostProcessing.radiance2brf(sim.get_sim_dir(), sim.get_dist_file(), sim.get_dist_file()+"_BRF")
上述代码使用的是默认的输出文件名spectral_VZ=0_VA=180(通过函数sim.get_dist_file得到),实际上,为了方便使用,我们在模拟时,可以设定自己的输出文件名,在read_sim_project和save_sim_project之间通过修改参数实现,代码如下:
sim.read_sim_project() # 读取模拟工程的内容sim.set_dist_file(os.path.join(sim.get_sim_dir(), "Results", "output_radiance_file"))# 模拟的输出文件sim.save_sim_project() # 保存工程
在Ex01中,虽然我们实现了整个模拟流程,但是默认场景中只包含了一个简单100m*100m的平地。本例中,我们将在场景中添加一些树木,并设定其光谱。
在LESS中,目前所有的场景元素(树木、房子等)均以三角面片的OBJ格式文件作为输入,树模型等可以通过第三方软件如OnyxTree等生成。
所有的场景元素均在类Scene中进行管理,当创建一个Simulation后,可以通过sim.get_scene()得到Scene的实例,进而访问或者修改场景中的元素。示例代码如下:
# coding: utf-8from SimulationHelper import SimulationHelperfrom Simulation import Simulationfrom PostProcessing import PostProcessingimport osfrom SceneObjects import SceneObjectfrom Utility import OBJHelperimport randomsim_dir = r"D:\LESS\simulations\Ex02"sim_helper = SimulationHelper(r"D:\LESS") # 创建SimulationHelper,参数为LESS的安装根目录sim_helper.create_new_sim(sim_dir) # 新建模拟工程sim = Simulation(sim_dir, sim_helper) # 初始化Simulation对象sim.read_sim_project() # 读取模拟工程的内容sim.set_dist_file(os.path.join(sim.get_sim_dir(), "Results", "output_radiance_file"))#################添加场景元素 start ####################scene = sim.get_scene() # 得到Scenelandscape = scene.get_landscape() # 得到LandScape对象landscape.clear_landscape_elements() # # 清除工程已有的场景元素(重复运行程序时,必须执行)obj_tree01 = SceneObject("Tree01") # 定义一个场景物体,名叫Tree01# 添加一个obj文件作为tree1的一个组分,对于包含多个group的obj文件,首先需要拆分并获取每个组的路径,再分别导入,每个group设置不同的光学属性comp_list = OBJHelper.seperate_obj(r"D:\LESS\app\Database\3D_Objects\Trees\RAMI\FREX_FROM_HET09_JBS_SUM.obj")# FREX_FROM_HET09_JBS_SUM.obj包含两个组分,第一个为leaves,第二个为branch,因此分别导入。# birch_leaf_green 和 birch_branch为默认已定义的内置光学属性,自定义光学属性将在下一个案例讲解obj_tree01.add_component_from_file(comp_list[0], "birch_leaf_green")obj_tree01.add_component_from_file(comp_list[1], "birch_branch")landscape.add_object(obj_tree01)# 当定义好一个obj文件时,还需要将其放置在不同的位置,在LESS中称之为instance# 随机放置在场景中,场景默认大小为100m*100mfor i in range(1000): x = random.random()*100 y = random.random()*100 landscape.place_object("Tree01", x=x, y=y)############### 添加场景元素 end ############### 模拟的输出文件sim.save_sim_project() # 保存工程sim.start() # 开始模拟PostProcessing.radiance2brf(sim.get_sim_dir(), sim.get_dist_file(), sim.get_dist_file()+"_BRF")
以上是一个简单的使用示例,更详细的说明请参考LESS用户手册。