从gdal的python绑定切换

本文档专门为gdal的python绑定用户编写。 (osgeo.gdal )谁读过关于栅格的书? philosophy 想知道转换需要什么。好消息是,转换可能并不复杂。本文档解释了这两个Python包之间的主要相似性和差异,并重点介绍了有助于切换的栅格的特性。

相互不相容

Rasterio和gdal的绑定可以争夺全局gdal对象。除非您对这两个软件包都有深入的了解,否则请选择 import osgeo.gdalimport rasterio .

GDAL的绑定 (gdal 对于本文档的其余部分)和Rasterio不完全兼容,不应在没有大量注意的情况下导入并在单个Python程序中使用。原因是它们每次加载的动态库(记住,这些是C扩展模块)。 libgdal.so 在Linux上, gdal.dll 在Windows上,有许多全局对象,这两个模块采用不同的方法来管理这些对象。

的gdal库的静态链接 gdalrasterio 可以避免这种争用,但实际上,您几乎不会看到静态链接gdal库的这些模块的分布。

除上述问题外,模块还有不同的风格- gdal 像C一样读写 rasterio 更像是 Python ——而且不能很好地互相补充。

GDAL环境

gdal库函数是在格式驱动程序、错误处理程序和特定于格式的配置选项的上下文中执行的,本文档将这些选项称为“gdal环境”。Rasterio具有gdal环境的抽象, gdal 没有。

gdal ,此上下文在导入模块时初始化。这是有道理的,因为 gdal 对象是gdal动态库中函数和类的瘦包装器,通常需要注册驱动程序和错误处理程序。这个 gdal 模块没有环境的抽象,但是可以使用如下函数修改它 gdal.SetErrorHandler()gdal.UseExceptions() .

Rasterio有不需要完整初始化和配置gdal的模块 (rasterio.dtypesrasterio.profilesrasterio.windows 例如)为了减少开销,在需要格式驱动程序和错误处理程序之前,它们不会注册。确实需要完全初始化gdal环境的函数将确保它们的存在。 rasterio.open() 是这类功能中最重要的。考虑下面的示例代码。

import rasterio
# The GDAL environment has no registered format drivers or error
# handlers at this point.

with rasterio.open('example.tif') as src:
    # Format drivers and error handlers are registered just before
    # open() executes.

进口 rasterio 不初始化gdal环境。打电话 rasterio.open() 做。这和 gdal 在哪里? import osgeo.gdal 不是 osgeo.gdal.Open() ,初始化gdal环境。

Rasterio对gdal环境有一个抽象的概念, rasterio.Env ,可以显式调用它以对gdal的配置进行更多的控制,如下所示。

import rasterio
# The GDAL environment has no registered format drivers or error
# handlers at this point.

with rasterio.Env(CPL_DEBUG=True, GDAL_CACHEMAX=512):
    # This ensures that all drivers are registered in the global
    # context. Within this block *only* GDAL's debugging messages
    # are turned on and the raster block cache size is set to 512MB.

    with rasterio.open('example.tif') as src:
        # Perform GDAL operations in this context.
        # ...
        # Done.

# At this point, configuration options are set back to their
# previous (possibly unset) values. The raster block cache size
# is returned to its default (5% of available RAM) and debugging
# messages are disabled.

如前所述, gdal 对于gdal环境没有这样的抽象。最接近的近似值类似于下面的代码。

from osgeo import gdal

# Define a new configuration, save the previous configuration,
# and then apply the new one.
new_config = {
    'CPL_DEBUG': 'ON', 'GDAL_CACHEMAX': '512'}
prev_config = {
    key: gdal.GetConfigOption(key) for key in new_config.keys()}
for key, val in new_config.items():
    gdal.SetConfigOption(key, val)

# Perform GDAL operations in this context.
# ...
# Done.

# Restore previous configuration.
for key, val in prev_config.items():
    gdal.SetConfigOption(key, val)

Rasterio通过一条python语句实现了这一点。

with rasterio.Env(CPL_DEBUG=True, GDAL_CACHEMAX=512):
    # ...

格式化驱动程序

gdal 为每个gdal格式驱动程序提供对象。使用Rasterio,格式驱动程序由字符串表示,并且仅用作以下函数的参数: rasterio.open() .

dst = rasterio.open('new.tif', 'w', format='GTiff', **kwargs)

Rasterio使用与gdal相同的格式驱动程序名称。

数据集标识符

Rasterio使用URI识别数据集,并为不同的协议提供方案。gdal绑定有自己的特殊语法。

Unix样式的文件名,如 /var/data/example.tif 为栅格和 gdal . Rasterio还接受类似于“文件”的URI方案 file:///var/data/example.tif .

Rasterio使用ApacheVFS风格的标识符(如 zip:///var/data/example.zip!example.tiftar:///var/data/example.tar!example.tif .

通过https服务的数据集使用类似“https”uris的 https://landsat-pds.s3.amazonaws.com/L8/139/045/LC81390452014295LGN00/LC81390452014295LGN00_B1.TIF .

AWS S3上的数据集使用“S3”方案标识符进行标识,如 s3://landsat-pds/L8/139/045/LC81390452014295LGN00/LC81390452014295LGN00_B1.TIF .

gdal ,等效标识符分别为 /vsizip//var/data/example.zip/example.tif/vsitar//var/data/example.tar/example.tif/vsicurl/landsat-pds.s3.amazonaws.com/L8/139/045/LC81390452014295LGN00/LC81390452014295LGN00_B1.TIF/vsis3/landsat-pds/L8/139/045/LC81390452014295LGN00/LC81390452014295LGN00_B1.TIF .

为了帮助开发人员进行切换,Rasterio也将接受这些标识符和其他特定于格式的连接字符串,并将它们分派给适当的格式驱动程序和协议。

数据集对象

栅格和 gdal 每个都有数据集对象。当然不是同一类,但也不是完全不同的类。在每种情况下,通常通过“opener”函数获取数据集对象: rasterio.open()gdal.Open() .

这样,Python开发人员就可以减少读取文档的时间,数据集对象由 rasterio.open() 基于python的文件对象建模。它甚至有 close() 方法 gdal 缺少以便可以主动关闭数据集连接。

乐队

gdal 有带对象。Rasterio没有,因此也从来没有对象具有悬空的数据集指针。使用栅格,波段由一个数字索引表示,从1开始(就像gdal那样),并用作数据集方法的参数。将数据集的第一个带区读取为numpy ndarray 做这个。

with rasterio.open('example.tif') as src:
    band1 = src.read(1)

gdal带对象的其他属性通常以数据集属性返回的元组的形式出现在栅格中,每个带依次有一个值。

>>> src = rasterio.open('example.tif')
>>> src.indexes
(1, 2, 3)
>>> src.dtypes
('uint8', 'uint8', 'uint8')
>>> src.descriptions
('Red band', 'Green band', 'Blue band')
>>> src.units
('DN', 'DN', 'DN')

希望应用程序使用只读带对象的开发人员可以通过将这些元组压缩在一起来创建它们。

from collections import namedtuple

Band = namedtuple('Band', ['idx', 'dtype', 'description', 'units'])

src = rasterio.open('example.tif')
bands = [Band(vals) for vals in zip(
    src.indexes, src.dtypes, src.descriptions, src.units)]

NamedDuples类似于轻量级类。

>>> for band in bands:
...     print(band.idx)
...
1
2
3

地质变换

这个 transform Rasterio数据集对象的属性与 GeoTransform 一个gdal数据集的属性,但Rasterio的功能更强大。它不仅是仿射变换矩阵元素的数组,而且是 Afine 并且有许多方便的方法。例如,任何栅格元素左上角的空间坐标都是数据集的 transform 矩阵和 (column, row) 元素的索引。

>>> src = rasterio.open('example.tif')
>>> src.transform * (0, 0)
(101985.0, 2826915.0)

仿射变换矩阵也可以反转。

>>> ~src.transform * (101985.0, 2826915.0)
(0.0, 0.0)

为了帮助开发人员切换, Affine 实例可以从使用的序列创建或转换为 gdal .

>>> from rasterio.transform import Affine
>>> Affine.from_gdal(101985.0, 300.0379266750948, 0.0,
...                  2826915.0, 0.0, -300.041782729805).to_gdal()
...
(101985.0, 300.0379266750948, 0.0, 2826915.0, 0.0, -300.041782729805)

坐标参考系

这个 crs Rasterio数据集对象的属性是Rasterio的实例 CRS 上课和工作很好 pyproj .

>>> from pyproj import Proj, transform
>>> src = rasterio.open('example.tif')
>>> transform(Proj(src.crs), Proj('+init=epsg:3857'), 101985.0, 2826915.0)
(-8789636.707871985, 2938035.238323653)

标签

gdal元数据项在栅格中称为“标记”。给定gdal元数据命名空间的标记集表示为dict。

>>> src.tags()
{'AREA_OR_POINT': 'Area'}
>>> src.tags(ns='IMAGE_STRUCTURE')
{'INTERLEAVE': 'PIXEL'}

gdal默认和 IMAGE_STRUCTURE 名称空间在http://www.gdal.org/gdal_datamodel.html中描述。Rasterio使用自己的几个名称空间: rio_creation_kwdsrio_overviews ,每个都有自己的语义。

偏移量和窗口

Rasterio为gdal没有的栅格数组的子集或窗口添加了一个抽象。窗口是一对元组,第一对是窗口开始和停止时的栅格行索引,第二对是窗口开始和停止时的列索引。列前的行,如 ndarray 片。的实例 Window 通过传递用于 gdal 到类构造函数。

src = rasterio.open('example.tif')

xoff, yoff = 0, 0
xsize, ysize = 10, 10
subset = src.read(1, window=Window(xoff, yoff, xsize, ysize))

有效数据屏蔽

Rasterio为每个数据集提供一个数组,用与gdal相同的指标表示其有效的数据掩码: 0 对于无效数据和 255 以获取有效数据。

>>> src = rasterio.open('example.tif')
>>> src.dataset_mask()
array([[0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       ...,
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0]], dtype-uint8)

数据集带的数组也可以作为numpy masked_array .

>>> src.read(1, masked=True)
masked_array(data =
 [[-- -- -- ..., -- -- --]
  [-- -- -- ..., -- -- --]
  [-- -- -- ..., -- -- --]
  ...,
  [-- -- -- ..., -- -- --]
  [-- -- -- ..., -- -- --]
  [-- -- -- ..., -- -- --]],
             mask =
 [[ True  True  True ...,  True  True  True]
  [ True  True  True ...,  True  True  True]
  [ True  True  True ...,  True  True  True]
  ...,
  [ True  True  True ...,  True  True  True]
  [ True  True  True ...,  True  True  True]
  [ True  True  True ...,  True  True  True]],
        fill_value = 0)

屏蔽数组的位置 maskTrue ,数据无效,已按gdal的掩码的相反意义屏蔽“out”。

错误和异常

Rasterio总是在发生错误时引发python异常,从不返回错误代码或 None 指示错误。 gdal 采用相反的方法,尽管开发人员可以通过调用 gdal.UseExceptions() .