Bagaimana cara saya mengulangi setiap sel dalam raster berkelanjutan?

13

Lihat tautan ini untuk lebih jelasnya.

Masalah:

Saya ingin mengulang melalui raster berkelanjutan (yang tidak memiliki tabel atribut), sel demi sel, dan mendapatkan nilai sel. Saya ingin mengambil nilai-nilai itu dan menjalankan persyaratannya, meniru langkah-langkah aljabar peta yang dirinci di bawah ini tanpa benar-benar menggunakan kalkulator raster.

Per permintaan komentar di bawah ini, saya telah menambahkan detail yang memberikan latar belakang masalah dan membenarkan perlunya menerapkan metode seperti pada bagian di bawah ini yang disebut "Analisis yang diperlukan:".

Analisis yang diajukan di bawah ini, meskipun relevan dengan masalah saya dengan memberikan latar belakang, tidak perlu diimplementasikan dalam jawaban. Ruang lingkup pertanyaan hanya berkaitan dengan iterasi melalui raster berkelanjutan untuk mendapatkan / menetapkan nilai sel.

Analisis yang dibutuhkan:

Jika salah satu dari kondisi berikut terpenuhi, berikan sel output nilai 1. Hanya beri sel output nilai 0 jika tidak ada kondisi yang terpenuhi.

Kondisi 1: Jika nilai sel lebih besar dari sel atas dan bawah, beri nilai 1:

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

Di mana file kernel terlihat seperti ini:

3 3 
0 1 0
0 0 0
0 1 0

Kondisi 2: Jika nilai sel lebih besar dari sel kiri dan kanan, beri nilai 1:

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

Di mana file kernel terlihat seperti ini:

3 3 
0 0 0
1 0 1
0 0 0  

Kondisi 3: Jika nilai sel lebih besar dari sel topleft dan bottomright, beri nilai 1:

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

Di mana file kernel terlihat seperti ini:

3 3 
1 0 0
0 0 0
0 0 1 

Kondisi 4: Jika nilai sel lebih besar dari bottomleft dan sel topright, beri nilai 1:

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

Di mana file kernel terlihat seperti ini:

3 3 
0 0 1
0 0 0
1 0 0 

Kondisi 5: Jika salah satu sel yang berdekatan memiliki nilai EQUAL untuk sel pusat, berikan nilai raster nilai 1 ( menggunakan varietas fokus dengan dua perhitungan lingkungan terdekat )

Mengapa tidak menggunakan aljabar peta?

Telah dicatat di bawah ini bahwa masalah saya dapat diselesaikan dengan menggunakan aljabar peta tetapi seperti yang terlihat di atas ini adalah total dari enam perhitungan raster, ditambah satu untuk menggabungkan semua raster yang dibuat bersama-sama. Menurut saya, jauh lebih efisien untuk melakukan sel demi sel dan melakukan semua perbandingan sekaligus di setiap sel daripada mengulangi masing-masing secara terpisah tujuh kali dan menggunakan sedikit memori untuk membuat tujuh raster.

Bagaimana seharusnya masalah diserang?

Tautan di atas menyarankan untuk menggunakan antarmuka IPixelBlock, namun tidak jelas dari dokumentasi ESRI apakah Anda benar-benar mengakses nilai sel tunggal itu sendiri melalui IPixelBlock, atau jika Anda mengakses beberapa nilai sel dari ukuran IPixelBlock yang Anda atur. Sebuah jawaban yang baik harus menyarankan metode untuk mengakses nilai-nilai sel raster terus menerus dan memberikan penjelasan tentang metodologi di balik kode, jika tidak jelas.

Singkatnya:

Apa metode terbaik untuk loop melalui setiap sel dalam raster TERUS-MENERUS (yang tidak memiliki tabel atribut ) untuk mengakses nilai selnya?

Jawaban yang baik tidak perlu mengimplementasikan langkah-langkah analisis yang dijelaskan di atas, hanya perlu menyediakan metodologi untuk mengakses nilai sel raster.

Conor
sumber
4
Hampir selalu tidak perlu untuk mengulang setiap sel dalam raster. Bisakah Anda memberikan informasi lebih lanjut tentang apa yang Anda coba lakukan?
user2856
2
@ Lukas benar: sejauh ini cara terbaik untuk melakukan perhitungan raster berulang dalam GIS adalah untuk menghindari perulangan secara eksplisit melalui sel, karena di bawah kap setiap perulangan yang harus dilakukan telah dioptimalkan. Alih-alih, cari cara untuk menggunakan fungsionalitas aljabar peta yang disediakan oleh GIS, jika memungkinkan. Jika Anda mendeskripsikan analisis Anda, Anda mungkin mendapatkan jawaban yang bermanfaat yang menggunakan pendekatan semacam itu.
whuber
@ Lukas Saya telah menambahkan rincian analisis.
Conor
1
Terima kasih atas klarifikasi, Conor. Saya setuju bahwa jika GIS Anda mengeluarkan biaya besar untuk setiap perhitungan raster, menulis loop Anda sendiri mungkin lebih efisien. Karena penasaran, apa interpretasi yang dimaksud dari serangkaian kondisi (tidak biasa) ini?
Whuber
1
@whuber Ini untuk operasi deteksi tepi untuk membuat poligon vektor dari raster saya. Aplikasi ini secara konseptual mirip dengan mengidentifikasi cekungan hidrologi dari DEM (pikirkan sel pusat dalam statistik lingkungan yang tercantum di atas sebagai "puncak" dari mana air akan mengalir turun lereng) tetapi berada di luar bidang hidrologi. Saya sebelumnya telah menggunakan Flow Direction dan Basin Raster untuk tujuan ini, tetapi mereka cenderung mengalami kesalahan dalam analisis akhir saya karena sifat-sifat metode ini tidak persis seperti yang saya butuhkan.
Conor

Jawaban:

11

Saya melihat ini telah dipecahkan oleh Original Poster (OP), tetapi saya akan memposting solusi sederhana dengan python kalau-kalau ada orang di masa depan yang tertarik pada berbagai cara untuk menyelesaikan masalah ini. Saya sebagian menggunakan perangkat lunak sumber terbuka, jadi inilah solusi menggunakan GDAL dalam 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)

Terapkan fungsi seperti ini:

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

Kemudian, ulangi data Anda dengan loop bersarang:

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

Atau mungkin Anda ingin meratakan array 2-D Anda dengan pemahaman daftar:

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

Bagaimanapun, saat iterasi melalui data pada sel-demi-sel itu mungkin untuk melemparkan beberapa kondisional ke dalam loop Anda untuk mengubah / mengedit nilai. Lihat skrip yang saya tulis untuk berbagai cara mengakses data: https://github.com/azgs/hazards-viewer/blob/master/python/zonal_stats.py .

asonnenschein
sumber
Saya suka kesederhanaan dan keanggunan solusi ini. Saya akan menunggu beberapa hari lagi dan jika tidak ada orang lain yang memberikan solusi dengan kualitas yang sama atau lebih besar, saya akan menambahkan tag untuk memperluas cakupan pertanyaan untuk kepentingan komunitas dan memberi Anda hadiah.
Conor
Terima kasih, @Conor! Kami mengalami masalah yang sama di tempat kerja saya awal minggu ini dan jadi saya menyelesaikannya dengan menulis kelas dengan GDAL / python. Secara khusus, kami membutuhkan metode sisi server untuk menghitung nilai rata-rata area raster yang hanya diberi kotak pembatas dari pengguna pada aplikasi sisi klien kami. Apakah Anda pikir akan bermanfaat jika saya menambahkan sisa kelas yang saya tulis?
asonnenschein
Menambahkan kode yang menunjukkan cara membaca array 2-D yang Anda ambil dan mengedit nilainya akan sangat membantu.
Conor
9

Memperbarui! Solusi 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

Jadi, mendapatkan array yang sudah selesai kembali ke raster menggunakan arcpy merepotkan. arcpy.NumPyArrayToRaster tupai dan cenderung mendefinisikan ulang luasan bahkan jika Anda memberi makan koordinat LL Anda.

Saya lebih suka menyimpan sebagai teks.

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

Saya menjalankan Python sebagai 64 bit untuk kecepatan - pada saat ini ini berarti saya tidak dapat memberi makan numpy.savetxt header. Jadi saya harus membuka output dan menambahkan header ASCII yang diinginkan Arc sebelum mengubah ASCII ke Raster

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

Versi numpy menjalankan raster shift, perkalian, dan penambahan saya jauh lebih cepat (1000 iterations dalam 2 menit) daripada versi arcpy (1000 iterations dalam 15 menit)

VERSI LAMA Saya dapat menghapus ini nanti saya hanya menulis skrip yang sama. Saya mencoba mengonversi ke titik dan menggunakan kursor pencarian. Saya hanya mendapatkan 5.000 iterasi dalam 12 jam. Jadi, saya mencari cara lain.

Cara saya melakukan ini adalah beralih melalui koordinat pusat sel dari setiap sel. Saya mulai di sudut kiri atas dan bergerak ke kanan ke kiri. Di akhir baris saya bergerak ke bawah baris dan mulai lagi di sebelah kiri. Saya memiliki raster 240 m dengan 2603 kolom dan 2438 baris sehingga total total 6111844 sel. Saya menggunakan variabel iterator dan loop sementara. Lihat di bawah

Beberapa catatan: 1 - Anda perlu mengetahui koordinat sejauh ini

2 - jalankan dengan koordinat titik untuk pusat sel - pindahkan 1/2 ukuran sel dari nilai batas

3 - Skrip saya menggunakan nilai sel untuk menarik raster nilai tertentu, lalu menggeser raster ini ke pusat pada sel asli. Ini menambah raster nol untuk memperluas jangkauan sebelum menambahkan ke raster akhir. Ini hanya sebuah contoh. Anda bisa meletakkan pernyataan kondisional Anda di sini (pernyataan if kedua dalam loop while).

4 - Skrip ini mengasumsikan semua nilai raster dapat digunakan sebagai bilangan bulat. Ini berarti Anda harus menyingkirkan no data terlebih dahulu. Con IsNull.

6 - Saya masih tidak senang dengan ini dan saya berusaha untuk mengambil ini sepenuhnya dari arcpy. Saya lebih suka berperan sebagai array numpy dan melakukan matematika di sana kemudian membawanya kembali ke 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")
SamEPA
sumber
4

Coba gunakan IGridTable, ICursor, IRow. Cuplikan kode ini untuk memperbarui nilai sel raster, namun ini menunjukkan dasar-dasar pengulangan:

Bagaimana saya bisa menambahkan bidang baru dalam tabel atribut raster dan mengulanginya?

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

Setelah Anda melintasi tabel, Anda bisa mendapatkan nilai baris bidang tertentu dengan menggunakan row.get_Value(yourfieldIndex). Jika Anda Google

arcobjects row.get_Value

Anda harus bisa mendapatkan banyak contoh yang menunjukkan ini.

Semoga itu bisa membantu.

artwork21
sumber
1
Sayangnya saya lupa untuk memperhatikan, dan saya akan mengedit dalam pertanyaan asli saya di atas, bahwa raster saya memiliki banyak nilai kontinu yang terdiri dari nilai ganda yang besar, dan karena itu metode ini tidak akan berfungsi karena raster saya tidak memiliki nilai tabel atribut.
Conor
4

Bagaimana ini sebagai ide radikal, Anda harus memprogram dalam python atau ArcObjects.

  1. Konversi kisi-kisi Anda ke suatu titik fitur kelas.
  2. Buat bidang XY dan isi.
  3. Memuat poin ke dalam kamus di mana kunci adalah string X, Y dan item adalah nilai sel ..
  4. Langkah melalui kamus Anda dan untuk setiap titik bekerja 8 sel XY sekitarnya.
  5. Ambil ini dari kamus Anda dan uji dengan aturan Anda, segera setelah Anda menemukan nilai yang benar, Anda dapat melewati sisa tes.
  6. Tulis hasilnya ke kamus lain dan kemudian konversikan kembali ke kisi dengan terlebih dahulu membuat FeatureClass titik dan kemudian mengonversi poin ke kisi.
Hornbydd
sumber
2
Dengan mengonversi fitur seperangkat titik, ide ini menghilangkan dua kualitas representasi data berbasis raster yang membuatnya sangat efektif: (1) menemukan tetangga adalah operasi waktu konstan yang sangat sederhana dan (2) karena penyimpanan eksplisit lokasi adalah tidak diperlukan, persyaratan RAM, disk, dan I / O minimal. Jadi, meskipun pendekatan ini akan berhasil, sulit untuk menemukan alasan untuk merekomendasikannya.
Whuber
Terima kasih atas jawaban Anda Hornbydd. Saya setuju dengan menerapkan metode seperti ini, tetapi sepertinya langkah 4 & 5 tidak akan menjadi komputasi yang sangat efektif. Raster saya akan memiliki minimum 62.500 sel (resolusi minimum untuk raster saya yang telah saya tetapkan adalah 250 sel x 250 sel, tetapi resolusi dapat dan biasanya memang terdiri dari lebih banyak), dan saya harus melakukan kueri spasial untuk setiap kondisi untuk menjalankan perbandingan saya ... Karena saya memiliki 6 kondisi, itu akan menjadi 6 * 62500 = 375000 kueri spasial. Saya akan lebih baik dengan aljabar peta. Tapi terima kasih atas cara baru dalam melihat masalah ini. Terpilih.
Conor
Tidak bisakah Anda mengonversinya menjadi ASCII dan kemudian menggunakan program seperti R untuk melakukan komputasi?
Oliver Burdekin
Plus saya punya applet Java yang saya tulis yang dapat dengan mudah dimodifikasi untuk memenuhi kondisi Anda di atas. Itu hanya algoritma perataan tetapi pembaruan akan sangat mudah dilakukan.
Oliver Burdekin
Selama program dapat dipanggil dari platform .NET untuk pengguna yang hanya memiliki .NET Framework 3.5 dan ArcGIS 10 diinstal. Program ini open source dan saya bermaksud bagi mereka untuk menjadi satu-satunya persyaratan perangkat lunak ketika dikirim ke pengguna akhir. Jika jawaban Anda dapat diterapkan untuk memenuhi kedua persyaratan ini maka itu akan dianggap sebagai jawaban yang valid. Saya akan menambahkan tag versi ke pertanyaan juga untuk klarifikasi.
Conor
2

Sebuah solusi:

Saya menyelesaikan ini sebelumnya hari ini. Kode ini merupakan adaptasi dari metode ini . Konsep di balik ini tidak terlalu sulit setelah saya menemukan apa objek yang digunakan untuk berinteraksi dengan raster sebenarnya. Metode di bawah ini mengambil dua dataset input (inRasterDS dan outRasterDS). Keduanya merupakan dataset yang sama, saya baru saja membuat salinan inRasterDS dan meneruskannya ke metode seperti outRasterDS. Dengan cara ini mereka berdua memiliki tingkat yang sama, referensi spasial, dll. Metode ini membaca nilai-nilai dari dalamRasterDS, sel demi sel, dan melakukan perbandingan tetangga terdekat pada mereka. Ia menggunakan hasil perbandingan tersebut sebagai nilai yang disimpan di outRasterDS.

Proses:

Saya menggunakan IRasterCursor -> IPixelBlock -> SafeArray untuk mendapatkan nilai pixel dan IRasterEdit untuk menulis yang baru ke raster. Saat Anda membuat IPixelBlock, Anda memberi tahu mesin ukuran dan lokasi area yang ingin Anda baca / tulis. Jika Anda hanya ingin mengedit bagian bawah raster, Anda menetapkannya sebagai parameter IPixelBlock Anda. Jika Anda ingin mengulang seluruh raster, Anda harus mengatur IPixelBlock sama dengan ukuran seluruh raster. Saya melakukan ini dalam metode di bawah ini dengan mengirimkan ukuran ke IRasterCursor (pSize) kemudian mendapatkan PixelBlock dari kursor raster.

Kunci lainnya adalah Anda harus menggunakan SafeArray untuk berinteraksi dengan nilai-nilai dalam metode ini. Anda mendapatkan IPixelBlock dari IRasterCursor, lalu SafeArray dari IPixelBlock. Kemudian Anda membaca dan menulis ke SafeArray. Ketika Anda selesai membaca / menulis ke SafeArray, tulis seluruh SafeArray Anda kembali ke IPixelBlock, lalu tulis IPixelBlock Anda ke IRasterCursor, lalu akhirnya gunakan IRasterCursor untuk mengatur lokasi untuk mulai menulis dan IRasterEdit untuk melakukan penulisan itu sendiri. Langkah terakhir ini adalah tempat Anda benar-benar mengedit nilai dataset.

    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);
        }

    }
Conor
sumber
1

Data raster AFAIK dapat dibaca dalam tiga cara:

  • oleh sel (tidak efisien);
  • oleh gambar (cukup efisien);
  • oleh blok (cara paling efisien).

Tanpa menciptakan kembali roda, saya sarankan untuk membaca slide Chris Garrard yang mencerahkan ini .

Jadi metode yang paling efisien adalah membaca data dengan blok, namun ini akan menyebabkan hilangnya data dalam korespondensi piksel yang terletak di atas batas blok saat menerapkan filter. Jadi cara alternatif yang aman harus terdiri dari membaca seluruh gambar sekaligus dan menggunakan pendekatan numpy.

Di sisi komputasi, sebagai gantinya, saya harus menggunakan gdalfilter.py dan secara implisit pendekatan VRT KernelFilteredSource untuk menerapkan filter yang diperlukan dan, di atas semua itu, hindari perhitungan yang berat.

Antonio Falciano
sumber