Transforms

Rasterio supports three primary methods for transforming of coordinates from image pixel (row, col) to and from geographic/projected (x, y) coordinates. The interface for performing these coordinate transformations is available in rasterio.transform through one of AffineTransformer, GCPTransformer, or RPCTransformer. The methods xy() and rowcol() are responsible for converting between (row, col) -> (x, y) and (x, y) -> (row, col), respectively.

Using Affine transformation matrix

AffineTransformer takes care of coordinate transformations given an Affine transformation matrix. For example

>>> transform = Affine(300.0379266750948, 0.0, 101985.0, 0.0,
                       -300.041782729805, 2826915.0)
>>> transformer = rasterio.transform.AffineTransformer(transform)
>>> transformer.xy(0, 0)
(102135.01896333754, 2826764.979108635)
>>> transformer.rowcol(102135.01896333754, 2826764.979108635)
(0, 0)

This is approximately equivalent to

>>> transform = Affine(300.0379266750948, 0.0, 101985.0, 0.0,
                       -300.041782729805, 2826915.0)
>>> transform * (0.5, 0.5)
(102135.01896333754, 2826764.979108635)
>>> ~transform * (102135.01896333754, 2826764.979108635)
(0.5, 0.5)

The dataset methods xy() and index() use rasterio.transform under the hood

>>> with rasterio.open('RGB.byte.tif') as src:
        print(src.xy(0, 0))
(102135.01896333754, 2826764.979108635)

Using Ground Control Points

>>> gcps = [GroundControlPoint(row=11521.5, col=0.5, x=-123.6185142817931, y=48.99561141948625, z=89.13533782958984, id='217', info=''),
            GroundControlPoint(row=11521.5, col=7448.5, x=-122.8802747777599, y=48.91210259315549, z=89.13533782958984, id='234', info=''),
            GroundControlPoint(row=0.5, col=0.5, x=-123.4809665720148, y=49.52809729106944, z=89.13533782958984, id='1', info=''),
            GroundControlPoint(row=0.5, col=7448.5, x=-122.7345733674704, y=49.44455878004666, z=89.13533782958984, id='18', info='')]
>>> transformer = rasterio.transform.GCPTransformer(gcps)
>>> transformer.xy(0, 0)
(-123.478928146887, 49.52808986989645)

Using Rational Polynomial Coefficients

For accuracy a height value is typically required when using RPCTransformer. By default, a value of 0 is assumed.

>>> with rasterio.open('RGB.byte.rpc.vrt') as src:
        transformer = rasterio.transform.RPCTransformer(src.rpcs)
        transformer.xy(0, 0)
(-123.47959047080701, 49.52794990575094)

A constant height offset can be specified using the rpc_height keyword argument. This is useful for datasets with little elevation change. In this case, rpc_height is assumed to be an average height above sea level for ground in the target scene, while zs is the height above ground of coordinates.

>>> with rasterio.open('RGB.byte.rpc.vrt') as src:
        # 100 meters above sea level
        transformer = rasterio.transform.RPCTransformer(src.rpcs, rpc_height=100)
        transformer.xy(0, 0, zs=0)
(-123.4811362101663, 49.52811584352445)

When a constant height offset is not sufficient, sample height values from a digital elevation model (DEM). using the rpc_dem keyword argument. RPCTransformer allows for options to be passed to GDALCreateRPCTransformerV2()

>>> with rasterio.open('RGB.byte.rpc.vrt') as src:
        transformer = rasterio.transform.RPCTransformer(src.rpcs, rpc_dem='vancouver-dem.tif')
        transformer.xy(0, 0)
(-123.47954729595642, 49.5279448909449)

Transformer Resources

The AffineTransformer is a pure Python class, however GCPTransformer and RPCTransformer make use of C/C++ GDAL objects. Explicit control of the transformer object can be achieved by use within a context manager or by calling close() method e.g.

>>> with rasterio.transform.RPCTransformer(rpcs) as transform:
        transform.xy(0, 0)
>>> transform.xy(0, 0)
ValueError: Unexpected NULL transformer

Note

If RPC_DEM is specified in rpc_options, GDAL will maintain an open file handle to the DEM until the transformer is closed.