연속 래스터의 모든 셀을 어떻게 반복합니까?


13

자세한 내용은 이 링크 를 참조하십시오.

문제 :

연속 래스터 (속성 테이블이없는 하나), 셀 단위 로 반복 하고 셀의 값을 얻고 싶습니다 . 실제로 래스터 계산기를 사용하지 않고 아래에 자세히 설명 된 대수 단계를 모방하여 그 값을 가져 와서 조건을 실행하고 싶습니다.

아래의 의견 요청에 따라 문제에 대한 배경 정보를 제공하고 아래의 "분석 필요 :"섹션과 같은 방법을 구현할 필요성을 정당화하는 세부 정보를 추가했습니다.

배경을 제공하여 내 문제와 관련이 있지만 아래 제안 된 분석은 대답으로 구현 할 필요가 없습니다. 질문의 범위는 셀 값을 얻거나 설정하기 위해 연속 래스터를 반복하는 것과 관련이 있습니다.

분석이 필요했습니다 :

다음 조건 중 하나라도 충족되면 출력 셀에 값 1을 지정하십시오. 조건이 충족되지 않은 경우에만 출력 셀 값을 0으로 지정하십시오.

조건 1 : 셀 값이 상단 및 하단 셀보다 큰 경우 값 1을 지정하십시오.

Con("raster" > FocalStatistics("raster", NbrIrregular("C:\filepath\kernel_file.txt"), "MAXIMUM"), 1, 0)

커널 파일은 다음과 같습니다.

3 3 
0 1 0
0 0 0
0 1 0

조건 2 : 셀 값이 왼쪽 및 오른쪽 셀보다 큰 경우 값 1을 지정하십시오.

Con("raster" > FocalStatistics("raster", NbrIrregular("C:\filepath\kernel_file.txt"), "MAXIMUM"), 1, 0)

커널 파일은 다음과 같습니다.

3 3 
0 0 0
1 0 1
0 0 0  

조건 3 : 셀 값이 왼쪽 상단 및 오른쪽 하단 셀보다 큰 경우 값 1을 지정하십시오.

Con("raster" > FocalStatistics("raster", NbrIrregular("C:\filepath\kernel_file.txt"), "MAXIMUM"), 1, 0)

커널 파일은 다음과 같습니다.

3 3 
1 0 0
0 0 0
0 0 1 

조건 4 : 셀 값이 왼쪽 하단 및 오른쪽 상단 셀보다 큰 경우 값 1을 지정하십시오.

Con("raster" > FocalStatistics("raster", NbrIrregular("C:\filepath\kernel_file.txt"), "MAXIMUM"), 1, 0)

커널 파일은 다음과 같습니다.

3 3 
0 0 1
0 0 0
1 0 0 

조건 5 : 하면 모든 인접 셀들 중 하나가 중앙 셀에 EQUAL 값을 가지며, 1의 값을 래스터 출력을 제공 ( 두 가장 가까운 이웃 계산에 초점 다양한 사용 )

왜 대수를 사용하지 않습니까?

아래에서지도 대수를 사용하여 문제를 해결할 수 있지만 위와 같이 총 6 개의 래스터 계산과 함께 생성 된 모든 래스터를 결합하는 것입니다. 나에게 개별적으로 7 번 반복하고 7 개의 래스터를 만들기 위해 상당히 작은 메모리를 사용하는 대신 셀별로 이동하고 각 셀에서 한 번에 모든 비교를 수행 하는 것이 훨씬 더 효율적인 것 같습니다 .

문제를 어떻게 공격해야합니까?

위의 링크는 IPixelBlock 인터페이스를 사용하도록 권장하지만 실제로 IPixelBlock을 통해 단일 셀 값 자체에 액세스하는지 또는 설정 한 IPixelBlock 크기에서 여러 셀 값에 액세스하는지 여부는 ESRI 설명서에서 명확하지 않습니다. 좋은 답변은 연속 래스터의 셀 값에 액세스하는 방법을 제안하고 명백하지 않은 경우 코드 뒤에 방법론에 대한 설명을 제공해야합니다.

요약해서 말하자면:

CONTINUOUS 래스터 ( 속성 테이블없는 )의 모든 셀을 반복 하여 셀 값에 액세스 하는 가장 좋은 방법은 무엇입니까 ?

좋은 답변은 위에서 설명한 분석 단계를 구현할 필요가 없으며 래스터의 셀 값에 액세스하는 방법론 만 제공하면됩니다.


4
래스터의 모든 셀을 반복하는 것은 거의 항상 불필요합니다. 당신이하려는 일에 대한 자세한 정보를 제공 할 수 있습니까?
user2856

2
@Luke는 정확합니다. 지금까지 모든 GIS에서 반복 래스터 계산을 수행하는 가장 좋은 방법 은 셀을 통해 명시 적으로 반복 하는 것을 피하는 것입니다. 대신 가능하다면 GIS에서 제공하는지도 대수 기능을 사용하는 방법을 찾으십시오. 분석 내용을 설명 할 경우 그러한 접근 방식을 사용하는 유용한 답변을 얻을 수 있습니다.
whuber

@Luke 나는 분석의 세부 사항을 추가했습니다.
Conor

1
설명해 주셔서 감사합니다, 코너 귀하의 GIS가 각 래스터 계산에 상당한 오버 헤드를 발생시키는 경우, 자신의 루프를 작성하는 것이 더 효율적일 수 있음에 동의합니다. 호기심으로,이 (비정상적인) 조건 세트의 의도 된 해석은 무엇입니까?
whuber

1
@whuber 내 래스터에서 벡터 다각형을 만드는 것은 가장자리 감지 작업입니다. 이 응용 프로그램은 개념적으로 DEM에서 수문 유역을 식별하는 것과 유사하지만 (물이 아래로 기울어지는 "피크"라고 언급 한 인근 통계에서 중앙 셀을 생각 함) 수문 분야 외부에 있습니다. 이전에는 이러한 목적으로 흐름 방향 및 분지 래스터를 사용해 왔지만 이러한 방법의 특성으로 인해 내가 필요로하는 것이 아니기 때문에 최종 분석에서 오류가 발생하기 쉽습니다.
Conor

답변:


11

나는 이것이 원래 포스터 (OP)에 의해 이미 해결되었지만, 미래의 누군가 가이 문제를 해결하기 위해 다른 방법에 관심이있는 경우를 대비하여 파이썬으로 간단한 해결책을 게시 할 것입니다. 오픈 소스 소프트웨어의 일부이므로 파이썬에서 GDAL을 사용하는 솔루션이 있습니다.

import gdal

#Set GeoTiff driver
driver = gdal.GetDriverByName("GTiff")
driver.Register()

#Open raster and read number of rows, columns, bands
dataset = gdal.Open(filepath)
cols = dataset.RasterXSize
rows = dataset.RasterYSize
allBands = dataset.RasterCount
band = dataset.GetRasterBand(1)

#Get array of raster cell values.  The two zeros tell the 
#iterator which cell to start on and the 'cols' and 'rows' 
#tell the iterator to iterate through all columns and all rows.
def get_raster_cells(band,cols,rows):
    return band.ReadAsArray(0,0,cols,rows)

다음과 같은 기능을 구현하십시오.

#Bind array to a variable
rasterData = get_raster_cells(band,cols,rows)

#The array will look something like this if you print it
print rasterData
> [[ 1, 2, 3 ],
   [ 4, 5, 6 ],
   [ 7, 8, 9 ]]

그런 다음 중첩 루프를 사용하여 데이터를 반복하십시오.

for row in rasterData:
    for val in row:
        print val
> 1
  2
  3
  4...

또는 목록 이해력으로 2D 배열을 평평하게하고 싶을 수도 있습니다.

flat = [val for row in rasterData for val in row]

어쨌든 셀 단위로 데이터를 반복하면서 값을 변경 / 편집하기 위해 루프에 일부 조건을 던질 수 있습니다. 데이터에 액세스하는 다른 방법은 https://github.com/azgs/hazards-viewer/blob/master/python/zonal_stats.py 에서 작성한이 스크립트를 참조 하십시오 .


나는이 솔루션의 단순성과 우아함을 좋아한다. 나는 며칠 더 기다릴 것입니다. 동일하거나 더 우수한 품질의 솔루션을 가진 사람이 없다면 커뮤니티의 이익을 위해 질문의 범위를 넓히고 현상금을 수여하는 태그를 추가 할 것입니다.
Conor

감사합니다, @Conor! 이번 주 초 직장에서 비슷한 문제가 발생하여 GDAL / python으로 수업을 작성하여 문제를 해결했습니다. 특히 클라이언트 측 응용 프로그램의 사용자가 경계 상자 만 제공 한 래스터 영역의 평균 값을 계산하는 서버 측 방법이 필요했습니다. 내가 쓴 나머지 수업을 추가하면 도움이 될 것이라고 생각하십니까?
asonnenschein

검색 한 2 차원 배열을 읽고 값을 편집하는 방법을 보여주는 코드를 추가하면 도움이됩니다.
Conor

9

최신 정보! numpy 솔루션 :

import arcpy
import numpy as np

in_ras = path + "/rastername"

raster_Array = arcpy.RasterToNumPyArray(in_ras)
row_num = raster_Array.shape[0]
col_num = raster_Array.shape[1]
cell_count = row_num * row_num

row = 0
col = 0
temp_it = 0

while temp_it < cell_count:
    # Insert conditional statements
    if raster_Array[row, col] > 0:
        # Do something
        val = raster_Array[row, col]
        print val
    row+=1
    if col > col_num - 1:
        row = 0
        col+=1

따라서 arcpy를 사용하여 완성 된 배열을 래스터로 되 돌리는 것은 번거로운 일입니다. arcpy.NumPyArrayToRaster는 다람쥐이며 LL 좌표를 제공하더라도 범위를 재정의하는 경향이 있습니다.

텍스트로 저장하는 것을 선호합니다.

np.savetxt(path + "output.txt", output, fmt='%.10f', delimiter = " ")

속도를 위해 64 비트로 Python을 실행하고 있습니다. 현재 numpy.savetxt에 헤더를 제공 할 수 없습니다. 따라서 ASCII를 래스터로 변환하기 전에 출력을 열고 Arc가 원하는 ASCII 헤더를 추가해야합니다

File_header = "NCOLS xxx" + '\n'+ "NROWS xxx" + '\n' + "XLLCORNER xxx"+'\n'+"YLLCORNER xxx"+'\n'+"CELLSIZE xxx"+'\n'+"NODATA_VALUE xxx"+'\n'

numpy 버전은 시프트 래스터, 곱셈 및 덧셈을 arcpy 버전 (15 분 동안 1000 회 반복)보다 훨씬 빠르게 (2 분 내에 1000 회 반복) 실행합니다.

구버전 나는 이것을 삭제해도 나중에 비슷한 스크립트를 썼다. 포인트로 변환하고 검색 커서를 사용해 보았습니다. 12 시간 동안 5000 회만 반복했습니다. 그래서 다른 방법을 찾았습니다.

이 작업을 수행하는 방법은 각 셀의 셀 중심 좌표를 반복하는 것입니다. 왼쪽 상단에서 시작하여 오른쪽에서 왼쪽으로 이동합니다. 줄의 끝에서 나는 줄을 아래로 이동하고 왼쪽에서 다시 시작합니다. 2603 열과 2438 행의 240m 래스터가 있으므로 총 6111844 개의 셀이 있습니다. 반복자 변수와 while 루프를 사용합니다. 아래 참조

몇 가지 참고 사항 : 1-범위의 좌표를 알아야합니다.

2-셀 중심에 대한 점 좌표로 실행-범위 값에서 셀 크기의 1/2로 이동

3-내 스크립트는 셀 값을 사용하여 값 특정 래스터를 가져온 다음이 래스터를 원래 셀의 중심으로 이동합니다. 최종 래스터에 추가하기 전에 범위를 확장하기 위해 래스터가 0이됩니다. 이것은 단지 예일뿐입니다. 조건문을 여기에 넣을 수 있습니다 (while 루프 내의 두 번째 if 문).

4-이 스크립트는 모든 래스터 값을 정수로 캐스트 할 수 있다고 가정합니다. 즉, 데이터 없음을 먼저 제거해야합니다. 사기꾼.

6-나는 여전히 이것에 만족하지 않으며 이것을 완전히 아크에서 꺼내려고 노력하고 있습니다. 차라리 numpy 배열로 캐스팅하고 거기에서 수학을 한 다음 다시 Arc로 가져옵니다.

ULx = 959415 ## coordinates for the Upper Left of the entire raster 
ULy = 2044545
x = ULx ## I redefine these if I want to run over a smaller area
y = ULy
temp_it = 0

while temp_it < 6111844: # Total cell count in the data extent
        if x <= 1583895 and y >= 1459474: # Coordinates for the lower right corner of the raster
           # Get the Cell Value
           val_result = arcpy.GetCellValue_management(inraster, str(x)+" " +str(y), "1")
           val = int(val_result.getOutput(0))
        if val > 0: ## Here you could insert your conditional statements
            val_pdf = Raster(path + "pdf_"str(val))
            shift_x  =  ULx - x # This will be a negative value
            shift_y = ULy - y # This will be a positive value
            arcpy.Shift_management(val_pdf, path+ "val_pdf_shift", str(-shift_x), str(-shift_y))
            val_pdf_shift = Raster(path + "val_pdf_shift")
            val_pdf_sh_exp = CellStatistics([zeros, val_pdf_shift], "SUM", "DATA")
            distr_days = Plus(val_pdf_sh_exp, distr_days)
        if temp_it % 20000 == 0: # Just a print statement to tell me how it's going
                print "Iteration number " + str(temp_it) +" completed at " + str(time_it)
        x += 240 # shift x over one column
        if x > 1538295: # if your at the right hand side of a row
            y = y-240 # Shift y down a row
            x = 959415 # Shift x back to the first left hand column
        temp_it+=1

distr_days.save(path + "Final_distr_days")

4

IGridTable, ICursor, IRow를 사용해보십시오. 이 코드 스 니펫은 래스터 셀 값을 업데이트하기위한 것이지만 반복의 기본 사항을 보여줍니다.

래스터 속성 테이블에 새 필드를 추가하고 반복하려면 어떻게해야합니까?

Public Sub CalculateArea(raster As IRaster, areaField As String)
    Dim bandCol As IRasterBandCollection
    Dim band As IRasterBand

    Set bandCol = raster
    Set band = bandCol.Item(0)

    Dim hasTable As Boolean
    band.hasTable hasTable
    If (hasTable = False) Then
        Exit Sub
    End If    

    If (AddVatField(raster, areaField, esriFieldTypeDouble, 38) = True) Then
        ' calculate cell size
        Dim rstProps As IRasterProps
        Set rstProps = raster

        Dim pnt As IPnt
        Set pnt = rstProps.MeanCellSize

        Dim cellSize As Double
        cellSize = (pnt.X + pnt.Y) / 2#

        ' get fields index
        Dim attTable As ITable
        Set attTable = band.AttributeTable

        Dim idxArea As Long, idxCount As Long
        idxArea = attTable.FindField(areaField)
        idxCount = attTable.FindField("COUNT")

        ' using update cursor
        Dim gridTableOp As IGridTableOp
        Set gridTableOp = New gridTableOp

        Dim cellCount As Long, cellArea As Double

        Dim updateCursor As ICursor, updateRow As IRow
        Set updateCursor = gridTableOp.Update(band.RasterDataset, Nothing, False)
        Set updateRow = updateCursor.NextRow()
        Do Until updateRow Is Nothing
            cellCount = CLng(updateRow.Value(idxCount))
            cellArea = cellCount * (cellSize * cellSize)

            updateRow.Value(idxArea) = cellArea
            updateCursor.updateRow updateRow

            Set updateRow = updateCursor.NextRow()
        Loop

    End If
End Sub

테이블을 순회하면를 사용하여 특정 필드 행 값을 얻을 수 있습니다 row.get_Value(yourfieldIndex). Google 인 경우

arcobjects row.get_Value

이것을 보여주는 많은 예제를 얻을 수 있어야합니다.

희망이 도움이됩니다.


1
유감스럽게도 언급을 무시하고 위의 원래 질문에서 편집 할 것입니다. 래스터에는 큰 이중 값으로 구성된 많은 연속 값이 있으므로 래스터에 속성 테이블 값이 없기 때문에이 방법은 작동하지 않습니다.
Conor

4

이것은 근본적인 아이디어로 파이썬이나 ArcObjects로 프로그래밍해야합니다.

  1. 그리드를 점 피쳐 클래스로 변환하십시오.
  2. XY 필드를 작성하고 채우십시오.
  3. 가 X, Y의 문자열이고 항목 이 셀 값인 사전에 점을로드하십시오 .
  4. 사전을 단계별로 살펴보고 각 포인트마다 8 개의 주변 셀 XY를 계산하십시오.
  5. 사전에서이를 검색하고 규칙을 사용하여 테스트하십시오. true 값을 찾으면 나머지 테스트를 건너 뛸 수 있습니다.
  6. 결과를 다른 사전에 기록한 다음 먼저 점 FeatureClass를 작성하고 점을 격자로 변환하여 격자로 다시 변환하십시오.

2
이 아이디어는 포인트 기능 세트로 변환함으로써 래스터 기반 데이터 표현의 두 가지 특성을 제거하여 효과적입니다. (1) 이웃을 찾는 것은 매우 간단한 상수 시간 작업이며 (2) 위치를 명시 적으로 저장하므로 필요하지 않은 RAM, 디스크 및 I / O 요구 사항은 최소입니다. 따라서이 방법은 효과가 있지만 권장 할만한 이유를 찾기는 어렵습니다.
whuber

답변 해 주셔서 감사합니다 Hornbydd. 나는 이와 같은 방법을 구현해도 괜찮지 만 4 단계와 5 단계는 계산적으로 효과적이지 않은 것처럼 보입니다. 내 래스터는 최소 62,500 개의 셀 (내가 설정 한 래스터의 최소 해상도는 250 셀 x 250 셀이지만 해상도는 훨씬 더 많이 구성 될 수 있음)이며 공간 쿼리를 수행해야합니다. 모든 조건에서 내 비교를 실행하려면 ... 6 개의 조건이 있으므로 6 * 62500 = 375000 공간 쿼리입니다. 지도 대수를 사용하는 것이 좋습니다. 그러나 문제를 보는이 새로운 방식에 감사드립니다. 공감.
Conor

ASCII로 변환 한 다음 R과 같은 프로그램을 사용하여 컴퓨팅을 수행 할 수 없습니까?
Oliver Burdekin

또한 위의 조건을 충족시키기 위해 쉽게 수정할 수있는 Java 애플릿이 있습니다. 스무딩 알고리즘 일 뿐이지 만 업데이트는 매우 쉽습니다.
Oliver Burdekin

.NET Framework 3.5 및 ArcGIS 10 만 설치 한 사용자를 위해 .NET 플랫폼에서 프로그램을 호출 할 수있는 한. 이 프로그램은 오픈 소스이며 최종 사용자에게 제공 될 때 유일한 소프트웨어 요구 사항이됩니다. 이 두 가지 요구 사항을 충족하기 위해 답변을 구현할 수 있으면 올바른 답변으로 간주됩니다. 명확성을 위해 질문에 버전 태그를 추가하겠습니다.
Conor

2

해결책 :

나는 오늘 일찍 이것을 해결했다. 코드는 이 방법 의 적응입니다 . 래스터와 인터페이스하는 데 사용 된 객체가 실제로 무엇을하는지 알아 낸 후에는이 개념의 개념이 그리 어렵지 않았습니다. 아래 방법은 두 개의 입력 데이터 세트 (inRasterDS 및 outRasterDS)를 사용합니다. 둘 다 동일한 데이터 세트입니다. 방금 inRasterDS의 사본을 만들어 outRasterDS로 메소드에 전달했습니다. 이 방법은 둘 다 동일한 범위, 공간 참조 등을 갖습니다.이 방법은 inRasterDS의 값을 셀 단위로 읽고 가장 가까운 이웃 비교를 수행합니다. 이러한 비교 결과를 outRasterDS에 저장된 값으로 사용합니다.

과정:

IRasterCursor-> IPixelBlock-> SafeArray를 사용하여 픽셀 값을 얻고 IRasterEdit를 사용하여 래스터에 새로운 값을 씁니다. IPixelBlock을 만들면 읽고 / 쓰기하려는 영역의 크기와 위치를 컴퓨터에 알려줍니다. 래스터의 아래쪽 절반 만 편집하려면이를 IPixelBlock 매개 변수로 설정하십시오. 전체 래스터를 반복하려면 IPixelBlock을 전체 래스터 크기와 동일하게 설정해야합니다. 아래 방법으로 IRasterCursor (pSize)에 크기를 전달한 다음 래스터 커서에서 PixelBlock을 가져 와서이 작업을 수행합니다.

다른 키는이 메소드의 값과 인터페이스하기 위해 SafeArray를 사용해야한다는 것입니다. IRasterCursor에서 IPixelBlock을, IPixelBlock에서 SafeArray를 얻습니다. 그런 다음 SafeArray를 읽고 씁니다. SafeArray에 대한 읽기 / 쓰기가 끝나면 전체 SafeArray를 다시 IPixelBlock에 쓴 다음 IPixelBlock을 IRasterCursor에 쓴 다음 IRasterCursor를 사용하여 쓰기 시작 위치를 설정하고 IRasterEdit를 사용하여 쓰기 자체를 수행하십시오. 이 마지막 단계는 실제로 데이터 세트의 값을 편집하는 곳입니다.

    public static void CreateBoundaryRaster(IRasterDataset2 inRasterDS, IRasterDataset2 outRasterDS)
    {
        try
        {
            //Create a raster. 
            IRaster2 inRaster = inRasterDS.CreateFullRaster() as IRaster2; //Create dataset from input raster
            IRaster2 outRaster = outRasterDS.CreateFullRaster() as IRaster2; //Create dataset from output raster
            IRasterProps pInRasterProps = (IRasterProps)inRaster;
            //Create a raster cursor with a pixel block size matching the extent of the input raster
            IPnt pSize = new DblPnt();
            pSize.SetCoords(pInRasterProps.Width, pInRasterProps.Height); //Give the size of the raster as a IPnt to pass to IRasterCursor
            IRasterCursor inrasterCursor = inRaster.CreateCursorEx(pSize); //Create IRasterCursor to parse input raster 
            IRasterCursor outRasterCursor = outRaster.CreateCursorEx(pSize); //Create IRasterCursor to parse output raster
            //Declare IRasterEdit, used to write the new values to raster
            IRasterEdit rasterEdit = outRaster as IRasterEdit;
            IRasterBandCollection inbands = inRasterDS as IRasterBandCollection;//set input raster as IRasterBandCollection
            IRasterBandCollection outbands = outRasterDS as IRasterBandCollection;//set output raster as IRasterBandCollection
            IPixelBlock3 inpixelblock3 = null; //declare input raster IPixelBlock
            IPixelBlock3 outpixelblock3 = null; //declare output raster IPixelBlock
            long blockwidth = 0; //store # of columns of raster
            long blockheight = 0; //store # of rows of raster

            //create system array for input/output raster. System array is used to interface with values directly. It is a grid that overlays your IPixelBlock which in turn overlays your raster.
            System.Array inpixels; 
            System.Array outpixels; 
            IPnt tlc = null; //set the top left corner

            // define the 3x3 neighborhood objects
            object center;
            object topleft;
            object topmiddle;
            object topright;
            object middleleft;
            object middleright;
            object bottomleft;
            object bottommiddle;
            object bottomright;

            long bandCount = outbands.Count; //use for multiple bands (only one in this case)

            do
            {

                inpixelblock3 = inrasterCursor.PixelBlock as IPixelBlock3; //get the pixel block from raster cursor
                outpixelblock3 = outRasterCursor.PixelBlock as IPixelBlock3;
                blockwidth = inpixelblock3.Width; //set the # of columns in raster
                blockheight = inpixelblock3.Height; //set the # of rows in raster
                outpixelblock3.Mask(255); //set any NoData values

                for (int k = 0; k < bandCount; k++) //for every band in raster (will always be 1 in this case)
                {
                    //Get the pixel array.
                    inpixels = (System.Array)inpixelblock3.get_PixelData(k); //store the raster values in a System Array to read
                    outpixels = (System.Array)outpixelblock3.get_PixelData(k); //store the raster values in a System Array to write
                    for (long i = 1; i < blockwidth - 1; i++) //for every column (except outside columns)
                    {
                        for (long j = 1; j < blockheight - 1; j++) //for every row (except outside rows)
                        {
                            //Get the pixel values of center cell and  neighboring cells

                            center = inpixels.GetValue(i, j);

                            topleft = inpixels.GetValue(i - 1, j + 1);
                            topmiddle = inpixels.GetValue(i, j + 1);
                            topright = inpixels.GetValue(i + 1, j + 1);
                            middleleft = inpixels.GetValue(i - 1, j);
                            middleright = inpixels.GetValue(i + 1, j);
                            bottomleft = inpixels.GetValue(i - 1, j - 1);
                            bottommiddle = inpixels.GetValue(i, j - 1);
                            bottomright = inpixels.GetValue(i - 1, j - 1);


                            //compare center cell value with middle left cell and middle right cell in a 3x3 grid. If true, give output raster value of 1
                            if ((Convert.ToDouble(center) >= Convert.ToDouble(middleleft)) && (Convert.ToDouble(center) >= Convert.ToDouble(middleright)))
                            {
                                outpixels.SetValue(1, i, j);
                            }


                            //compare center cell value with top middle and bottom middle cell in a 3x3 grid. If true, give output raster value of 1
                            else if ((Convert.ToDouble(center) >= Convert.ToDouble(topmiddle)) && (Convert.ToDouble(center) >= Convert.ToDouble(bottommiddle)))
                            {
                                outpixels.SetValue(1, i, j);
                            }

                            //if neither conditions are true, give raster value of 0
                            else
                            {

                                outpixels.SetValue(0, i, j);
                            }
                        }
                    }
                    //Write the pixel array to the pixel block.
                    outpixelblock3.set_PixelData(k, outpixels);
                }
                //Finally, write the pixel block back to the raster.
                tlc = outRasterCursor.TopLeft;
                rasterEdit.Write(tlc, (IPixelBlock)outpixelblock3);
            }
            while (inrasterCursor.Next() == true && outRasterCursor.Next() == true);
            System.Runtime.InteropServices.Marshal.ReleaseComObject(rasterEdit);


        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }

    }

1

AFAIK 래스터 데이터는 세 가지 방법으로 읽을 수 있습니다.

  • 세포 별 (비효율적);
  • 이미지별로 (아주 효율적);
  • 블록별로 (가장 효율적인 방법).

바퀴를 다시 만들지 않고 Chris Garrard 의이 밝은 슬라이드 를 읽어 보는 것이 좋습니다 .

따라서 가장 효율적인 방법은 블록 단위로 데이터를 읽는 것이지만 필터를 적용하는 동안 블록 경계에 위치한 픽셀에 해당하는 데이터 손실이 발생합니다. 따라서 안전한 대안 방법은 전체 이미지를 한 번에 읽고 numpy 방식을 사용하는 것입니다.

계산 측면 에서 필요한 필터를 적용하고 무엇보다도 무거운 계산을 피하기 위해 gdalfilter.py 및 암시 적으로 VRT KernelFilteredSource 접근 방식을 사용해야합니다.

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