NumPy없이 OGR 포인트에서 GDAL 래스터의 픽셀 값을 얻습니까?


45

나는 조경을 가로 지르는 풍부한 야생 수분 조절제의 계산 모델을 연구하고 있습니다. 모델 자체가 완성되었으므로 이제 사후 처리 단계로 어려움을 겪고 있습니다.

GDAL pollinator 공급 래스터가 다음과 같이 보입니다 (색이 밝을수록 pollinator가 픽셀을 더 많이 방문합니다).

풍경에 수분 공급 장치를 나타내는 회색조 래스터

그리고 풍경의 샘플 위치를 나타내는 점의 OGR shapefile이 있습니다.

여기에 이미지 설명을 입력하십시오

이 포인트 아래의 픽셀에 대한 분석을 시도하고 있지만 그렇게하려면 포인트 아래의 픽셀 값을 추출 할 수 있어야합니다.

파이썬을 통해 OGR 및 GDAL 만 사용하여 포인트 아래에서 픽셀 값을 추출 할 수 있습니까? ReadAsArray()출력 래스터가 매우 크고 (메모리에 너무 커서) 래스터 전체를 메모리로 읽는 것을 피하고 싶습니다.

이 게시물 은 비슷하지만 명령 줄 호출이 필요하다는 것을 알았 습니다 .


2
ReadAsArray ()는 어떻습니까? 관심있는 단일 셀만 읽으십니까? 점 좌표에서 픽셀 공간으로 변환하고 필요한 셀을 추출해야합니다.
Jay Laura

1
gdalsrsinfo의 코드를 살펴보면 GDALInvertGeoTransform ()을 사용하고 지리적 공간과 픽셀 공간 사이를 전환하는 방법을 보여줍니다. trac.osgeo.org/gdal/browser/trunk/gdal/apps/gdalsrsinfo.cpp

PostGIS 사용 마음에 들지 않으면 이것을 참조 하십시오 . 매우 빠르며 단지 1 SQL 라인입니다.
mlt

이 문제가 발생하여 PostGIS 데이터베이스에 액세스 할 수 있으면이 점을 명심하겠습니다. 나는이 특정 문제에 대해하지 않았으므로 아래 GDAL 솔루션이 트릭을 수행했습니다. 그래도 고마워!
James

@kyle 일을 변경 한 경우 나도 몰라하지만 그것이 것 같습니다 GDALInvGeoTransform가 되지 반전 하고 이 예입니다 .
mlt

답변:


60

gdal.Dataset 또는 gdal.Band ReadRaster 메소드를 사용할 수 있습니다 . 참고 항목 GDALOGR API 자습서 아래의 예를. ReadRaster는 numpy를 사용 / 요구하지 않으며 반환 값은 원시 이진 데이터이며 표준 python struct 모듈을 사용하여 압축을 풀어야 합니다.

예를 들면 :

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, 테이블 또는 다른 객체로 저장할 수 있습니까? 같은 길이의 좌표를 가진 물체 objetct
gonzalez.ivan90

질문이 있습니다, 루크 감사! gis.stackexchange.com/questions/269603/…
gonzalez.ivan90

라인이 할당은 px/ py그 MX /의 경계 외부에서 내 거짓말 경우 잘못 rb때문에 int(-0.5) == 0. 당신이 필요 floor(...)하고 당신은 어느 쪽의 확인해야 px/ py0보다 작은 수 있습니다 (또는 호출하기 전에 그것을 int()부정적인 인덱스 작업이 (가 배열의 다른 측면을 얻을) 때문에). 이 문제를 해결하는 더 좋은 방법이 있는지 알고 싶습니다. 또한 회전을 올바르게 처리하도록 해당 선을 어떻게 다시 작성합니까?
naught101
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.