파이썬을 사용하여 래스터에서 각 픽셀의 XY 좌표와 셀 값을 얻는 방법은 무엇입니까?


16

나는 Python을 처음 접했고 ArcGIS 10에서 Python을 사용하여 픽셀 단위로 래스터의 셀 값과 좌표 (각 픽셀 중심의 XY 좌표를 매핑)를 얻는 빠른 방법이 있는지 알고 싶습니다.

이것을 더 설명하려면 첫 번째 픽셀의 맵 X, 맵 Y 및 셀 값을 가져 와서 세 개의 변수에 세 개의 값을 할당하고 나머지 픽셀 (전체 래스터를 통해 반복)에 대해이 단계를 반복해야합니다.


내 질문에 대해 더 자세히 설명해야한다고 생각합니다. 문제는 첫 번째 래스터 픽셀의 XY 위치를 가져와 해당 XY 위치에 해당하는 다른 여러 래스터의 셀 값을 가져와야한다는 것입니다. 이 프로세스는 중간 점 모양 파일을 만들지 않고 첫 번째 래스터의 모든 픽셀을 반복해야합니다 .80 억 픽셀의 래스터를 처리해야하기 때문에 실제로 시간이 많이 걸리기 때문입니다. 또한 ArcGIS 10에서 Python을 사용 하여이 작업을 수행해야합니다.

@ 제임스 : 당신의 제안에 대단히 감사합니다. 예, 이것은 하나의 래스터에서 작동하지만 다른 여러 래스터의 셀 값도 수집해야합니다. 문제는 첫 번째 래스터의 첫 번째 픽셀의 X 및 Y 좌표를 얻은 후에 해당 X, 첫 번째 래스터의 Y 위치, 세 번째 래스터 등에 해당하는 두 번째 래스터의 셀 값을 가져와야한다는 것입니다. 따라서 첫 번째 래스터를 반복 할 때 픽셀의 X 및 Y 위치를 가져오고 해당 위치에 해당하는 다른 래스터의 셀 값을 가져 오는 것이 동시에 수행되어야하지만 확실하지 않습니다. ArcGIS 10에서 첫 번째 래스터를 점 모양 파일로 변환하고 다중 값 추출을 점 함수로 수행하면됩니다.

@ hmfly : 감사합니다. 예.이 방법 (RastertoNumpyarray)은 배열의 알려진 행 및 열 값의 좌표를 얻을 수 있으면 작동합니다.

@ whuber : 계산을하고 싶지 않습니다 .XY 좌표와 셀 값을 텍스트 파일에 쓰는 것만으로 충분합니다.


아마도 전체 래스터에서 수학을하고 싶습니까? 래스터 계산기는 픽셀 단위로 작동합니다.
BWill

1
보다 자세한 목적을 설명하십시오.
BWill

일반적으로 점을 반복하는 대신 Map Algebra 연산을 사용하여 효율적이고 안정적인 솔루션을 얻을 수 있습니다. Spatial Analyst의 맵 대수 구현의 한계는 모든 경우에이 접근법이 작동하지 못하게하지만 놀랍게도 많은 상황에서 루프를 코딩 할 필요는 없습니다. 정확히 어떤 계산을 수행해야합니까?
whuber

편집을 다시하십시오 : 물론 그것은 합법적 인 목적입니다. 이 형식은 파이프 라인 아래로 소프트웨어가 필요할 때 적용 할 수 있습니다. 그러나 80 억 (X, Y, value1, ..., value3) 튜플을 작성하려면 2,240 억 바이트 (2 진)에서 400 억 바이트 (ASCII) 사이가 필요하며, 둘 중 어느 쪽이든 다소 큰 데이터 세트가 필요합니다. 궁극적으로 달성하려는 목표에 대한 대안을 찾는 것이 좋습니다!
whuber

답변:


11

@Dango의 아이디어에 따라 다음 코드를 만들고 같은 크기와 셀 크기를 가진 작은 래스터에서 테스트했습니다.

import arcpy, numpy

inRaster = r"C:\tmp\RastersArray.gdb\InRaster"
inRaster2 = r"C:\tmp\RastersArray.gdb\InRaster2"

##Get properties of the input raster
inRasterDesc = arcpy.Describe(inRaster)

#coordinates of the lower left corner
rasXmin = inRasterDesc.Extent.Xmin
rasYmin = inRasterDesc.Extent.Ymin

# Cell size, raster size
rasMeanCellHeight = inRasterDesc.MeanCellHeight
rasMeanCellWidth = inRasterDesc.MeanCellWidth
rasHeight = inRasterDesc.Height
rasWidth = inRasterDesc.Width

##Calculate coordinates basing on raster properties
#create numpy array of coordinates of cell centroids
def rasCentrX(rasHeight, rasWidth):
    coordX = rasXmin + (0.5*rasMeanCellWidth + rasWidth)
    return coordX
inRasterCoordX = numpy.fromfunction(rasCentrX, (rasHeight,rasWidth)) #numpy array of X coord

def rasCentrY(rasHeight, rasWidth):
    coordY = rasYmin + (0.5*rasMeanCellHeight + rasHeight)
    return coordY
inRasterCoordY = numpy.fromfunction(rasCentrY, (rasHeight,rasWidth)) #numpy array of Y coord

#combine arrays of coordinates (although array for Y is before X, dstack produces [X, Y] pairs)
inRasterCoordinates = numpy.dstack((inRasterCoordY,inRasterCoordX))


##Raster conversion to NumPy Array
#create NumPy array from input rasters 
inRasterArrayTopLeft = arcpy.RasterToNumPyArray(inRaster)
inRasterArrayTopLeft2 = arcpy.RasterToNumPyArray(inRaster2)

#flip array upside down - then lower left corner cells has the same index as cells in coordinates array
inRasterArray = numpy.flipud(inRasterArrayTopLeft)
inRasterArray2 = numpy.flipud(inRasterArrayTopLeft2)


# combine coordinates and value
inRasterFullArray = numpy.dstack((inRasterCoordinates, inRasterArray.T))

#add values from second raster
rasterValuesArray = numpy.dstack((inRasterFullArray, inRasterArray2.T))

@hmfly 코드를 기반으로 원하는 값에 액세스 할 수 있습니다.

(height, width, dim )=rasterValuesArray.shape
for row in range(0,height):
    for col in range(0,width):
        #now you have access to single array of values for one cell location

불행히도 하나의 '하지만'이 있습니다-코드는 시스템 메모리로 처리 할 수있는 NumPy 배열에 적합합니다. 내 시스템 (8GB)의 경우 가장 큰 배열은 약 9000,9000입니다.

내 경험으로 더 많은 도움을받을 수 없으므로 큰 배열을 다루는 것에 대한 제안을 고려할 수 있습니다 : https : //.com/questions/1053928/python-numpy-very-large-matrices

arcpy.RasterToNumPyArray이 방법을 사용하면 NumPy 배열로 변환 된 래스터의 하위 집합 ( ArcGIS10 도움말 페이지 ) 을 지정하여 큰 데이터 집합을 하위 행렬로 청킹 할 때 유용 할 수 있습니다.


Marcin의 코드는 슈퍼입니다! 고마워하지만 래스터와 동일한 해상도로 래스터의 X, Y를 쓰지 않습니다. 나는 x와 y가 1m가되고 100m가 아니라는 것을 의미합니다. 고마워

7

(행, 열)을 통해 픽셀 값을 얻으려면 다음과 같이 arcpy 스크립트를 작성할 수 있습니다.

import arcpy
raster = arcpy.Raster("yourfilepath")
array = arcpy.RasterToNumPyArray(raster)
(height, width)=array.shape
for row in range(0,height):
    for col in range(0,width):
        print str(row)+","+str(col)+":"+str(array.item(row,col))

그러나 픽셀의 좌표를 얻으려면 NumPyArray가 도움이 될 수 없습니다. RasterToPoint Tool을 사용하여 래스터를 포인트로 변환 한 다음 Shape를 기준으로 좌표를 얻을 수 있습니다.


7

좌표 및 셀 값을 ArcGIS 10에서 텍스트 파일로 출력하는 가장 간단한 방법은 샘플 함수 이며 코드가 필요 없으며 특히 각 셀을 반복 할 필요가 없습니다. 으로 는 ArcGIS <= 9.3 래스터 계산기는 단순하게되도록 사용 outfile.csv = sample(someraster)되는 것 출력 (Z, X, Y의 형식) 모두 (비 NULL) 값 및 셀 좌표 텍스트 파일. ArcGIS 10에서는 "in_location_data"인수가 필수 인 것처럼 보이므로 구문을 사용해야합니다 Sample(someraster, someraster, outcsvfile).

편집 : 여러 래스터를 지정할 수도 있습니다 : Sample([someraster, anotherraster, etc], someraster, outcsvfile). 이것이 80 억 셀에서 작동하는지 여부에 대해서는 아무것도 모른다 ...

편집 : 참고, ArcGIS 10에서는 이것을 테스트하지 않았지만 <= 9.3 (및 워크 스테이션)에서 몇 년 동안 샘플 기능을 사용했습니다.

편집 : 이제 ArcGIS 10에서 테스트했으며 텍스트 파일로 출력되지 않습니다. 이 도구는 파일 확장자를 ".dbf"로 자동 변경합니다. 그러나 ... 다음 파이썬 코드는 SOMA 및 MOMA 로 작동합니다. 맵 대수 문이 ArcGIS 10에서 여전히 지원되므로 .

import arcgisscripting
gp=arcgisscripting.create()
gp.multioutputmapalgebra(r'%s=sample(%s)' % (outputcsv,inputraster))

아주 좋아요 이것을 지적 해 주셔서 감사합니다-나는 전에이 도구를 보지 못했습니다. 내 솔루션보다 훨씬 깔끔하고 간단합니다!
JamesS

6

이 작업을 수행하는 한 가지 방법은 사용하는 것입니다 Raster_To_Point에 의해 다음 도구 Add_XY_Coordinates의 도구를. 속성 테이블의 각 행이 래스터의 픽셀을 X_Coord 에 대한 열로 나타내는 shapefile로 끝납니다 . Y_CoordCell_Value에 . 그런 다음 커서를 사용하여이 테이블을 반복하거나 원하는 경우 Excel과 같은 형식으로 내보낼 수 있습니다.

처리 할 래스터가 하나 뿐인 경우 스크립팅 할 가치가 없습니다. ArcToolbox의 도구를 사용하십시오. 많은 래스터에 대해이 작업을 수행해야하는 경우 다음과 같이 시도 할 수 있습니다.

[ 참고 : ArcGIS 10이없고 ArcPy에 익숙하지 않으므로 매우 개략적 인 개요입니다. 테스트를 거치지 않았으며 제대로 작동하려면 조정이 필요합니다.]

import arcpy, os
from arcpy import env

# User input
ras_fold = r'path/to/my/data'           # The folder containing the rasters
out_fold = r'path/to/output/shapefiles' # The folder in which to create the shapefiles

# Set the workspace
env.workspace = ras_fold

# Get a list of raster datasets in the raster folder
raster_list = arcpy.ListRasters("*", "All")

# Loop over the rasters
for raster in raster_list:
    # Get the name of the raster dataset without the file extension
    dataset_name = os.path.splitext(raster)[0]

    # Build a path for the output shapefile
    shp_path = os.path.join(out_fold, '%s.shp' % dataset_name)

    # Convert the raster to a point shapefile
    arcpy.RasterToPoint_conversion(raster, shp_path, "VALUE")

    # Add columns to the shapefile containing the X and Y co-ordinates
    arcpy.AddXY_management(shp_path)

그런 다음 검색 커서를 사용 하거나 dbfpy를 사용하여 shapefile 속성 테이블을 반복 할 수 있습니다 . 이를 통해 래스터 (현재 shapefile .dbf 테이블에 저장 됨)의 데이터를 파이썬 변수로 읽을 수 있습니다.

from dbfpy import dbf

# Path to shapefile .dbf
dbf_path = r'path\to\my\dbf_file.dbf'

# Open the dbf file
db = dbf.Dbf(dbf_path)

# Loop over the records
for rec in db:
    cell_no = rec['POINTID'] # Numbered from top left, running left to right along each row
    cell_x = rec['POINT_X']
    cell_y = rec['POINT_Y']
    cell_val = rec['GRID_CODE']

    # Print values
    print cell_no, cell_x, cell_y, cell_val

3

어쩌면 래스터에 대한 월드 파일을 만들고 래스터를 numpy 배열로 숨길 수 있습니다. 그런 다음 배열을 반복하면 셀 값이 표시되고 월드 파일에서 x, y를 크림색으로 업데이트하면 각 셀 값에 대한 좌표도 갖게됩니다. 그것이 도움이되기를 바랍니다.


JamesS가 제안한 Raster to Point 도구 방법에 관심이 없다면 이것이 방법이라고 말할 것입니다.
nmpeterson 2019

3

Marcin의 코드는 rasCentrX 및 rasCentrY 함수의 문제를 제외하고 출력 좌표가 다른 해상도로 나타납니다 (Grazia가 관찰 한 것처럼). 내 수정은 바뀌었다

coordX = rasXmin + (0.5*rasMeanCellWidth + rasWidth)

coordX = rasXmin + ((0.5 + rasWidth) * rasMeanCellWidth)

  coordY = rasYmin + (0.5*rasMeanCellHeight + rasHeight)

  coordY = rasYmin + ((0.5 + rasHeight) * rasMeanCellHeight)

코드를 사용하여 ESRI Grid를 CSV 파일로 변환했습니다. inRaster2에 대한 참조를 제거한 다음 csv.writer를 사용하여 좌표와 값을 출력하면됩니다.

out = csv.writer(open(outputCSV,"wb"), delimiter=',', quoting=csv.QUOTE_NONNUMERIC)
out.writerow(['X','Y','Value'])
(height, width, dim )=inRasterFullArray.shape
for row in range(0,height):
    for col in range(0,width):
        out.writerow(inRasterFullArray[row,col])

또한 전치사가 필요한 것을 찾지 못했습니다.

inRasterFullArray = numpy.dstack((inRasterCoordinates, inRasterArray.T))

그래서 그것을

inRasterFullArray = numpy.dstack((inRasterCoordinates, inRasterArray))

2

추악하지만 매우 효과적인 :

  1. 문제의 래스터 모서리 외부에 4 개의 점이있는 새 점 피처를 만듭니다. 해당 래스터와 동일한 좌표계를 사용해야합니다.
  2. 'xcor'및 'ycor'이중 필드 추가
  3. 이 필드의 좌표를 얻기 위해 지오메트리 계산
  4. 공간 분석가-> 보간 -> 추세 -> 선형 회귀
  5. 환경 설정 : 문제의 래스터와 동일하게 래스터 및 셀 크기 스냅
  6. 'xcor'및 'ycor'에 대해 별도로 실행
  7. 셀 값으로 좌표를 가진 평가자가 나오면 스크립트의 입력으로 사용하십시오.

2

오픈 소스 파이썬 패키지를 사용하는 간단한 솔루션 :

import fiona
import rasterio
from pprint import pprint


def raster_point_coords(raster, points):

    # initialize dict to hold data
    pt_data = {}

    with fiona.open(points, 'r') as src:
        for feature in src:
            # create dict entry for each feature
            pt_data[feature['id']] = feature

    with rasterio.open(raster, 'r') as src:
        # read raster into numpy array
        arr = src.read()
        # rasterio always reads into 3d array, this is 2d, so reshape
        arr = arr.reshape(arr.shape[1], arr.shape[2])
        # get affine, i.e. data needed to work between 'image' and 'raster' coords
        a = src.affine

    for key, val in pt_data.items():
        # get coordinates
        x, y = val['geometry']['coordinates'][0], val['geometry']['coordinates'][1]
        # use affine to convert to row, column
        col, row = ~a * (x, y)
        # remember numpy array is indexed array[row, column] ie. y, x
        val['raster_value'] = arr[int(row), int(col)]

    pprint(pt_data) 

if __name__ == '__main__':
    # my Landsat raster
    ras = '/data01/images/sandbox/LT05_040028_B1.tif'
    # my shapefile with two points which overlap raster area
    pts = '/data01/images/sandbox/points.shp'
    # call function
    raster_point_coords(ras, pts)

Fiona는 셰이프 파일을 열고 피처를 반복하여 dict객체에 추가 할 수있어 편리 합니다. 실제로 피오나 feature자체는dict 하므로 속성에 쉽게 액세스 할 수 있습니다. 내 포인트에 속성이 있으면 좌표, id 등과 함께이 dict에 나타납니다.

Rasterio는 래스터에서 numpy 배열, 가볍고 빠른 데이터 유형으로 쉽게 읽을 수 있기 때문에 편리합니다. 또한 래스터 x, y 좌표를 배열 행 col 좌표로 변환하는 데 필요한 모든 데이터 인을 dict포함한 래스터 속성에 액세스 할 수 있습니다 affine. @perrygeo의 훌륭한 설명은 여기를 참조 하십시오 .

우리는 각 포인트에 대한 데이터를 가지고 있고 추출 된 pt_data타입으로 끝납니다 . 원한다면 추출 된 데이터로 shapefile을 쉽게 다시 작성할 수 있습니다.dictraster_value

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.