卫星图像处理

我是谁?

我是 David Hoese,我在威斯康星大学麦迪逊分校的 太空科学与工程中心 (SSEC) 担任软件开发人员。我的工作是创建软件,使气象数据更容易为科学家和研究人员所获取。

我也是开源社区 PyTroll 的成员,担任 SatPy 库的核心开发者。我在 SSEC 项目 Polar2Grid 和 Geo2Grid 中使用 SatPy,这两个项目在 SatPy 提供的功能之上提供了简单的命令行界面。

我正尝试解决的问题

由于卫星图像数据格式和结构多种多样,通常难以读取和使用。为了使卫星图像更有用,SatPy 库将对卫星数据执行的常见操作封装在简单的接口中。通常,气象卫星数据需要经过以下部分或全部步骤

  • 读取: 从一个或多个数据文件中读取观测到的科学数据,同时跟踪地理位置和其他元数据,以使数据最有用和最具描述性。

  • 合成: 组合一个或多个不同的数据“通道”,以突出数据中的某些特征。这通常显示为 RGB 图像。

  • 校正: 有时数据会存在伪影(例如,来自仪器硬件或大气),可以将其移除或调整。

  • 重采样: 可视化工具通常只支持一小部分地球投影,而卫星数据通常不在这些投影中。当想要比较不同仪器(无论是否在同一颗卫星上)之间的数据时,重采样也很有用。

  • 增强: 数据可以用某些方式进行归一化或缩放,使某些大气条件更明显。这也可用于更好地将数据适配到其他数据类型(如 8 位整数等)中。

  • 写入: 可视化工具通常只支持少数特定的文件格式。其中一些格式难以写入,或者根据目标应用程序而存在微小差异。

随着卫星仪器技术的进步,科学家必须学习如何处理每个仪器的更多通道,以及在他们学习使用卫星数据时前所未有的空间和时间分辨率。如果幸运的话,科学家可以使用高性能计算系统,而其他人可能不得不在台式机或笔记本电脑上忍受漫长的执行时间。通过优化处理中耗时和耗内存的部分,我们希望科学家能够专注于科学研究,将那些烦人的部分留给 SatPy 处理。

Dask 如何提供帮助

SatPy 对 Dask 的使用使得在笔记本电脑上进行计算成为可能,而这些计算过去需要高性能服务器。SatPy 最初被 XarrayDataArray 对象吸引,因为其元数据存储功能和对 Dask 数组的支持。我们知道我们最初使用 Numpy 掩码数组的方式无法扩展到正在生成的新卫星数据。SatPy 现在已转向由 Dask 支持的 DataArray 对象,并利用 Dask 的以下能力

  • 惰性评估: 当你不必从内存中移除中间结果来处理下一步时,软件开发会变得容易得多。

  • 任务缓存: 我们的处理涉及许多可以在不同进程之间共享的中间结果。当 Dask 图中的内容被优化时,作为开发者,我们就不必自己编写“重用”逻辑。这也意味着不再需要的中间结果可以被丢弃并释放内存。

  • 并行工作器和数组分块: 卫星数据通常通过地理位置进行比较。因此,一个索引处的像素经常与另一个数组在相同索引处的像素进行比较。将数组分割成块并单独处理它们为我们带来了巨大的性能提升,并且不必管理哪个工作器获取数组的哪个块,这使得开发变得轻松。

得益于以上所有优点,我们可以在一台 3 年前的笔记本电脑上在 6-8 分钟内创建令人惊叹的高分辨率 RGB 图像,而使用 SatPy 旧的 Numpy 实现则需要 35 分钟以上并可能因内存限制而崩溃。

使用 Dask 时的痛点

  1. Dask 数组不是 Numpy 数组。几乎所有功能都得到支持,或者足够接近让你习惯它,但并非全部。大多数情况下你可以顺利使用并获得良好的性能;而在其他情况下,你可能会在不知情的情况下,在短短几行代码中多次计算你的数组。有时我希望 Dask 有一个功能,如果你的数组在未经你明确允许的情况下被计算,就会引发异常。

  2. 写入常见的卫星数据格式(如 GeoTIFF)并非总能被多个写入器(集群上的多个节点)同时写入,有些甚至不是线程安全的。打开一个文件对象并将其与 dask.array.store 一起使用可能适用于某些调度器,但不适用于其他调度器。

  3. 维度更改是个麻烦事。卫星数据处理有时涉及查找表,以节省从卫星向地面发送数据时的带宽限制或其他类似情况。使用查找表(包括像 KDTree 这样的东西)与 Dask 编码并使其正常工作可能非常困难和令人困惑。这通常涉及使用 atopmap_blocks,或者有时会付出代价,将东西传递给一个 Delayed 函数,其中整个数据数组被作为一个完整的、内存消耗大的数组传递。

  4. 由于所解决问题的性质,许多卫星处理似乎在使用默认的线程 Dask 调度器时比分布式调度器表现更好。许多处理,尤其是 RGB 图像的创建,需要以不同方式比较多个数组,并且会受到分布式工作器之间通信量大的影响。据我所知,没有一种简单的方法可以控制处理位置以及使用哪个调度器,而不需要用户了解 Dask 内部的详细信息。

我围绕 Dask 使用的技术

如前所述,SatPy 尽可能使用 Xarray 来封装我们的大部分 Dask 操作。我们在 PyTroll 社区中创建了其他有用的工具,以帮助支持在服务器上部署卫星处理工具,但它们并非专门针对 Dask。