Отримання значення пікселя растру GDAL під точкою OGR без NumPy?


45

Я працюю над обчислювальною моделлю кількості диких запилювачів у ландшафті. Сама модель завершена, і я зараз борюся з кроком після обробки.

У мене є растр подачі запитувачів GDAL, який виглядає приблизно так (світліші кольори означають більшу відвідуваність пікселя):

Растровий відтінок сірого кольору, що представляє запас запилювача на ландшафті

І у мене є таблиця форм ОГР точок, що представляють зразкові місця на пейзажі:

введіть тут опис зображення

Я намагаюся провести деякий аналіз пікселів під цими точками, але для цього мені потрібно мати можливість витягти значення пікселя під крапкою.

Чи можливо витягнути значення пікселя під точкою, використовуючи лише OGR та GDAL через Python? Я вважаю за краще уникати читання всього растру в пам'яті ReadAsArray(), оскільки мої растрові вихідні дані дуже великі (занадто великі, щоб вписатись у пам'ять).

Я помітив цю публікацію , яка схожа, але вимагає виклику командного рядка.


2
А як щодо ReadAsArray () та лише читання в точці? Тож читайте лише одну осередку, яка вас цікавить? Вам потрібно буде перетворити з точкових координат у піксельний простір і витягти необхідну комірку.
Джей Лора

1
Подивіться на код gdalsrsinfo, він показує вам, як використовувати GDALInvertGeoTransform () та перемикатися між географічним простором та піксельним простором: trac.osgeo.org/gdal/browser/trunk/gdal/apps/gdalsrsinfo.cpp

Якщо ви не проти використовувати PostGIS, дивіться це . Це надзвичайно швидко і складає всього 1 рядок SQL.
mlt

Я маю це на увазі, якщо я зіткнуся з цією проблемою та отримаю доступ до бази даних PostGIS! Я не мав для цієї конкретної проблеми, тому рішення GDAL нижче зробило свою справу. Дякую, хоча!
Джеймс

@kyle Я не знаю, чи все змінилося, але схоже, що це GDALInvGeoTransform не інвертується, і це є прикладом .
mlt

Відповіді:


61

Ви можете використовувати метод gdal.Dataset або gdal.Band ReadRaster. Дивіться підручники API GDAL та OGR та приклад нижче. ReadRaster не використовує / не вимагає numpy, повернене значення - це необроблені двійкові дані і його потрібно розпакувати за допомогою стандартного модуля структури python .

Приклад:

from osgeo import gdal,ogr
import struct

src_filename = '/tmp/test.tif'
shp_filename = '/tmp/test.shp'

src_ds=gdal.Open(src_filename) 
gt=src_ds.GetGeoTransform()
rb=src_ds.GetRasterBand(1)

ds=ogr.Open(shp_filename)
lyr=ds.GetLayer()
for feat in lyr:
    geom = feat.GetGeometryRef()
    mx,my=geom.GetX(), geom.GetY()  #coord in map units

    #Convert from map to pixel coordinates.
    #Only works for geotransforms with no rotation.
    px = int((mx - gt[0]) / gt[1]) #x pixel
    py = int((my - gt[3]) / gt[5]) #y pixel

    structval=rb.ReadRaster(px,py,1,1,buf_type=gdal.GDT_UInt16) #Assumes 16 bit int aka 'short'
    intval = struct.unpack('h' , structval) #use the 'short' format code (2 bytes) not int (4 bytes)

    print intval[0] #intval is a tuple, length=1 as we only asked for 1 pixel value

Крім того, оскільки причина, яку ви не використовували, numpyполягала в тому, щоб уникнути читання всього масиву при використанні ReadAsArray(), нижче наведений приклад, який використовує numpyі не читає весь растр в.

from osgeo import gdal,ogr
import struct

src_filename = '/tmp/test.tif'
shp_filename = '/tmp/test.shp'

src_ds=gdal.Open(src_filename) 
gt=src_ds.GetGeoTransform()
rb=src_ds.GetRasterBand(1)

ds=ogr.Open(shp_filename)
lyr=ds.GetLayer()
for feat in lyr:
    geom = feat.GetGeometryRef()
    mx,my=geom.GetX(), geom.GetY()  #coord in map units

    #Convert from map to pixel coordinates.
    #Only works for geotransforms with no rotation.
    px = int((mx - gt[0]) / gt[1]) #x pixel
    py = int((my - gt[3]) / gt[5]) #y pixel

    intval=rb.ReadAsArray(px,py,1,1)
    print intval[0] #intval is a numpy array, length=1 as we only asked for 1 pixel value

І як можна зберегти як csv, table чи інший об’єкт? Об'єкт з однаковою довжиною координат об'єкта
gonzalez.ivan90

Ось питання, Лука. Дякую! gis.stackexchange.com/questions/269603/…
gonzalez.ivan90

рядки, які присвоюють px/ pyнеправильні в тому випадку, якщо mx / my лежить поза межами rb, тому що int(-0.5) == 0. Вам потрібно floor(...), а потім вам потрібно перевірити, що жоден з px/ pyне менший за нуль (або зробіть це перед тим, як зателефонувати int()), оскільки негативні показники працюють (вони отримують іншу сторону масиву). Мені б хотілося дізнатись, чи є охайніший спосіб вирішення цієї проблеми. Крім того, як ви переписуєте ці рядки, щоб вони правильно поводилися з обертаннями?
naught101
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.