Sürekli bir taramada her hücreyi nasıl yineleyebilirim?


13

Daha fazla ayrıntı için bu bağlantıya bakın.

Sorun:

Ben sürekli raster (bir öznitelik tablo olan bir), hücre hücre ve döngü değerini almak için döngü istiyorum . Raster hesap makinesini kullanmadan aşağıda ayrıntılı olarak verilen harita cebir adımlarını taklit ederek bu değerleri alıp koşullu olarak çalıştırmak istiyorum.

Aşağıdaki yorum istekleri doğrultusunda, soruna arka plan sağlayan ve aşağıdaki "Analiz gerekli:" adlı bölümde böyle bir yöntem uygulama ihtiyacını gerekçelendiren ayrıntılar ekledim.

Aşağıda önerilen analizin, arka plan sağlayarak sorunumla ilgili olmasına rağmen, bir cevapta uygulanması gerekmez. Sorunun kapsamı, yalnızca hücre değerlerini almak / ayarlamak için sürekli bir tarama yoluyla yineleme ile ilgilidir.

Analiz gerekli:

Aşağıdaki koşullardan HERHANGİ BİRİ yerine getirilirse, çıkış hücresine 1 değeri verin. Çıkış hücresine yalnızca koşullardan hiçbiri yerine getirilmezse 0 değerini verin.

Koşul 1: Hücre değeri üst ve alt hücrelerden büyükse, 1 değerini verin:

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

Çekirdek dosyası şöyle görünür:

3 3 
0 1 0
0 0 0
0 1 0

Koşul 2: Hücre değeri sol ve sağ hücrelerden büyükse, 1 değerini verin:

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

Çekirdek dosyası şöyle görünür:

3 3 
0 0 0
1 0 1
0 0 0  

Koşul 3: Hücre değeri üst sol ve alt sağ hücrelerden büyükse, 1 değerini verin:

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

Çekirdek dosyası şöyle görünür:

3 3 
1 0 0
0 0 0
0 0 1 

Koşul 4: Hücre değeri alt sol ve sağdan büyük hücrelerden büyükse, 1 değerini verin:

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

Çekirdek dosyası şöyle görünür:

3 3 
0 0 1
0 0 0
1 0 0 

Durum 5: Eğer herhangi bir komşu hücrelerin bir merkezi hücreye bir değere eşit olan, 1 değerine tarama çıktı vermek ( iki en yakın komşu hesaplamalar ile fokal çeşitli kullanarak )

Harita cebiri neden kullanılmıyor?

Aşağıda, sorunumun harita cebiri kullanılarak çözülebileceği kaydedildi, ancak yukarıda görüldüğü gibi, toplam altı raster hesaplama artı bir arada yaratılan tüm rasterleri birleştirmek için bir tane. Bana öyle geliyor ki , her bir hücrede yedi kez döngü yapmak ve yedi raster oluşturmak için oldukça fazla bellek kullanmak yerine her hücrede bir kerede tüm karşılaştırmaları yapmak çok daha verimli.

Sorun nasıl ele alınmalı?

Yukarıdaki bağlantı IPixelBlock arayüzünün kullanılmasını önerir, ancak ESRI belgelerinden IPixelBlock üzerinden tek bir hücre değerine gerçekten erişip erişmediğiniz veya ayarladığınız IPixelBlock boyutundan birden fazla hücre değerine erişip erişmediğiniz açık değildir. İyi bir cevap, sürekli bir raster hücre değerlerine erişmek için bir yöntem önermeli ve açıkça belli değilse, kodun arkasındaki metodolojinin bir açıklamasını sağlamalıdır.

Özetle:

Hücre değerlerine erişmek için bir CONTINUOUS rasterindeki ( öznitelik tablosu olmayan ) her hücrede döngü oluşturmanın en iyi yöntemi nedir ?

İyi bir yanıtın yukarıda açıklanan analiz adımlarını uygulaması gerekmez, yalnızca bir raster hücre değerlerine erişmek için bir metodoloji sağlamak gerekir.


4
Rasterdeki her hücrede döngü yapmak neredeyse her zaman gerekli değildir. Ne yapmaya çalıştığınız hakkında daha fazla bilgi verebilir misiniz?
user2856 23:13

2
@ Luke doğru: herhangi bir CBS'de yinelemeli bir raster hesaplaması yapmanın en iyi yolu , hücreler arasında açıkça döngüden kaçınmaktır , çünkü kaputun altında yapılması gereken herhangi bir döngü zaten optimize edilmiştir. Bunun yerine, eğer mümkünse, CBS tarafından sağlanan harita cebir işlevini kullanmanın bir yolunu arayın. Analizinizi açıklayacak olsanız, böyle bir yaklaşımı kullanan faydalı cevaplar alabilirsiniz.
whuber

@Luke Analizin ayrıntılarını ekledim.
Conor

1
Açıklama için teşekkürler Conor. GIS'iniz her bir raster hesaplaması için önemli bir ek yüke maruz kalırsa, kendi döngünüzü yazmanın daha verimli olabileceğini kabul ediyorum. Meraktan, bu (olağandışı) koşul kümesinin amaçlanan yorumu nedir?
whuber

1
@whuber Rasterimden vektör çokgenleri oluşturmak kenar algılama işlemleri içindir. Uygulama kavramsal olarak bir DEM'den hidroloji havzalarını tanımlamaya benzer (yukarıda belirtilen mahalle istatistiklerinde merkez hücrenin, suyun aşağı doğru akacağı "tepe" olarak düşünün), ancak hidroloji alanının dışındadır. Daha önce bu amaçla Flow Direction ve Havza Rasters kullanıyordum, ancak bu yöntemlerin özellikleri tam olarak ihtiyacım olan şey olmadığı için son analizimde hataya eğilimli.
Conor

Yanıtlar:


11

Bunun Orijinal Poster (OP) tarafından zaten çözülmüş olduğunu görüyorum, ancak gelecekte herhangi bir kişinin bu sorunu çözmek için farklı yollarla ilgilenmesi durumunda python'da basit bir çözüm yayınlayacağım. Ben açık kaynak yazılım kısmi, bu yüzden python GDAL kullanarak bir çözüm:

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)

İşlevi şu şekilde uygulayın:

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

Ardından, iç içe geçmiş bir döngü ile verilerinizi tekrarlayın:

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

Veya 2-B dizinizi bir liste kavrayışı ile düzleştirmek isteyebilirsiniz:

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

Her neyse, veriler hücre bazında yinelenirken, değerleri değiştirmek / düzenlemek için döngünüze bazı şartlar atmak mümkündür. Verilere erişmenin farklı yolları için yazdığım bu komut dosyasına bakın: https://github.com/azgs/hazards-viewer/blob/master/python/zonal_stats.py .


Bu çözümün sadeliğini ve zarafetini seviyorum. Birkaç gün daha bekleyeceğim ve hiç kimse eşit veya daha yüksek kalitede bir çözümle gelmezse, topluluğun yararı için sorunun kapsamını genişletmek ve size ödül vermek için etiketler ekleyeceğim.
Conor

Teşekkürler @Conor! Bu hafta başında işyerimde benzer bir sorunla karşılaştık ve böylece GDAL / python ile bir sınıf yazarak çözdüm. Özellikle, istemci tarafı uygulamamızdaki bir kullanıcıdan yalnızca sınırlayıcı bir kutu verilen bir raster alanının ortalama değerini hesaplamak için bir sunucu tarafı yöntemine ihtiyacımız vardı. Yazdığım dersin geri kalanını eklesem bunun yararlı olacağını düşünüyor musunuz?
asonnenschein

Aldığınız 2-B diziyi nasıl okuyacağınızı ve değerlerini nasıl düzenleyeceğinizi gösteren kod eklemek yardımcı olacaktır.
Conor

9

Güncelleme! Numpy çözümü:

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

Bu nedenle, bitmiş diziyi arkpy kullanarak raster haline getirmek zahmetlidir. arcpy.NumPyArrayToRaster sincaplıdır ve LL koordinatlarınızı besleseniz bile uzantıları yeniden tanımlama eğilimindedir.

Metin olarak kaydetmeyi tercih ederim.

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

Python'u hız için 64 bit olarak çalıştırıyorum - şu andan itibaren bu numpy.savetxt üstbilgisini besleyemediğim anlamına geliyor. Bu yüzden çıktıyı açmam ve Arc'ın ASCII'yi Raster'a dönüştürmeden önce istediği ASCII başlığını eklemeliyim

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

Numpy sürümü, kaydırma rasterimi, çarpımlarımı ve eklememi, arcpy versiyonundan (15 dakika içinde 1000 iterasyon) çok daha hızlı (2 dakika içinde 1000 iterasyon) çalıştırıyor

ESKİ SÜRÜM Bunu daha sonra silebilirim Ben sadece benzer bir senaryo yazdım. Noktalara dönüştürmeyi ve arama imlecini kullanmayı denedim. 12 saat içinde sadece 5000 tekrar aldım. Başka bir yol aradım.

Bunu yapmanın yolu her bir hücrenin hücre merkezi koordinatlarını tekrarlamaktır. Sol üst köşeden başlıyorum ve sağdan sola hareket ediyorum. Satırın sonunda bir satır aşağı gidip tekrar soldan başlıyorum. 2603 sütun ve 2438 sıralı 240 m'lik bir tarama cihazım var, bu yüzden toplam 6111844 toplam hücre. Bir yineleyici değişkeni ve while döngüsü kullanıyorum. Aşağıya bakınız

Birkaç not: 1 - derecenin koordinatlarını bilmeniz gerekir

2 - hücre merkezi için nokta koordinatları ile çalıştırın - hücre boyutunun değerlerinden 1/2 oranında hareket edin

3 - Betiğim, değere özgü bir raster çekmek için hücre değerini kullanıyor, ardından bu rasteri orijinal hücrenin ortasına kaydırın. Bu, son bir rastere eklenmeden önce kapsamı genişletmek için sıfır bir raster ekler. Bu sadece bir örnek. Koşullu ifadelerinizi buraya koyabilirsiniz (while döngüsü içindeki if ifadesinin ikincisi).

4 - Bu komut dosyası, raster değerlerinin tamsayı olarak kullanılabileceğini varsayar. Bu, ilk önce hiçbir veriden kurtulmanız gerektiği anlamına gelir. Con IsNull.

6 - Hala bundan memnun değilim ve bunu tamamen yaylıdan çıkarmak için çalışıyorum. Ben numpy diziler olarak tercih ediyorum ve orada matematik yapmak sonra Arc geri getirmek.

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 kullanmayı deneyin. Bu kod snippet'i raster hücre değerlerini güncellemek içindir, ancak yinelemenin temellerini gösterir:

Raster öznitelik tablosuna nasıl yeni bir alan ekleyebilir ve bu alanı nasıl döngüleyebilirim?

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

Tabloyu gezdikten sonra kullanarak belirli bir alan satırı değeri elde edebilirsiniz row.get_Value(yourfieldIndex). Google

arcobjects row.get_Value

bunu gösteren çok sayıda örnek alabilmelisiniz.

Umarım yardımcı olur.


1
Maalesef not etmeyi ihmal ettim ve yukarıdaki orijinal sorumda, rasterimin büyük çift değerlerden oluşan birçok sürekli değere sahip olduğunu ve rasterimin nitelik tablosu değerleri olmadığı için bu yöntem çalışmayacaktır.
Conor

4

Bu radikal bir fikir olarak, python veya ArcObjects'te programlamanızı gerektirir.

  1. Kılavuzunuzu nokta özellik sınıflarına dönüştürün.
  2. XY alanları oluşturun ve doldurun.
  3. Noktaları, anahtarın X, Y dizesi ve öğenin hücre değeri olduğu bir sözlüğe yükleyin .
  4. Sözlüğünüze adım atın ve her nokta için 8 XY hücresini çevirin.
  5. Bunları sözlüğünüzden alın ve kurallarınızla test edin, doğru bir değer bulduğunuzda testlerin geri kalanını atlayabilirsiniz.
  6. Sonuçları başka bir sözlüğe yazın ve önce bir nokta FeatureClass noktası oluşturarak ızgaraya geri dönüştürün ve ardından noktaları bir ızgaraya dönüştürün.

2
Bir dizi nokta özelliğine dönüştürerek, bu fikir, raster tabanlı veri sunumunun bu kadar etkili olmasını sağlayan iki niteliğini ortadan kaldırır: (1) komşuları bulmak son derece basit bir sabit zamanlı işlemdir ve (2) konumların açıkça depolanması RAM, disk ve G / Ç gereksinimleri minimumdur. Bu nedenle, bu yaklaşım işe yarayacak olsa da, bunu önermek için herhangi bir neden bulmak zor.
whuber

Cevabınız için teşekkürler Hornbydd. Böyle bir yöntem uygulamak ile sorun değil, ama adım 4 & 5 çok etkili hesaplamalı akıllıca olmaz gibi görünüyor. Benim rasterlerim en az 62.500 hücreye sahip olacak (ayarladığım rasterim için minimum çözünürlük 250 hücre x 250 hücredir, ancak çözünürlük daha fazla olabilir ve genellikle daha fazlasını içerir) ve uzamsal bir sorgu yapmak zorundayım karşılaştırmalarımı yürütmek için her koşul için ... 6 koşulum olduğu için bu 6 * 62500 = 375000 uzamsal sorgu olacaktır. Harita cebiri ile daha iyi olurdum. Ancak sorunu görüntülemenin bu yeni yolu için teşekkürler. Upvoted.
Conor

Bunu sadece ASCII'ye dönüştürüp hesaplama yapmak için R gibi bir program kullanamaz mısınız?
Oliver Burdekin

Ayrıca, yukarıdaki koşullarınızı karşılamak için kolayca değiştirilebilecek bir Java uygulamam var. Sadece bir düzeltme algoritmasıydı, ancak güncellemelerin yapılması oldukça kolay olurdu.
Oliver Burdekin

Yalnızca .NET Framework 3.5 ve ArcGIS 10 yüklü bir kullanıcı için program .NET platformundan çağrılabildiği sürece. Program açık kaynak kodlu ve son kullanıcılara teslim edildiğinde bunların tek yazılım gereksinimi olmasını amaçlıyorum. Cevabınız bu iki gereksinimi karşılamak için uygulanabilirse, geçerli bir cevap olarak kabul edilecektir. Açıklığa kavuşturmak için soruya bir sürüm etiketi de ekleyeceğim.
Conor

2

Bir çözüm:

Bunu bugün daha erken çözmüştüm. Kod, bu yöntemin bir uyarlamasıdır . Raster ile arayüz için kullanılan nesnelerin gerçekte ne yaptığını anladıktan sonra bunun arkasındaki kavram çok zor değildi. Aşağıdaki yöntem iki giriş veri kümesi alır (inRasterDS ve outRasterDS). Her ikisi de aynı veri kümesidir, ben sadece inRasterDS'nin bir kopyasını yaptım ve outRasterDS olarak yönteme geçtim. Bu şekilde, her ikisi de aynı ölçüde, uzamsal referansa vb. Sahip olur. Yöntem inRasterDS, hücreden hücreye değerleri okur ve bunlara en yakın komşu karşılaştırmalarını yapar. Bu karşılaştırmaların sonuçlarını outRasterDS'de saklanan değerler olarak kullanır.

Süreç:

Piksel değerlerine ulaşmak için IRasterCursor -> IPixelBlock -> SafeArray ve rasterlere yenilerini yazmak için IRasterEdit kullandım. IPixelBlock oluşturduğunuzda, makineye okumak / yazmak istediğiniz alanın boyutunu ve konumunu söylersiniz. Rasterlerin yalnızca alt yarısını düzenlemek istiyorsanız, IPixelBlock parametreleriniz olarak ayarlayın. Tüm raster üzerinde döngü yapmak istiyorsanız, IPixelBlock'u tüm raster boyutuna eşit olarak ayarlamanız gerekir. Bunu IRasterCursor (pSize) boyutuna geçip PixelBlock'u raster imlecinden alarak aşağıdaki yöntemde yaparım.

Diğer anahtar, bu yöntemdeki değerlerle arabirim oluşturmak için SafeArray kullanmanızdır. IPixelBlock'u IRasterCursor'dan, sonra SafeArray'ı IPixelBlock'tan alırsınız. Sonra SafeArray'a okur ve yazarsınız. SafeArray'a okuma / yazma işlemini bitirdiğinizde, tüm SafeArray'ınızı IPixelBlock'a geri yazın, sonra IPixelBlock'unuzu IRasterCursor'a yazın, son olarak yazma işlemini başlatmak için konumu ayarlamak için IRasterCursor'ı ve yazma işlemini yapmak için IRasterEdit'i kullanın. Bu son adım, veri kümesinin değerlerini gerçekten düzenlediğiniz yerdir.

    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 tarama verileri üç şekilde okunabilir:

  • hücre ile (verimsiz);
  • görüntü ile (oldukça verimli);
  • bloklarla (en verimli yol).

Tekerleği yeniden icat etmeden , Chris Garrard'ın bu aydınlatıcı slaytlarını okumanızı öneririm .

Bu nedenle en verimli yöntem verileri blok halinde okumaktır, ancak bu, filtre uygulanırken blok sınırları üzerinde bulunan piksellerin yazışmalarında veri kaybına neden olur. Bu nedenle güvenli bir alternatif yol, görüntünün tamamını aynı anda okumak ve numpy yaklaşımını kullanmak olmalıdır.

Hesaplamalı tarafta, bunun yerine, gerekli filtreleri uygulamak ve her şeyden önce ağır hesaplamalardan kaçınmak için gdalfilter.py ve dolaylı olarak VRT KernelFilteredSource yaklaşımını kullanmalıyım .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.