Làm thế nào để tôi lặp qua mọi tế bào trong một raster liên tục?


13

Xem liên kết này để biết thêm chi tiết.

Vấn đề:

Tôi muốn lặp qua một raster liên tục (một cái không có bảng thuộc tính), từng ô và nhận giá trị của ô. Tôi muốn lấy các giá trị đó và chạy các điều kiện trên chúng, mô phỏng các bước đại số bản đồ chi tiết bên dưới mà không thực sự sử dụng máy tính raster.

Theo yêu cầu của các bình luận bên dưới, tôi đã thêm các chi tiết cung cấp nền tảng cho vấn đề và chứng minh sự cần thiết phải thực hiện một phương pháp như vậy trong phần bên dưới có tên là "Phân tích cần thiết:".

Phân tích được đề xuất dưới đây, trong khi có liên quan đến vấn đề của tôi bằng cách cung cấp nền, không cần phải thực hiện trong câu trả lời. Phạm vi của câu hỏi chỉ liên quan đến việc lặp qua một raster liên tục để lấy / đặt các giá trị ô.

Các phân tích cần thiết:

Nếu BẤT K of điều kiện nào sau đây được thỏa mãn, hãy đặt cho ô đầu ra một giá trị là 1. Chỉ cung cấp cho ô đầu ra giá trị 0 nếu không có điều kiện nào được đáp ứng.

Điều kiện 1: Nếu giá trị ô lớn hơn ô trên cùng và dưới cùng, hãy đưa ra giá trị 1:

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

Trường hợp tập tin kernel trông như thế này:

3 3 
0 1 0
0 0 0
0 1 0

Điều kiện 2: Nếu giá trị ô lớn hơn các ô bên trái và bên phải, hãy đưa ra giá trị 1:

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

Trường hợp tập tin kernel trông như thế này:

3 3 
0 0 0
1 0 1
0 0 0  

Điều kiện 3: Nếu giá trị ô lớn hơn các ô topleft và bottomright, đưa ra giá trị 1:

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

Trường hợp tập tin kernel trông như thế này:

3 3 
1 0 0
0 0 0
0 0 1 

Điều kiện 4: Nếu giá trị ô lớn hơn các ô dưới cùng và topright, cho giá trị 1:

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

Trường hợp tập tin kernel trông như thế này:

3 3 
0 0 1
0 0 0
1 0 0 

Điều kiện 5: Nếu bất kỳ một trong các ô liền kề có giá trị THIẾT BỊ cho ô trung tâm, hãy cung cấp cho raster đầu ra giá trị 1 ( sử dụng đa dạng tiêu cự với hai phép tính lân cận gần nhất )

Tại sao không sử dụng đại số bản đồ?

Dưới đây đã lưu ý rằng vấn đề của tôi có thể được giải quyết bằng cách sử dụng đại số bản đồ nhưng như đã thấy ở trên, đây là tổng cộng sáu phép tính raster, cộng với một để kết hợp tất cả các raster được tạo với nhau. Dường như với tôi rằng nó là nhiều hơn nữa hiệu quả để đi ô-by-tế bào và làm tất cả những so sánh cùng một lúc trong mỗi tế bào thay vì lặp qua từng cá nhân bảy lần và sử dụng khá nhiều bộ nhớ để tạo Bảy rasters.

Vấn đề nên được tấn công như thế nào?

Liên kết ở trên khuyên bạn nên sử dụng giao diện IPixelBlock, tuy nhiên không rõ ràng từ tài liệu ESRI cho dù bạn thực sự đang truy cập vào một giá trị ô thông qua IPixelBlock hoặc nếu bạn đang truy cập nhiều giá trị ô từ kích thước của IPixelBlock bạn đã đặt. Một câu trả lời tốt sẽ đề xuất một phương pháp để truy cập các giá trị ô của raster liên tục và đưa ra lời giải thích về phương pháp đằng sau mã, nếu không rõ ràng.

Tóm tắt:

Phương pháp tốt nhất để lặp qua mọi ô trong trình raster TIẾP TỤC ( không có bảng thuộc tính ) để truy cập các giá trị ô của nó là gì?

Một câu trả lời tốt không cần phải thực hiện các bước phân tích được mô tả ở trên, nó chỉ cần cung cấp một phương pháp để truy cập các giá trị ô của raster.


4
Gần như luôn luôn không cần thiết phải lặp qua mọi ô trong raster. Bạn có thể cung cấp thêm thông tin về những gì bạn đang cố gắng làm?
dùng2856

2
@Luke là chính xác: cho đến nay, cách tốt nhất để thực hiện phép tính raster lặp trong bất kỳ hệ thống GIS nào là tránh lặp vòng qua các ô một cách rõ ràng, bởi vì dưới vỏ bọc, mọi vòng lặp phải được thực hiện đã được tối ưu hóa. Thay vào đó, hãy tìm cách sử dụng chức năng đại số bản đồ do GIS cung cấp, nếu điều đó hoàn toàn có thể. Nếu bạn mô tả phân tích của mình, bạn có thể có được câu trả lời hữu ích sử dụng cách tiếp cận như vậy.
whuber

@Luke Tôi đã thêm chi tiết phân tích.
Conor

1
Cảm ơn bạn đã làm rõ, Conor. Tôi đồng ý rằng nếu hệ thống GIS của bạn phải chịu chi phí đáng kể cho mỗi phép tính raster, việc viết vòng lặp của riêng bạn có thể hiệu quả hơn. Vì tò mò, ý định giải thích của tập hợp các điều kiện (bất thường) này là gì?
whuber

1
@whuber Nó dành cho các hoạt động phát hiện cạnh để tạo đa giác vector từ raster của tôi. Ứng dụng này về mặt khái niệm tương tự như xác định các lưu vực thủy văn từ một DEM (nghĩ về ô trung tâm trong các thống kê lân cận được liệt kê ở trên là "đỉnh" mà nước sẽ chảy xuống từ) nhưng nằm ngoài lĩnh vực thủy văn. Trước đây tôi đã sử dụng Flow Direction và Basin Rasters cho mục đích này, nhưng những thứ đó dễ bị lỗi trong phân tích cuối cùng của tôi do các thuộc tính của các phương thức này không chính xác là những gì tôi cần.
Conor

Câu trả lời:


11

Tôi thấy điều này đã được Giải quyết bằng Poster gốc (OP), nhưng tôi sẽ đăng một giải pháp đơn giản cho python chỉ trong trường hợp bất kỳ ai trong tương lai quan tâm đến các cách khác nhau để giải quyết vấn đề này. Tôi là một phần của phần mềm nguồn mở, vì vậy đây là một giải pháp sử dụng GDAL trong python:

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)

Thực hiện chức năng như thế này:

#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 ]]

Sau đó, lặp qua dữ liệu của bạn với một vòng lặp lồng nhau:

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

Hoặc có thể bạn muốn làm phẳng mảng 2 chiều của mình bằng cách hiểu danh sách:

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

Dù sao, trong khi lặp qua dữ liệu trên cơ sở từng tế bào, có thể ném một số điều kiện vào vòng lặp của bạn để thay đổi / chỉnh sửa giá trị. Xem tập lệnh này tôi đã viết cho các cách khác nhau để truy cập dữ liệu: https://github.com/azgs/hazards-viewer/blob/master/python/zonal_stats.py .


Tôi thích sự đơn giản và thanh lịch của giải pháp này. Tôi sẽ đợi thêm một vài ngày nữa và nếu không có ai đưa ra giải pháp có chất lượng tương đương hoặc cao hơn, tôi sẽ thêm các thẻ để mở rộng phạm vi câu hỏi vì lợi ích của cộng đồng và trao thưởng cho bạn tiền thưởng.
Conor

Cảm ơn, @Conor! Chúng tôi đã gặp một vấn đề tương tự tại nơi làm việc của tôi vào đầu tuần này và vì vậy tôi đã giải quyết nó bằng cách viết một lớp với GDAL / python. Cụ thể, chúng tôi cần một phương thức phía máy chủ để tính giá trị trung bình của một khu vực của raster chỉ được cung cấp một hộp giới hạn từ người dùng trên ứng dụng phía máy khách của chúng tôi. Bạn có nghĩ rằng nó sẽ có ích nếu tôi thêm phần còn lại của lớp tôi đã viết không?
asonnenschein

Thêm mã hiển thị cách đọc mảng 2 chiều bạn đã truy xuất và chỉnh sửa giá trị của nó sẽ hữu ích.
Conor

9

Cập nhật! Các giải pháp 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

Vì vậy, việc đưa mảng hoàn thành trở lại raster bằng arcpy là rắc rối. arcpy.NumPyArrayToRaster là squirrelly và có xu hướng xác định lại phạm vi ngay cả khi bạn cho nó tọa độ LL của bạn.

Tôi thích lưu dưới dạng văn bản.

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

Tôi đang chạy Python với tốc độ 64 bit - tính đến thời điểm hiện tại, điều này có nghĩa là tôi không thể cung cấp cho numpy.savetxt một tiêu đề. Vì vậy, tôi phải mở đầu ra và thêm tiêu đề ASCII mà Arc muốn trước khi chuyển đổi ASCII sang Raster

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

Phiên bản gọn gàng chạy raster shift của tôi, nhân và thêm nhanh hơn (1000 lần lặp trong 2 phút) so với phiên bản arcpy (1000 lần lặp trong 15 phút)

PHIÊN BẢN OLD Tôi có thể xóa điều này sau khi tôi vừa viết một kịch bản tương tự. Tôi đã thử chuyển đổi thành điểm và sử dụng con trỏ tìm kiếm. Tôi chỉ nhận được 5000 lần lặp trong 12 giờ. Vì vậy, tôi tìm cách khác.

Cách của tôi để làm điều này là lặp qua tọa độ trung tâm ô của mỗi ô. Tôi bắt đầu ở góc trên bên trái và di chuyển từ phải sang trái. Ở cuối hàng tôi di chuyển xuống một hàng và bắt đầu lại ở bên trái. Tôi có một raster 240 m với 2603 cột và 2438 hàng nên tổng cộng có 6111844 ô. Tôi sử dụng một biến lặp và vòng lặp while. Xem bên dưới

Một vài lưu ý: 1 - bạn cần biết tọa độ của phạm vi

2 - chạy với tọa độ điểm cho trung tâm ô - di chuyển bằng 1/2 kích thước ô từ các giá trị phạm vi

3 - Tập lệnh của tôi đang sử dụng giá trị ô để kéo một giá trị cụ thể của raster, sau đó chuyển raster này sang chính giữa ô ban đầu. Điều này thêm vào một raster zero để mở rộng phạm vi trước khi thêm vào một raster cuối cùng. Đây chỉ là một ví dụ. Bạn có thể đặt các câu lệnh điều kiện của bạn ở đây (câu lệnh if thứ hai trong vòng lặp while).

4 - Kịch bản này giả định tất cả các giá trị raster có thể được sử dụng dưới dạng số nguyên. Điều này có nghĩa là bạn cần phải thoát khỏi dữ liệu đầu tiên. Con Isull.

6 - Tôi vẫn chưa hài lòng với điều này và tôi đang làm việc để hoàn toàn thoát khỏi điều này. Tôi thà sử dụng các mảng numpy và làm toán ở đó sau đó mang nó trở lại 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

Hãy thử sử dụng IGridTable, ICthon, IRow. Đoạn mã này là để cập nhật các giá trị ô raster, tuy nhiên nó cho thấy những điều cơ bản của việc lặp:

Làm cách nào tôi có thể thêm một trường mới trong bảng thuộc tính raster và lặp qua nó?

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

Khi bạn duyệt qua bảng, bạn có thể nhận giá trị hàng của trường cụ thể bằng cách sử dụng row.get_Value(yourfieldIndex). Nếu bạn Google

arcobjects row.get_Value

bạn sẽ có thể nhận được rất nhiều ví dụ cho thấy điều này.

Mong rằng sẽ giúp.


1
Tôi không may bỏ qua lưu ý và tôi sẽ chỉnh sửa trong câu hỏi ban đầu của tôi ở trên, rằng raster của tôi có nhiều giá trị liên tục bao gồm các giá trị kép lớn và vì vậy phương thức này sẽ không hoạt động vì raster của tôi không có giá trị bảng thuộc tính.
Conor

4

Làm thế nào về điều này như là một ý tưởng cấp tiến, nó sẽ yêu cầu bạn lập trình trong python hoặc ArcObjects.

  1. Chuyển đổi lưới của bạn để một featureclasss điểm.
  2. Tạo các trường XY và dân cư.
  3. Tải các điểm vào một từ điển trong đó khóa là một chuỗi X, Y và mục là giá trị ô ..
  4. Bước qua từ điển của bạn và cho mỗi điểm, hãy tìm ra 8 ô XY xung quanh.
  5. Lấy những thứ này từ từ điển của bạn và kiểm tra các quy tắc của bạn, ngay khi bạn tìm thấy một giá trị đúng, bạn có thể bỏ qua phần còn lại của các bài kiểm tra.
  6. Viết kết quả vào một từ điển khác và sau đó chuyển đổi trở lại lưới bằng cách trước tiên tạo một FeatureClass điểm và sau đó chuyển đổi điểm thành lưới.

2
Bằng cách chuyển đổi thành một tập hợp các tính năng điểm, ý tưởng này giúp loại bỏ hai phẩm chất của biểu diễn dữ liệu dựa trên raster giúp nó hiệu quả: (1) tìm hàng xóm là một hoạt động liên tục cực kỳ đơn giản và (2) vì lưu trữ vị trí rõ ràng là không cần thiết, RAM, đĩa và yêu cầu I / O là tối thiểu. Vì vậy, mặc dù phương pháp này sẽ hiệu quả, thật khó để tìm ra bất kỳ lý do nào để đề xuất nó.
whuber

Cảm ơn câu trả lời của bạn Hornbydd. Tôi ổn với việc thực hiện một phương pháp như thế này, nhưng có vẻ như các bước 4 & 5 sẽ không hiệu quả về mặt tính toán. Trình raster của tôi sẽ có tối thiểu 62.500 ô (độ phân giải tối thiểu cho raster của tôi mà tôi đã đặt là 250 ô x 250 ô, nhưng độ phân giải có thể và thường bao gồm nhiều hơn nữa) và tôi phải thực hiện một truy vấn không gian cho mọi điều kiện để thực hiện so sánh của tôi ... Vì tôi có 6 điều kiện, đó sẽ là 6 * 62500 = 375000 truy vấn không gian. Tôi sẽ tốt hơn với đại số bản đồ. Nhưng cảm ơn vì cách nhìn mới về vấn đề này. Nâng cao.
Conor

Bạn có thể chuyển đổi nó thành ASCII và sau đó sử dụng một chương trình như R để thực hiện tính toán không?
Oliver Burdekin

Thêm vào đó tôi có một applet Java mà tôi đã viết có thể dễ dàng sửa đổi để đáp ứng các điều kiện của bạn ở trên. Nó chỉ là một thuật toán làm mịn nhưng các bản cập nhật sẽ khá dễ thực hiện.
Oliver Burdekin

Miễn là chương trình có thể được gọi từ nền tảng .NET cho người dùng chỉ cài đặt .NET Framework 3.5 và ArcGIS 10. Chương trình này là nguồn mở và tôi dự định đây sẽ là những yêu cầu phần mềm duy nhất khi được cung cấp cho người dùng cuối. Nếu câu trả lời của bạn có thể được thực hiện để đáp ứng hai yêu cầu này thì nó sẽ được coi là một câu trả lời hợp lệ. Tôi cũng sẽ thêm một thẻ phiên bản cho câu hỏi để làm rõ.
Conor

2

Một giải pháp:

Tôi đã giải quyết điều này sớm hơn ngày hôm nay. Mã này là một sự thích ứng của phương pháp này . Khái niệm đằng sau điều này không quá khó khăn một khi tôi đã tìm ra những vật thể được sử dụng để giao tiếp với raster thực sự làm gì. Phương pháp dưới đây có hai bộ dữ liệu đầu vào (inRasterDS và outRasterDS). Cả hai đều là cùng một tập dữ liệu, tôi chỉ tạo một bản sao của inRasterDS và chuyển nó vào phương thức dưới dạng outRasterDS. Bằng cách này, cả hai đều có cùng mức độ, tham chiếu không gian, v.v ... Phương thức này đọc các giá trị từ inRasterDS, từng ô và so sánh hàng xóm gần nhất với chúng. Nó sử dụng kết quả của những so sánh đó làm giá trị được lưu trữ trong outRasterDS.

Quá trình:

Tôi đã sử dụng IRasterCthon -> IPixelBlock -> SafeArray để lấy các giá trị pixel và IRasterEdit để ghi các giá trị mới vào raster. Khi bạn tạo IPixelBlock, bạn đang báo cho máy biết kích thước và vị trí của khu vực bạn muốn đọc / ghi vào. Nếu bạn chỉ muốn chỉnh sửa nửa dưới của raster, bạn đặt đó làm tham số IPixelBlock. Nếu bạn muốn lặp trên toàn bộ raster, bạn phải đặt IPixelBlock bằng với kích thước của toàn bộ raster. Tôi thực hiện điều này theo phương pháp bên dưới bằng cách chuyển kích thước cho IRasterCoder (pSize) sau đó lấy PixelBlock từ con trỏ raster.

Chìa khóa khác là bạn phải sử dụng SafeArray để giao tiếp với các giá trị trong phương thức này. Bạn nhận IPixelBlock từ IRasterCthon, sau đó là SafeArray từ IPixelBlock. Sau đó, bạn đọc và viết thư cho SafeArray. Khi bạn đọc xong / ghi vào SafeArray, hãy viết lại toàn bộ SafeArray của bạn thành IPixelBlock, sau đó viết IPixelBlock của bạn vào IRasterCoder, sau đó cuối cùng sử dụng IRasterCoder để đặt vị trí bắt đầu ghi và IRasterEdit để tự viết. Bước cuối cùng này là nơi bạn thực sự chỉnh sửa các giá trị của bộ dữ liệu.

    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

Dữ liệu raster AFAIK có thể được đọc theo ba cách:

  • theo tế bào (không hiệu quả);
  • bằng hình ảnh (khá hiệu quả);
  • theo khối (cách hiệu quả nhất).

Không cần phát minh lại bánh xe, tôi đề nghị đọc những slide khai sáng này của Chris Garrard.

Vì vậy, phương pháp hiệu quả nhất là đọc dữ liệu theo khối, tuy nhiên điều này sẽ gây mất dữ liệu tương ứng với các pixel nằm trên ranh giới khối trong khi áp dụng bộ lọc. Vì vậy, một cách thay thế an toàn nên bao gồm đọc toàn bộ hình ảnh cùng một lúc và sử dụng phương pháp tiếp cận gọn gàng.

Về mặt tính toán, thay vào đó, tôi nên sử dụng gdalfilter.py và ngầm hiểu cách tiếp cận VRT KernelFilteredSource để áp dụng các bộ lọc cần thiết và trên hết, tránh các tính toán nặng nề.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.