मैं एक निरंतर रेखापुंज में हर कोशिका के माध्यम से पुनरावृति कैसे करूं?


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: यदि आसन्न कोशिकाओं में से किसी एक का केंद्र सेल के लिए एक मान है, तो आउटपुट रेखापुंज को 1 मान दें ( दो निकटतम पड़ोस गणनाओं के साथ फोकल किस्म का उपयोग करके )

मानचित्र बीजगणित का उपयोग क्यों नहीं करते?

यह नीचे उल्लेख किया गया है कि मेरी समस्या को मानचित्र बीजगणित का उपयोग करके हल किया जा सकता है लेकिन जैसा कि ऊपर देखा गया है कि यह कुल मिलाकर छह रेखापुंज की गणना है, साथ ही साथ बनाई गई सभी आपदाओं के संयोजन के लिए एक है। मुझे ऐसा लगता है कि यह है बहुत सेल-दर-सेल जाने के लिए और के बजाय प्रत्येक व्यक्तिगत रूप से सात बार के माध्यम से पाशन और सात rasters बनाने के लिए काफी स्मृति का एक सा उपयोग की प्रत्येक कोशिका में एक ही बार में तुलना की सब करने के लिए और अधिक कुशल।

समस्या पर हमला कैसे किया जाना चाहिए?

उपरोक्त लिंक IPixelBlock इंटरफ़ेस का उपयोग करने की सलाह देता है, हालांकि यह ESRI प्रलेखन से स्पष्ट नहीं है कि क्या आप वास्तव में IPixelBlock के माध्यम से स्वयं एकल सेल मान प्राप्त कर रहे हैं, या यदि आप निर्धारित किए गए IPLelBlock के आकार से कई सेल मानों का उपयोग कर रहे हैं। एक अच्छा जवाब एक निरंतर रेखापुंज के सेल मूल्यों तक पहुँचने के लिए एक विधि का सुझाव देना चाहिए और कोड के पीछे कार्यप्रणाली का स्पष्टीकरण प्रदान करना चाहिए, यदि यह स्पष्ट रूप से स्पष्ट नहीं है।

संक्षेप में:

अपने सेल मूल्यों तक पहुँचने के लिए एक CONTINUOUS रेखापुंज (जिसमें कोई विशेषता तालिका नहीं है ) में प्रत्येक सेल के माध्यम से लूप करने की सबसे अच्छी विधि क्या है ?

एक अच्छे उत्तर को ऊपर वर्णित विश्लेषण चरणों को लागू करने की आवश्यकता नहीं है, इसे केवल एक रेखापुंज के सेल मूल्यों तक पहुंचने के लिए एक कार्यप्रणाली प्रदान करने की आवश्यकता है।


4
यह लगभग हमेशा एक रेखापुंज में हर कोशिका के माध्यम से लूप करने के लिए आवश्यक है। क्या आप इसके बारे में अधिक जानकारी प्रदान कर सकते हैं कि आप क्या करने की कोशिश कर रहे हैं?
user2856

2
@ ल्यूक सही है: किसी भी जीआईएस में पुनरावृत्ति रेखापुंज गणना करने के लिए अब तक का सबसे अच्छा तरीका कोशिकाओं के माध्यम से स्पष्ट रूप से लूपिंग से बचने के लिए है, क्योंकि हुड के तहत किसी भी लूपिंग को जो करना है वह पहले से ही अनुकूलित किया गया है। इसके बजाय, जीआईएस द्वारा प्रदान किए गए नक्शे बीजगणित की कार्यक्षमता का उपयोग करने का एक तरीका तलाश करें, यदि यह संभव है। यदि आप अपने विश्लेषण का वर्णन करने के लिए थे, तो आप उपयोगी उत्तर प्राप्त कर सकते हैं जो इस तरह के दृष्टिकोण का उपयोग करते हैं।
whuber

@ ल्यूक मैंने विश्लेषण का विवरण जोड़ा है।
कॉनर

1
स्पष्टीकरण के लिए धन्यवाद, कॉनर। मैं सहमत हूं कि यदि आपका जीआईएस प्रत्येक रेखापुंज गणना के लिए पर्याप्त उपरि लागू करता है, तो अपना स्वयं का लूप लिखना अधिक कुशल हो सकता है। जिज्ञासा से बाहर, स्थितियों की इस (असामान्य) सेट की इच्छित व्याख्या क्या है?
whuber

1
@ वाउचर यह मेरे रैस्टर से वेक्टर बहुभुज बनाने के लिए एज डिटेक्शन ऑपरेशंस के लिए है। आवेदन वैचारिक रूप से एक डेम से जल विज्ञान बेसिन की पहचान करने के समान है (ऊपर "चोटी" के रूप में सूचीबद्ध पड़ोस के आंकड़ों में केंद्र कोशिका के बारे में सोचें कि पानी नीचे से बह जाएगा) लेकिन जल विज्ञान के क्षेत्र से बाहर है। मैं पहले इस उद्देश्य के लिए फ्लो डायरेक्शन और बेसिन रिस्तेर्स का उपयोग कर रहा हूं, लेकिन उन तरीकों के गुणों के कारण मेरे अंतिम विश्लेषण में त्रुटि होने का खतरा है, जिनकी मुझे आवश्यकता नहीं है।
कॉनर

जवाबों:


11

मैं देखता हूं कि यह मूल पोस्टर (ओपी) द्वारा पहले ही हल कर लिया गया है, लेकिन मैं अजगर में एक सरल समाधान पोस्ट करूंगा, अगर भविष्य में कोई भी इस समस्या को हल करने के लिए अलग-अलग तरीकों से दिलचस्पी लेता है। मैं ओपन सोर्स सॉफ्टवेयर के लिए आंशिक हूं, इसलिए यहां अजगर में 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...

या हो सकता है कि आप एक सूची समझ के साथ अपने 2-डी सरणी को समतल करना चाहते हैं:

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

वैसे भी, सेल-दर-सेल आधार पर डेटा के माध्यम से पुनरावृत्ति करते हुए मूल्यों को बदलने या संपादित करने के लिए कुछ सशर्त को अपने पाश में फेंकना संभव है। इस स्क्रिप्ट को देखें मैंने डेटा तक पहुंचने के विभिन्न तरीकों के लिए लिखा था: https://github.com/azgs/hazards-viewer/blob/master/python/zonal_stats.py


मुझे इस समाधान की सादगी और सुंदरता पसंद है। मैं कुछ और दिनों की प्रतीक्षा करने जा रहा हूं और यदि कोई भी समान या अधिक गुणवत्ता के समाधान के साथ नहीं आता है तो मैं समुदाय के लाभ के लिए प्रश्न के दायरे को व्यापक बनाने के लिए टैग जोड़ूंगा और आपको इनाम दूंगा।
कॉनर

धन्यवाद, @Conor! हमें इस सप्ताह की शुरुआत में अपने कार्यस्थल पर इसी तरह की समस्या का सामना करना पड़ा और इसलिए मैंने GDAL / अजगर के साथ एक वर्ग लिखकर इसे हल किया। विशेष रूप से, हमें अपने क्लाइंट-साइड एप्लिकेशन पर एक उपयोगकर्ता से केवल एक बाउंडिंग बॉक्स दिए गए एक रेखापुंज के क्षेत्र के औसत मूल्य की गणना के लिए एक सर्वर-साइड विधि की आवश्यकता थी। क्या आपको लगता है कि अगर मैंने अपनी लिखी हुई बाकी कक्षा को जोड़ दिया तो यह फायदेमंद होगा?
asonnenschein

कोड को जोड़ने से पता चलता है कि आपके द्वारा पुनर्प्राप्त और संपादित किए गए 2-डी सरणी को पढ़ने के लिए कैसे उपयोगी होगा।
कॉनर

9

अपडेट करें! संख्यात्मक समाधान:

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.NumPyArrayToRaster गिलहरी है और अगर आप इसे अपने एलएल निर्देशांक को खिलाते हैं, तो भी विस्तार को फिर से परिभाषित करना होगा।

मैं पाठ के रूप में सहेजना पसंद करता हूं।

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

मैं गति के लिए 64 बिट के रूप में पायथन चला रहा हूं - फिलहाल इसका मतलब है कि मैं एक हेडर को numpy.savetxt फ़ीड नहीं कर सकता। इसलिए मुझे आउटपुट खोलना होगा और ASCII हैडर जोड़ना होगा जो आर्क ASCII को रैस्टर में परिवर्तित करने से पहले चाहता है

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

खस्ता संस्करण मेरी शिफ्ट रेखापुंज, गुणन, और बहुत तेजी से (2 मिनट में 1000 पुनरावृत्तियों) को चलाता है खस्ता संस्करण (15 मिनट में 1000 पुनरावृत्तियों) की तुलना में

पुराने संस्करण मैं इसे हटा सकता हूं बाद में मैंने सिर्फ एक समान स्क्रिप्ट लिखी। मैंने बिंदुओं को परिवर्तित करने और खोज कर्सर का उपयोग करने की कोशिश की। मैंने 12 घंटे में केवल 5000 पुनरावृत्तियों को प्राप्त किया। इसलिए, मैंने दूसरे तरीके की तलाश की।

ऐसा करने का मेरा तरीका प्रत्येक कोशिका के सेल केंद्र निर्देशांक के माध्यम से पुनरावृति करना है। मैं ऊपरी बाएं कोने में शुरू करता हूं और दाएं से बाएं चलता हूं। पंक्ति के अंत में मैं एक पंक्ति नीचे जाता हूं और बाईं ओर फिर से शुरू करता हूं। मेरे पास 2403 कॉलम और 2438 पंक्तियों के साथ 240 मीटर रस्टर है, इसलिए कुल 6111844 कुल सेल हैं। मैं एक पुनरावृत्ति चर और थोड़ी देर के लूप का उपयोग करता हूं। निचे देखो

कुछ नोट्स: 1 - आपको हद के निर्देशांक जानने की जरूरत है

2 - सेल सेंटर के लिए बिंदु निर्देशांक के साथ चलाएं - 1/2 में कोशिका के आकार को मानों से बढ़ाएं

3 - मेरी स्क्रिप्ट सेल वैल्यू का उपयोग मूल्य विशिष्ट रेखापुंज खींचने के लिए कर रही है, फिर मूल कक्ष पर इस रेखापुंज को केंद्र में स्थानांतरित करें। यह एक अंतिम रेखापुंज में जोड़ने से पहले सीमा का विस्तार करने के लिए एक शून्य रेखापुंज में जोड़ता है। यह सिर्फ एक उदाहरण है। आप अपने सशर्त विवरण यहाँ (दूसरी अगर लूप के भीतर कथन) रख सकते हैं।

4 - यह स्क्रिप्ट मानता है कि सभी रैस्टर मान पूर्णांक के रूप में डाले जा सकते हैं। इसका मतलब है कि आपको पहले बिना डेटा से छुटकारा पाने की आवश्यकता है। Con IsNull

6 - मैं अभी भी इससे खुश नहीं हूं और मैं इसे पूरी तरह से आर्कपी से बाहर निकालने के लिए काम कर रहा हूं। मैं इसके बजाय संख्यात्मक सरणियों के रूप में डालूंगा और वहां गणित करूंगा और फिर इसे आर्क पर वापस लाऊंगा।

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
मैंने दुर्भाग्य से ध्यान देने की उपेक्षा की है, और मैं ऊपर दिए गए अपने मूल प्रश्न में संपादित करूंगा, कि मेरे रेखापुंज में कई निरंतर मान हैं जिनमें बड़े दोहरे मान हैं, और जैसे कि यह विधि काम नहीं करेगी क्योंकि मेरे रेखापुंज में कोई विशेषता तालिका मान नहीं हैं।
कॉनर

4

एक कट्टरपंथी विचार के रूप में इसके बारे में कैसे, यह आपको अजगर या आर्कोबजेक्ट्स में प्रोग्राम करने की आवश्यकता होगी।

  1. अपने ग्रिड को एक पॉइंट फीचरक्लास में बदलें।
  2. XY फ़ील्ड बनाएँ और आबाद करें।
  3. बिंदुओं को एक ऐसे शब्दकोश में लोड करें जहाँ कुंजी X, Y का स्ट्रिंग हो और आइटम सेल वैल्यू हो।
  4. अपने शब्दकोश के माध्यम से कदम और प्रत्येक बिंदु के लिए 8 आसपास के सेल XYs पर काम करें।
  5. इन्हें अपने शब्दकोश से पुनः प्राप्त करें और अपने नियमों के साथ परीक्षण करें, जैसे ही आप एक ऐसा मान पाते हैं जो सच है कि आप बाकी परीक्षणों को छोड़ सकते हैं।
  6. परिणामों को किसी अन्य शब्दकोश में लिखें और फिर एक बिंदु पर पहले फीचरक्लास बनाकर ग्रिड में परिवर्तित करें और फिर एक ग्रिड में बिंदुओं को परिवर्तित करें।

2
बिंदु सुविधाओं के एक सेट में परिवर्तित करके, यह विचार रेखापुंज-आधारित डेटा प्रतिनिधित्व के दो गुणों को समाप्त कर देता है जो इसे इतना प्रभावी बनाते हैं: (1) पड़ोसियों को ढूंढना एक अत्यंत सरल निरंतर-समय संचालन और (2) है क्योंकि स्थानों का स्पष्ट भंडारण है जरूरत नहीं है, RAM, डिस्क, और I / O आवश्यकताएँ न्यूनतम हैं। इस प्रकार, हालांकि यह दृष्टिकोण काम करेगा, लेकिन इसकी सिफारिश करने के लिए कोई कारण ढूंढना मुश्किल है।
whuber

आपके उत्तर के लिए धन्यवाद Hornbydd मैं इस तरह से एक विधि को लागू करने के साथ ठीक हूं, लेकिन ऐसा लगता है कि चरण 4 और 5 बहुत प्रभावी कम्प्यूटेशनल बुद्धिमान नहीं होंगे। मेरी आपदाओं में न्यूनतम 62,500 कोशिकाएँ होंगी (मेरे रिज़स्टर के लिए न्यूनतम रिज़ॉल्यूशन जो मैंने निर्धारित किया है वह 250 सेल x 250 सेल है, लेकिन रिज़ॉल्यूशन आमतौर पर बहुत अधिक हो सकता है), और मुझे एक स्थानिक क्वेरी करनी होगी हर हालत के लिए मेरी तुलना को अंजाम देने के लिए ... चूंकि मेरे पास 6 शर्तें हैं, जो 6 * 62500 = 375000 स्थानिक प्रश्न होंगे। मैं नक्शे बीजगणित के साथ बेहतर होगा। लेकिन समस्या को देखने के इस नए तरीके के लिए धन्यवाद। Upvoted।
कॉनर

क्या आप इसे ASCII में नहीं बदल सकते हैं और फिर कंप्यूटिंग करने के लिए R जैसे प्रोग्राम का उपयोग कर सकते हैं?
ओलिवर बर्डेकिन

इसके अलावा मेरे पास एक जावा एप्लेट है जो मैंने लिखा है कि ऊपर की अपनी शर्तों को पूरा करने के लिए आसानी से संशोधित किया जा सकता है। यह सिर्फ एक स्मूथिंग एल्गोरिदम था लेकिन अपडेट करना बहुत आसान होगा।
ओलिवर बर्डेकिन

तो जब तक प्रोग्राम को .NET प्लेटफॉर्म से उस उपयोगकर्ता के लिए बुलाया जा सकता है जिसके पास केवल .NET फ्रेमवर्क 3.5 और आर्कगिस 10 स्थापित है। कार्यक्रम खुला स्रोत है और मैं अंत उपयोगकर्ताओं के लिए दिया जब केवल सॉफ्टवेयर आवश्यकताओं के लिए उन लोगों का इरादा है। यदि आपका उत्तर इन दोनों आवश्यकताओं को पूरा करने के लिए लागू किया जा सकता है तो इसे एक वैध उत्तर माना जाएगा। मैं प्रश्न के साथ-साथ स्पष्टीकरण के लिए एक संस्करण टैग जोड़ूंगा।
कॉनर

2

एक तरकीब:

इसका हल मैंने आज पहले कर लिया था। कोड इस पद्धति का एक अनुकूलन है । इसके पीछे की अवधारणा बहुत कठिन नहीं थी क्योंकि एक बार मैंने यह पता लगा लिया था कि वस्तुओं को वास्तव में क्या करते हैं। नीचे दी गई विधि में दो इनपुट डेटासेट (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 रैस्टर डेटा को तीन तरीकों से पढ़ा जा सकता है:

  • सेल द्वारा (अकुशल);
  • छवि द्वारा (काफी कुशल);
  • द्वारा ब्लॉक (सबसे कुशल तरीका)।

पहिए को फिर से लगाए बिना, मैं क्रिस गारार्ड की इन ज्ञानवर्धक स्लाइडों को पढ़ने का सुझाव देता हूं ।

तो सबसे कुशल विधि ब्लॉक द्वारा डेटा पढ़ा जाता है, हालांकि इससे फ़िल्टर को लागू करते समय ब्लॉक सीमाओं पर स्थित पिक्सेल के पत्राचार में डेटा हानि होगी। तो एक सुरक्षित वैकल्पिक तरीका एक बार में पूरी छवि को पढ़ने और संख्यात्मक दृष्टिकोण का उपयोग करने में शामिल होना चाहिए।

कम्प्यूटेशनल पक्ष पर, इसके बजाय, मुझे gdalfilter.py का उपयोग करना चाहिए और आवश्यक फ़िल्टर को लागू करने के लिए और इसके बाद के संस्करण में VRT कर्नेलफिल्डसोर्स स्रोत का उपयोग करना चाहिए , और भारी गणना से बचें।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.