Here's a more programmatic way of using GDAL than @Aragon's answer. I've not tested it, but it is mostly boiler-plate code that has worked for me in the past. It relies on Numpy and GDAL bindings, but that's about it.
import osgeo.gdal as gdal
import osgeo.osr as osr
import numpy as np
from numpy import ma
def maFromGDAL(filename):
dataset = gdal.Open(filename, gdal.GA_ReadOnly)
if dataset is None:
raise Exception()
# Get the georeferencing metadata.
# We don't need to know the CRS unless we want to specify coordinates
# in a different CRS.
#projection = dataset.GetProjection()
geotransform = dataset.GetGeoTransform()
# We need to know the geographic bounds and resolution of our dataset.
if geotransform is None:
dataset = None
raise Exception()
# Get the first band.
band = dataset.GetRasterBand(1)
# We need to nodata value for our MaskedArray later.
nodata = band.GetNoDataValue()
# Load the entire dataset into one numpy array.
image = band.ReadAsArray(0, 0, band.XSize, band.YSize)
# Close the dataset.
dataset = None
# Create a numpy MaskedArray from our regular numpy array.
# If we want to be really clever, we could subclass MaskedArray to hold
# our georeference metadata as well.
# see here: http://docs.scipy.org/doc/numpy/user/basics.subclassing.html
# For details.
masked_image = ma.masked_values(image, nodata, copy=False)
masked_image.fill_value = nodata
return masked_image, geotransform
def pixelToMap(gt, pos):
return (gt[0] + pos[0] * gt[1] + pos[1] * gt[2],
gt[3] + pos[0] * gt[4] + pos[1] * gt[5])
# Reverses the operation of pixelToMap(), according to:
# https://en.wikipedia.org/wiki/World_file because GDAL's Affine GeoTransform
# uses the same values in the same order as an ESRI world file.
# See: http://www.gdal.org/gdal_datamodel.html
def mapToPixel(gt, pos):
s = gt[0] * gt[4] - gt[3] * gt[1]
x = (gt[4] * pos[0] - gt[1] * pos[1] + gt[1] * gt[5] - gt[4] * gt[2]) / s
y = (-gt[3] * pos[0] + gt[0] * pos[1] + gt[3] * gt[2] - gt[0] * gt[5]) / s
return (x, y)
def valueAtMapPos(image, gt, pos):
pp = mapToPixel(gt, pos)
x = int(pp[0])
y = int(pp[1])
if x < 0 or y < 0 or x >= image.shape[1] or y >= image.shape[0]:
raise Exception()
# Note how we reference the y column first. This is the way numpy arrays
# work by default. But GDAL assumes x first.
return image[y, x]
try:
image, geotransform = maFromGDAL('myimage.tif')
val = valueAtMapPos(image, geotransform, (434323.0, 2984745.0))
print val
except:
print('Something went wrong.')