GDAL 및 Python : 특정 값을 가진 모든 셀에 대한 좌표를 얻는 방법은 무엇입니까?


12

나는있어 아크 / 정보 이진 그리드 --- 특히,는 ArcGIS가 축적 래스터 흐름 --- 나는 특정 값을 갖는 모든 셀을 확인하고 싶습니다 (또는 값의 범위에서). 궁극적으로, 나는이 세포들을 나타내는 점들의 shapefile을 원합니다.

QGIS를 사용하여 hdr.adf를 열고이 결과를 얻을 수 있습니다. 워크 플로는 다음과 같습니다.

  • QGIS> 래스터 메뉴> 래스터 계산기 (모든 포인트를 목표 값으로 표시)
  • QGIS> 래스터 메뉴> 다각형
  • QGIS> 벡터 메뉴> 형상 하위 메뉴> 다각형 중심
  • 원치 않는 폴리 중심을 삭제하기 위해 중심을 편집하십시오 (그들 = 0)

이 접근 방식은 "작업을 수행하지만"삭제해야하는 2 개의 파일을 생성하기 때문에 마음에 들지 않습니다. 그런 다음 중심의 쉐이프 파일 (예 : 그 = 0)에서 원치 않는 레코드를 제거해야합니다.

기존의 문제는이 주제에 접근하지만, 그것은는 ArcGIS / ArcPy에 맞게 조정, 그리고 나는 FOSS 공간에 머물 싶습니다.

누구나 래스터의 셀 값을 조사하는 기존 GDAL / Python 레시피 / 스크립트가 있고 목표 값 또는 목표 범위의 값이 발견되면 레코드가 셰이프 파일에 추가됩니까? 이렇게하면 UI 상호 작용을 피할 수있을뿐만 아니라 단일 패스에서 깔끔한 결과를 얻을 수 있습니다.

Chris Garrard의 프레젠테이션 중 하나를 상대로 작업 하여 촬영 했지만 래스터 작업은 조타실에 없으며 약한 코드로 질문을 어지럽히고 싶지 않습니다.

누구든지 정확한 데이터 세트를 가지고 놀고 싶다면 여기에 .zip으로 넣습니다 .


[편집 노트] 후손을 위해 이것을 남겨 둡니다. om_henners와의 의견 교환을 참조하십시오. 기본적으로 x / y (행 / 열) 값이 뒤집 혔습니다. 원래 답변은 다음과 같습니다.

(y_index, x_index) = np.nonzero(a == 1000)

이처럼 거꾸로 :

(x_index, y_index) = np.nonzero(a == 1000)

스크린 샷에 설명 된 문제가 처음 발생했을 때 기하학을 잘못 구현했는지 궁금해 하고이 줄에서 x / y 좌표 값을 뒤집어 실험했습니다.

point.SetPoint(0, x, y)

..같이..

point.SetPoint(0, y, x)

그러나 그것은 효과가 없었습니다. 그리고 나는 om_henners의 Numpy 표현의 값을 뒤집으려고하지 않았다고 생각했습니다. I 진짜 문제는 관련된 생각 x_size하고 y_size, 각각의 값, 30-30행 및 열 인덱스는 셀에 대한 계산 된 점 좌표를 사용하는 경우에 적용된다.

[원본 편집]

@om_henners, ogr ( invisibleroads.com , Chris Garrard )을 사용하여 점 모양 파일을 만들기위한 몇 가지 레시피와 함께 귀하의 솔루션을 시도하고 있지만 점이 통과하는 것처럼 점이 나타나는 문제가 있습니다 315/135도까지.

연한 파란색 점 : 위의 QGIS 접근 방식으로 생성

퍼플 포인트 : 아래 의 GDAL / OGR py 코드로 생성

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


[해결됨]

이 Python 코드는 @om_henners가 제안한 완전한 솔루션을 구현합니다. 나는 그것을 테스트했고 작동합니다. 고마워요!


from osgeo import gdal
import numpy as np
import osgeo.ogr
import osgeo.osr

path = "D:/GIS/greeneCty/Greene_DEM/GreeneDEM30m/flowacc_gree/hdr.adf"
print "\nOpening: " + path + "\n"

r = gdal.Open(path)
band = r.GetRasterBand(1)

(upper_left_x, x_size, x_rotation, upper_left_y, y_rotation, y_size) = r.GetGeoTransform()

a = band.ReadAsArray().astype(np.float)

# This evaluation makes x/y arrays for all cell values in a range.
# I knew how many points I should get for ==1000 and wanted to test it.
(y_index, x_index) = np.nonzero((a > 999) & (a < 1001))

# This evaluation makes x/y arrays for all cells having the fixed value, 1000.
#(y_index, x_index) = np.nonzero(a == 1000)

# DEBUG: take a look at the arrays..
#print repr((y_index, x_index))

# Init the shapefile stuff..
srs = osgeo.osr.SpatialReference()
#srs.ImportFromProj4('+proj=utm +zone=15 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs')
srs.ImportFromWkt(r.GetProjection())

driver = osgeo.ogr.GetDriverByName('ESRI Shapefile')
shapeData = driver.CreateDataSource('D:/GIS/01_tutorials/flow_acc/ogr_pts.shp')

layer = shapeData.CreateLayer('ogr_pts', srs, osgeo.ogr.wkbPoint)
layerDefinition = layer.GetLayerDefn()

# Iterate over the Numpy points..
i = 0
for x_coord in x_index:
    x = x_index[i] * x_size + upper_left_x + (x_size / 2) #add half the cell size
    y = y_index[i] * y_size + upper_left_y + (y_size / 2) #to centre the point

    # DEBUG: take a look at the coords..
    #print "Coords: " + str(x) + ", " + str(y)

    point = osgeo.ogr.Geometry(osgeo.ogr.wkbPoint)
    point.SetPoint(0, x, y)

    feature = osgeo.ogr.Feature(layerDefinition)
    feature.SetGeometry(point)
    feature.SetFID(i)

    layer.CreateFeature(feature)

    i += 1

shapeData.Destroy()

print "done! " + str(i) + " points found!"

1
코드의 빠른 팁 : srs.ImportFromWkt(r.GetProjection())알려진 프로젝트 문자열에서 투영을 생성하는 대신 래스터 투영을 쉐이프 파일 투영으로 사용할 수 있습니다 .
om_henners

귀하의 코드는 numpy 필터를 작성하여 값 = 1000 만 포함하도록 래스터 셀 값을 포함하지 않는다는 점을 제외하고 내가 찾고있는 모든 것을 수행합니다. 래스터 셀 값을 산출? 감사!
브렌트 에드워즈

답변:


19

GDAL에서는 래스터를 numpy 배열로 가져올 수 있습니다.

from osgeo import gdal
import numpy as np

r = gdal.Open("path/to/raster")
band = r.GetRasterBand(1) #bands start at one
a = band.ReadAsArray().astype(np.float)

그런 다음 numpy를 사용하면 부울 식과 일치하는 배열의 인덱스를 얻는 것이 간단합니다.

(y_index, x_index) = np.nonzero(a > threshold)
#To demonstate this compare a.shape to band.XSize and band.YSize

래스터 지오 변환에서 왼쪽 상단 x 및 y 좌표 및 셀 크기와 같은 정보를 얻을 수 있습니다.

(upper_left_x, x_size, x_rotation, upper_left_y, y_rotation, y_size) = r.GetGeoTransform()

왼쪽 상단 셀은에 해당합니다 a[0, 0]. Y 크기는 항상 음수이므로 x 및 y 인덱스를 사용하면 인덱스를 기반으로 각 셀의 좌표를 계산할 수 있습니다.

x_coords = x_index * x_size + upper_left_x + (x_size / 2) #add half the cell size
y_coords = y_index * y_size + upper_left_y + (y_size / 2) #to centre the point

여기에서 OGR을 사용하여 shapefile을 작성하는 것은 간단합니다. 일부 샘플 코드 는 포인트 정보를 사용하여 새 데이터 세트를 생성하는 방법에 대한 이 질문참조하십시오 .


안녕하세요, 저는 이것을 구현하는 데 작은 문제가 있습니다. 사용중인 코드와 내가 얻는 내용을 포함하도록 질문을 업데이트했습니다. 기본적으로 .py 코드는 QGIS 접근 방식이 생성하는 미러 이미지 (포인트 배치)를 생성합니다. 구현의 요점은 래스터 범위를 벗어 났으므로 문제는 코드와 관련이 있습니다. : = 나는 당신이 약간의 빛을 비출 수 있기를 바라고 있습니다. 감사!
elrobis

그것에 대해 죄송합니다-완전히 내 나쁜. GDAL에서 래스터를 가져올 때 행은 y 방향이고 열은 x 방향입니다. 나는 위의 코드를 업데이트했지만, 트릭과 인덱스를 얻을 수 있습니다(y_index, x_index) = np.nonzero(a > threshold)
om_henners

1
또한 경우에 따라 셀 크기의 절반을 양방향 좌표에 추가하여 셀의 점을 가운데에 맞 춥니 다.
om_henners

그렇습니다. (화면 잡아에서와 같이) 내가 처음이 버그가 발생하면 내가 잘못 포인트 형상을 구현했다면 내가 Y로 X / Y를 뒤집기 시도 그래서, 나는 궁금 / X 내가 만든 때 .shp--- 만 그렇지 않은 일도 아니고 가까운 곳도 아니 었습니다. x 값이 수백에 있고 y가 수백만에 있기 때문에 충격을받지 않았습니다. 나는 Numpy 표현에서 다시 뒤집어 쓰려고하지 않았습니다. 도와 주셔서 감사합니다. 멋지네요. 정확히 내가 원하는 것. :)
elrobis

4

QGIS 에서 Sexante 도구 상자 를 사용하지 않는 이유는 무엇 입니까? Model Builder for ArcGIS와 비슷합니다. 이렇게하면 작업을 연결하여 하나의 작업으로 취급 할 수 있습니다. 내가 실수하지 않은 경우 중간 파일 삭제 및 원치 않는 레코드 제거를 자동화 할 수 있습니다.


1

래스터를 지원하는 postgis로 데이터를 가져 와서 해당 기능을 사용하는 것이 도움이 될 수 있습니다. 이 튜토리얼 에는 필요한 요소가있을 수 있습니다.

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