Python gdal을 사용하여 GeoTiff에서 좌표 및 해당 픽셀 값을 가져 와서 numpy 배열로 저장하십시오


10

GeoTiff 파일에서 해당 좌표의 투영 된 좌표와 실제 픽셀 값을 구한 다음 numpy 배열로 저장하려면 어떻게해야합니까? arsenci020l.tif 파일이 있고 그 좌표는 미터입니다. 아래는 내가 실행 한 gdalinfo의 요약 된 출력입니다.

~$ gdalinfo arsenci020l.tif 
Driver: GTiff/GeoTIFF
Files: arsenci020l.tif
       arsenci020l.tfw
Size is 10366, 7273
Coordinate System is:
PROJCS["Lambert Azimuthal Equal Area projection with arbitrary plane grid; projection center 100.0 degrees W, 45.0 degrees N",
    GEOGCS["WGS 84",
        DATUM["WGS_1984",
            SPHEROID["WGS 84",6378137,298.257223563,
                AUTHORITY["EPSG","7030"]],
            AUTHORITY["EPSG","6326"]],
        PRIMEM["Greenwich",0],
        UNIT["degree",0.0174532925199433],
        AUTHORITY["EPSG","4326"]],
    PROJECTION["Lambert_Azimuthal_Equal_Area"],
    PARAMETER["latitude_of_center",45],
    PARAMETER["longitude_of_center",-100],
    PARAMETER["false_easting",0],
    PARAMETER["false_northing",0],
    UNIT["metre",1,
        AUTHORITY["EPSG","9001"]]]
Origin = (-6086629.000000000000000,4488761.000000000000000)
Pixel Size = (1000.000000000000000,-1000.000000000000000)
...

tiff에서 위도 / 경도 좌표를 얻는 방법 (GeoTIFF 파일에서 위도 및 경도 얻기)에 대한 비슷한 질문이 있었고 대답은 상단 왼쪽 x 및 y 픽셀 좌표 만 얻는 방법을 보여주었습니다. 픽셀 값을 가져 와서 numpy 배열로 저장하는 것뿐만 아니라 모든 투영 된 픽셀 좌표를 가져와야합니다. 어떻게하니?


10366 × 7273 = 7,500 만 포인트 이상을 원하십니까?
Mike T

@MikeT 그렇게 생각합니다. 나는 해결하려는 문제에 접근하는 방법에 대한 더 나은 해결책을 모른다.이 데이터 세트에서 미국 블록의 각 중심까지 가장 가까운 픽셀 좌표를 찾은 다음 검색을 통해 cKDTree 쿼리가 가장 가까운 이웃 검색에 도움이된다는 것을 깨달았습니다. 알고리즘의 Python 함수는 numpy 배열로 쿼리하기 위해 "트리"를 요청합니다. 이 데이터 세트의 모든 픽셀 좌표에서 어떻게 든 저장해야합니다. 더 나은 솔루션이 있으면 알려주십시오!
irakhman

답변:


7

주석으로 추가하지만 약간 길다-파이썬에서 gdal / ogr을 사용하려는 경우-이와 같은 것이 작동 할 수 있습니다 (테스트하지 않은 다른 코드와 함께 해킹되었습니다!). 가장 가까운 것을 찾는 것이 아니라 다각형 중심에 래스터 픽셀을 배치하려면 중심의 xy에서 래스터를 쿼리하면됩니다. 속도 트레이드 오프가 무엇인지 모릅니다.

from osgeo import gdal,ogr

fc='PathtoYourVector'
rast='pathToYourRaster'

def GetCentroidValue(fc,rast):
    #open vector layer
    drv=ogr.GetDriverByName('ESRI Shapefile') #assuming shapefile?
    ds=drv.Open(fc,True) #open for editing
    lyr=ds.GetLayer(0)

    #open raster layer
    src_ds=gdal.Open(rast) 
    gt=src_ds.GetGeoTransform()
    rb=src_ds.GetRasterBand(1)
    gdal.UseExceptions() #so it doesn't print to screen everytime point is outside grid

    for feat in lyr:
        geom=feat.GetGeometryRef()
        mx=geom.Centroid().GetX()
        my=geom.Centroid().GetY()

        px = int((mx - gt[0]) / gt[1]) #x pixel
        py = int((my - gt[3]) / gt[5]) #y pixel
        try: #in case raster isnt full extent
            structval=rb.ReadRaster(px,py,1,1,buf_type=gdal.GDT_Float32) #Assumes 32 bit int- 'float'
            intval = struct.unpack('f' , structval) #assume float
            val=intval[0]
        except:
            val=-9999 #or some value to indicate a fail

       feat.SetField('YOURFIELD',val)
       lyr.SetFeature(feat)

    src_ds=None
    ds=None

GetCentroidValue(fc,rast)

14

이것은 당신을 갈 것입니다. rasterio를 사용하여 래스터 값을 읽고 픽셀 중심 좌표를 affine을 사용하여 Eastings / Northings 로 변환 한 다음 pyproj를 사용하여 위도 / 경도로 변환합니다 . 대부분의 배열은 입력 래스터와 모양이 같습니다.

import rasterio
import numpy as np
from affine import Affine
from pyproj import Proj, transform

fname = '/path/to/your/raster.tif'

# Read raster
with rasterio.open(fname) as r:
    T0 = r.transform  # upper-left pixel corner affine transform
    p1 = Proj(r.crs)
    A = r.read()  # pixel values

# All rows and columns
cols, rows = np.meshgrid(np.arange(A.shape[2]), np.arange(A.shape[1]))

# Get affine transform for pixel centres
T1 = T0 * Affine.translation(0.5, 0.5)
# Function to convert pixel row/column index (from 0) to easting/northing at centre
rc2en = lambda r, c: (c, r) * T1

# All eastings and northings (there is probably a faster way to do this)
eastings, northings = np.vectorize(rc2en, otypes=[np.float, np.float])(rows, cols)

# Project all longitudes, latitudes
p2 = Proj(proj='latlong',datum='WGS84')
longs, lats = transform(p1, p2, eastings, northings)

1
이것을 사용할 때 "T0 = r.affine"줄에 대해 "AttributeError : 'DatasetReader'개체에 'affine'속성이 없습니다"라는 메시지가 표시됩니다.
mitchus

@mitchus 명백히 affine의 별칭 transform일 뿐이며 가장 최근 버전의 rasterio에서이 별칭이 제거되었습니다. 답변을 편집했지만 여기에 새로 온 이후 동료 검토가 필요한 것 같습니다. :)
Autumnsault

1
또한 A.shape2 차원 만있는에 대한 색인이 잘못된 것 같습니다 .
Autumnsault
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.