Below is an example that I wrote for a workshop that utilizes the numpy and gdal Python modules. It reads data from one .tif file into a numpy array, does a reclass of the values in the array and then writes it back out to a .tif.
From your explanation, it sounds like you might have succeeded in writing out a valid file, but you just need to symbolize it in QGIS. If I remember correctly, when you first add a raster, it often shows up all one color if you don't have a pre-existing color map.
import numpy, sys
from osgeo import gdal
from osgeo.gdalconst import *
# register all of the GDAL drivers
gdal.AllRegister()
# open the image
inDs = gdal.Open("c:/workshop/examples/raster_reclass/data/cropland_40.tif")
if inDs is None:
print 'Could not open image file'
sys.exit(1)
# read in the crop data and get info about it
band1 = inDs.GetRasterBand(1)
rows = inDs.RasterYSize
cols = inDs.RasterXSize
cropData = band1.ReadAsArray(0,0,cols,rows)
listAg = [1,5,6,22,23,24,41,42,28,37]
listNotAg = [111,195,141,181,121,122,190,62]
# create the output image
driver = inDs.GetDriver()
#print driver
outDs = driver.Create("c:/workshop/examples/raster_reclass/output/reclass_40.tif", cols, rows, 1, GDT_Int32)
if outDs is None:
print 'Could not create reclass_40.tif'
sys.exit(1)
outBand = outDs.GetRasterBand(1)
outData = numpy.zeros((rows,cols), numpy.int16)
for i in range(0, rows):
for j in range(0, cols):
if cropData[i,j] in listAg:
outData[i,j] = 100
elif cropData[i,j] in listNotAg:
outData[i,j] = -100
else:
outData[i,j] = 0
# write the data
outBand.WriteArray(outData, 0, 0)
# flush data to disk, set the NoData value and calculate stats
outBand.FlushCache()
outBand.SetNoDataValue(-99)
# georeference the image and set the projection
outDs.SetGeoTransform(inDs.GetGeoTransform())
outDs.SetProjection(inDs.GetProjection())
del outData
Your PointsXYZIC
is now a numpy array. Which means you can use numpy indexing to filter the data you're interested in. For example you can use an index of booleans to determine which points to grab.
#the values we're classifying against
unclassified = 1
ground = 2
#create an array of booleans
filter_array = np.any(
[
PointsXYZIC[:, 4] == unclassified, #The final column to index against
PointsXYZIC[:, 4] == ground,
],
axis=0
)
#use the booleans to index the original array
filtered_rows = PointsXYZIC[filter_array]
You should now have a numpy array with all the values where the data is unclassified or ground. To get the values that have been classified you could use:
filter_array = np.all(
[
PointsXYZIC[:, 4] != unclassified, #The final column to index against
PointsXYZIC[:, 4] != ground,
],
axis=0
)
Best Answer
The two functions from the code snippet below,
create_raster
andnumpy_array_to_raster
should do the trick. In terms of maintaining theNoData
value from the array in the output raster, that is set on the band(s) of a raster with the.SetNoDataValue()
method which in this code snippet is used in thenumpy_array_to_raster
function. For more information about usinggdal
&numpy
for raster processing I would highly recommend Chris Garrard's book Geoprocessing with Python and for a quick reference this gdal/ogr cookbook page is a great resource.