[Gdal-dev] Numpy and GDAL

Frank Warmerdam warmerdam at pobox.com
Mon Jan 20 17:29:50 EST 2003


Folks,

I haven't really mastered the zen of Numpy (aka Numeric), the array math
package for Python, but I did a nice hack today that I thought might be of
interest to some others.  The requirement was to add "nodata" support to
the gdal_merge.py script, a simple script to merge a bunch of raster files
into one mosaic.

This devolves down to a function call to copy a rectangle of data from a
source file to a destination file.  I changed it to look like this:

# =============================================================================
def raster_copy_with_nodata( s_fh, s_xoff, s_yoff, s_xsize, s_ysize, s_band_n,
                              t_fh, t_xoff, t_yoff, t_xsize, t_ysize, t_band_n,
                              nodata ):

     if verbose != 0:
         print 'Copy %d,%d,%d,%d to %d,%d,%d,%d.' \
               % (s_xoff, s_yoff, s_xsize, s_ysize,
              t_xoff, t_yoff, t_xsize, t_ysize )

     s_band = s_fh.GetRasterBand( s_band_n )
     t_band = t_fh.GetRasterBand( t_band_n )

     data_src = s_band.ReadAsArray( s_xoff, s_yoff, s_xsize, s_ysize,
                                    t_xsize, t_ysize )
     data_dst = t_band.ReadAsArray( t_xoff, t_yoff, t_xsize, t_ysize )

     nodata_test = Numeric.equal(data_src,nodata)
     to_write = Numeric.choose( nodata_test, (data_src, data_dst) )

     t_band.WriteArray( to_write, t_xoff, t_yoff )

     return 0

The key items are:
  o Read source window as an "array" at the same resolution as the output
    window.
  o Read the existing data in the destination file for the target window
    as an array.
  o Create an array of 0/1 values indicating which pixels in the source
    array match the nodata value - "Numeric.equal(data_src,nodata)" where
    nodata is a simple scalar.
  o Use the Numeric.choose() function to choose the existing target file
    value where the test returned 1, and the source data where it returned 0.
  o Write to destination file.

The nice thing is that Numeric.equal() and Numeric.choose() are internally
implemented in C so there is no per-pixel python script evaluation going on.

Note that the Numeric.choose() function can take a longer vector of values.
For instance, you could have a 256 entry lut and use an 8bit input image
array to do a lookup in the lut.

Pretty nice stuff!

PS. I have committed a change to gdal_merge.py so that it now supports
"nodata" values ... pixel values in the source image that should not be
copied to the merged image.

Later,

-- 
---------------------------------------+--------------------------------------
I set the clouds in motion - turn up   | Frank Warmerdam, warmerdam at pobox.com
light and sound - activate the windows | http://pobox.com/~warmerdam
and watch the world go round - Rush    | Geospatial Programmer for Rent





More information about the Gdal-dev mailing list