रेखापुंज के भीतर दिए गए पिक्सेल मान की न्यूनतम बाउंडिंग सीमा ज्ञात करना?


9

मैं सोच रहा हूं कि क्या किसी विशेष मूल्य के साथ एक रेखापुंज के लिए न्यूनतम बाउंडिंग सीमा खोजने का एक तरीका है। मैंने एक वैश्विक छवि से रेखापुंज किया और काफी हद तक NoData क्षेत्र के साथ वैश्विक सीमा के रूप में सेट है। मैं इस रैस्टर से NoData क्षेत्र को निकालना चाहता हूं और विशेष मूल्य के पिक्सल वाले क्षेत्र को बनाए रखना चाहता हूं। मैं यह कैसे कर सकता हूँ?

यहां मेरा उदाहरण है: मैं मूल्य = 1 (नीला क्षेत्र) निकालना चाहता हूं और आगे की प्रक्रिया के लिए पूरी दुनिया के बजाय नीले क्षेत्र की सीमा का उपयोग करना चाहता हूं।

नमूना छवि


क्या आप एक नमूना पोस्ट कर सकते हैं?
हारून

"मैं इस रेखापुंज के लिए अशक्त पंक्तियों और स्तंभों को हटाना चाहूंगा।" इसका वास्तव में क्या मतलब है? मुझे समझ नहीं आ रहा है कि वांछित अंतिम परिणाम क्या है।
ब्लाह २३ bl

"न्यूनतम बाउंडिंग सीमा" तक क्या आप आयताकार सीमा या एक बहुभुज पदचिह्न की तलाश कर रहे हैं जो डेटा के साथ छवि के क्षेत्र का प्रतिनिधित्व करता है?
ब्लाह २३ bl

1
@Tomek, ओ पी करने के लिए देख रहा है खोजने के हद तक, नहीं इसे मैन्युअल रूप से बनाना होगा।
blah238

1
अगर सचमुच कुछ भी उचित खेल है, तो कुछ सॉफ्टवेयर में ऐसा करने के लिए अंतर्निहित कमांड हैं; उदाहरण के लिए देखें ।wolfram.com/ mathematica/ref/ImageCrop.html।
whuber

जवाबों:


6

यदि मुझे यह प्रश्न ठीक से समझ में आ गया है कि ऐसा लगता है कि आप उन मानों के न्यूनतम बाउंडिंग बॉक्स को जानना चाहते हैं जो अशक्त नहीं हैं। तब तक आप रेखापुंज को बहुभुज में बदल सकते हैं, उन बहुभुजों का चयन करें जिनमें आप रुचि रखते हैं और फिर उन्हें रेखापुंज में परिवर्तित कर सकते हैं। फिर आप उन गुणों मानों को देख सकते हैं जो आपको मिनियम बाउंडिंग बॉक्स देना चाहिए।


1
सभी ने बताया कि यह शायद सबसे अच्छा तरीका है जिसे आर्कजीएस रेखापुंज प्रसंस्करण वर्कफ़्लो की सीमाएं दी गई हैं।
blah238

मैंने ठीक यही किया। क्या कोई स्वचालित तरीका है? मुझे लगता है कि बहुभुज एल्गोरिथ्म के रेखापुंज में रेखापुंज के न्यूनतम बाउंडिंग बॉक्स को निकालने के लिए एक कदम है।
देखा

क्या आप एक अजगर समाधान के बाद हैं?
डेंजरो

8

चाल डेटा की सीमा की गणना करने के लिए है जिसमें मूल्य हैं। शायद इनको प्राप्त करने का सबसे तेज़, सबसे स्वाभाविक और सबसे सामान्य तरीका है: जोनल समरी के साथ: ज़ोन के लिए सभी गैर-नोडाटा कोशिकाओं का उपयोग करके, एक्स और वाई निर्देशांक वाले ज़ोनल मिनट और अधिकतम ग्रिड पूरी सीमा तक प्रदान करेंगे।

ईएसआरआई इन गणनाओं को करने के तरीकों में बदलाव करता रहता है; उदाहरण के लिए, कॉर्डिनेट ग्रिड के लिए बिल्ट-इन एक्सप्रेशंस को आर्कगिस 8 के साथ छोड़ दिया गया था और वापस नहीं आया था। बस मज़े के लिए, यहाँ तेज़, सरल गणनाओं का एक सेट है जो काम करेगा चाहे कोई भी हो।

  1. ग्रिड को एकल ज़ोन में परिवर्तित करके, इसे अपने आप से, जैसे कि अंदर है, बदल दें

    "माय ग्रिड" == "माय ग्रिड"

  2. मान 1 के साथ एक स्थिर ग्रिड को प्रवाह-संचय करके एक कॉलम इंडेक्स ग्रिड बनाएं। (इंडेक्स 0. के साथ शुरू होगा।) यदि वांछित है, तो इसे कोशिकाओं द्वारा गुणा करें और एक्स-समन्वय ग्रिड प्राप्त करने के लिए मूल के एक्स-समन्वय को जोड़ें " एक्स ”(नीचे दिखाया गया है)।

  3. इसी तरह, मूल्य 64 के साथ एक स्थिर ग्रिड को प्रवाह-संचित करके एक पंक्ति सूचकांक ग्रिड ( और फिर एक वाई-समन्वित ग्रिड "Y") बनाएं ।

  4. ज़ोन का न्यूनतम और "X" और "Y" की गणना करने के लिए चरण (1) से ज़ोन ग्रिड का उपयोग करें : अब आपके पास वांछित सीमा है।

अंतिम छवि

(हद तक, जैसा कि आंचलिक आंकड़ों की दो सारणियों में दिखाया गया है, इस चित्र में एक आयताकार रूपरेखा द्वारा दर्शाया गया है। ग्रिड "I" चरण 1 (1) में प्राप्त क्षेत्र ग्रिड है।)

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


8

यहां आर्किटिस 10.1+ के लिए @ वॉटर्स विधि का एक संस्करण एक अजगर टूलबॉक्स (.pyt) के रूप में है।

import arcpy

class Toolbox(object):
    def __init__(self):
        """Define the toolbox (the name of the toolbox is the name of the
        .pyt file)."""
        self.label = "Raster Toolbox"
        self.alias = ""

        # List of tool classes associated with this toolbox
        self.tools = [ClipNoData]


class ClipNoData(object):
    def __init__(self):
        """Clip raster extent to the data that have values"""
        self.label = "Clip NoData"
        self.description = "Clip raster extent to the data that have values. "
        self.description += "Method by Bill Huber - https://gis.stackexchange.com/a/55150/2856"

        self.canRunInBackground = False

    def getParameterInfo(self):
        """Define parameter definitions"""
        params = []

        # First parameter
        params+=[arcpy.Parameter(
            displayName="Input Raster",
            name="in_raster",
            datatype='GPRasterLayer',
            parameterType="Required",
            direction="Input")
        ]

        # Second parameter
        params+=[arcpy.Parameter(
            displayName="Output Raster",
            name="out_raster",
            datatype="DERasterDataset",
            parameterType="Required",
            direction="Output")
        ]

        return params

    def isLicensed(self):
        """Set whether tool is licensed to execute."""
        return arcpy.CheckExtension('spatial')==u'Available'

    def execute(self, parameters, messages):
        """See https://gis.stackexchange.com/a/55150/2856
           ##Code comments paraphrased from @whubers GIS StackExchange answer
        """
        try:
            #Setup
            arcpy.CheckOutExtension('spatial')
            from arcpy.sa import *
            in_raster = parameters[0].valueAsText
            out_raster = parameters[1].valueAsText

            dsc=arcpy.Describe(in_raster)
            xmin=dsc.extent.XMin
            ymin=dsc.extent.YMin
            mx=dsc.meanCellWidth
            my=dsc.meanCellHeight
            arcpy.env.extent=in_raster
            arcpy.env.cellSize=in_raster
            arcpy.AddMessage(out_raster)

            ## 1. Convert the grid into a single zone by equating it with itself
            arcpy.AddMessage(r'1. Convert the grid into a single zone by equating it with itself...')
            zones = Raster(in_raster) == Raster(in_raster)

            ## 2. Create a column index grid by flow-accumulating a constant grid
            ##    with value 1. (The indexes will start with 0.) Multiply this by
            ##    the cellsize and add the x-coordinate of the origin to obtain
            ##    an x-coordinate grid.
            arcpy.AddMessage(r'Create a constant grid...')
            const = CreateConstantRaster(1)

            arcpy.AddMessage(r'2. Create an x-coordinate grid...')
            xmap = (FlowAccumulation(const)) * mx + xmin

            ## 3. Similarly, create a y-coordinate grid by flow-accumulating a
            ##    constant grid with value 64.
            arcpy.AddMessage(r'3. Create a y-coordinate grid...')
            ymap = (FlowAccumulation(const * 64)) * my + ymin

            ## 4. Use the zone grid from step (1) to compute the zonal min and
            ##    max of "X" and "Y"
            arcpy.AddMessage(r'4. Use the zone grid from step (1) to compute the zonal min and max of "X" and "Y"...')

            xminmax=ZonalStatisticsAsTable(zones, "value", xmap,r"IN_MEMORY\xrange", "NODATA", "MIN_MAX")
            xmin,xmax=arcpy.da.SearchCursor(r"IN_MEMORY\xrange", ["MIN","MAX"]).next()

            yminmax=ZonalStatisticsAsTable(zones, "value", ymap,r"IN_MEMORY\yrange", "NODATA", "MIN_MAX")
            ymin,ymax=arcpy.da.SearchCursor(r"IN_MEMORY\yrange", ["MIN","MAX"]).next()

            arcpy.Delete_management(r"IN_MEMORY\xrange")
            arcpy.Delete_management(r"IN_MEMORY\yrange")

            # Write out the reduced raster
            arcpy.env.extent = arcpy.Extent(xmin,ymin,xmax+mx,ymax+my)
            output = Raster(in_raster) * 1
            output.save(out_raster)

        except:raise
        finally:arcpy.CheckInExtension('spatial')

बहुत अच्छा ल्यूक। स्व निहित, रन करने योग्य, उपयोग करता है in_memory, और बूट करने के लिए अच्छी तरह से टिप्पणी की। मुझे इसे काम करने के लिए बैकग्राउंड प्रोसेसिंग ( जियोप्रोसेसिंग> विकल्प> ... ) को बंद करना पड़ा ।
मैट विल्की

1
मैंने स्क्रिप्ट को अपडेट किया है और canRunInBackground = False सेट किया है। मैं ध्यान दूंगा कि यह कार्यक्षेत्र / स्क्रैचवर्कस्पेस वातावरण को एक स्थानीय फ़ोल्डर (एफजीडीबी नहीं) में बदलने के लायक है जैसा कि मैंने पाया जब मैंने उन्हें डिफ़ॉल्ट के रूप में छोड़ दिया (यानी <नेटवर्क उपयोगकर्ता प्रोफ़ाइल> \ Default.gdb) स्क्रिप्ट को 9min लिया !!! 250x250 सेल ग्रिड पर चलाने के लिए। एक स्थानीय FGDB में बदलने से यह 9sec और एक स्थानीय फ़ोल्डर 1-2sec तक ले गया ...
user2856

स्थानीय फ़ोल्डरों के बारे में अच्छी बात है, और त्वरित पृष्ठभूमि सुधार के लिए धन्यवाद (मैं इसे पास करने वाले सभी लोगों के लिए निर्देश लिखने से बेहतर हूं)। यह बिटकॉइन / जीथब / जीकोड / आदि पर फेंकने लायक हो सकता है।
मैट विल्की

+1 इस योगदान के लिए धन्यवाद, ल्यूक! मैं आपके जवाब में बचे (बल्कि बड़े) अंतर को भरने के लिए आपकी सराहना करता हूं।
whuber

4

मैंने एक गदल और सुन्न आधारित समाधान तैयार किया है। यह रेखापुंज मैट्रिक्स को पंक्तियों और स्तंभों में तोड़ता है और किसी भी खाली पंक्ति / स्तंभ को गिराता है। इस कार्यान्वयन में "खाली" 1 से कम कुछ भी नहीं है, और केवल एकल बैंड रैस्टर के लिए जिम्मेदार है।

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

व्यापार भागों (बाहर fleshing की जरूरत है, के रूप में काम नहीं करेगा):

    #read raster into a numpy array
    data = np.array(gdal.Open(src_raster).ReadAsArray())
    #scan for data
    non_empty_columns = np.where(data.max(axis=0)>0)[0]
    non_empty_rows = np.where(data.max(axis=1)>0)[0]
        # assumes data is any value greater than zero
    crop_box = (min(non_empty_rows), max(non_empty_rows),
        min(non_empty_columns), max(non_empty_columns))

    # retrieve source geo reference info
    georef = raster.GetGeoTransform()
    xmin, ymax = georef[0], georef[3]
    xcell, ycell = georef[1], georef[5]

    # Calculate cropped geo referencing
    new_xmin = xmin + (xcell * crop_box[0]) + xcell
    new_ymax = ymax + (ycell * crop_box[2]) - ycell
    cropped_transform = new_xmin, xcell, 0.0, new_ymax, 0.0, ycell

    # crop
    new_data = data[crop_box[0]:crop_box[1]+1, crop_box[2]:crop_box[3]+1]

    # write to disk
    band = out_raster.GetRasterBand(1)
    band.WriteArray(new_data)
    band.FlushCache()
    out_raster = None

एक पूरी स्क्रिप्ट में:

import os
import sys
import numpy as np
from osgeo import gdal

if len(sys.argv) < 2:
    print '\n{} [infile] [outfile]'.format(os.path.basename(sys.argv[0]))
    sys.exit(1)

src_raster = sys.argv[1]
out_raster = sys.argv[2]

def main(src_raster):
    raster = gdal.Open(src_raster)

    # Read georeferencing, oriented from top-left
    # ref:GDAL Tutorial, Getting Dataset Information
    georef = raster.GetGeoTransform()
    print '\nSource raster (geo units):'
    xmin, ymax = georef[0], georef[3]
    xcell, ycell = georef[1], georef[5]
    cols, rows = raster.RasterYSize, raster.RasterXSize
    print '  Origin (top left): {:10}, {:10}'.format(xmin, ymax)
    print '  Pixel size (x,-y): {:10}, {:10}'.format(xcell, ycell)
    print '  Columns, rows    : {:10}, {:10}'.format(cols, rows)

    # Transfer to numpy and scan for data
    # oriented from bottom-left
    data = np.array(raster.ReadAsArray())
    non_empty_columns = np.where(data.max(axis=0)>0)[0]
    non_empty_rows = np.where(data.max(axis=1)>0)[0]
    crop_box = (min(non_empty_rows), max(non_empty_rows),
        min(non_empty_columns), max(non_empty_columns))

    # Calculate cropped geo referencing
    new_xmin = xmin + (xcell * crop_box[0]) + xcell
    new_ymax = ymax + (ycell * crop_box[2]) - ycell
    cropped_transform = new_xmin, xcell, 0.0, new_ymax, 0.0, ycell

    # crop
    new_data = data[crop_box[0]:crop_box[1]+1, crop_box[2]:crop_box[3]+1]

    new_rows, new_cols = new_data.shape # note: inverted relative to geo units
    #print cropped_transform

    print '\nCrop box (pixel units):', crop_box
    print '  Stripped columns : {:10}'.format(cols - new_cols)
    print '  Stripped rows    : {:10}'.format(rows - new_rows)

    print '\nCropped raster (geo units):'
    print '  Origin (top left): {:10}, {:10}'.format(new_xmin, new_ymax)
    print '  Columns, rows    : {:10}, {:10}'.format(new_cols, new_rows)

    raster = None
    return new_data, cropped_transform


def write_raster(template, array, transform, filename):
    '''Create a new raster from an array.

        template = raster dataset to copy projection info from
        array = numpy array of a raster
        transform = geo referencing (x,y origin and pixel dimensions)
        filename = path to output image (will be overwritten)
    '''
    template = gdal.Open(template)
    driver = template.GetDriver()
    rows,cols = array.shape
    out_raster = driver.Create(filename, cols, rows, gdal.GDT_Byte)
    out_raster.SetGeoTransform(transform)
    out_raster.SetProjection(template.GetProjection())
    band = out_raster.GetRasterBand(1)
    band.WriteArray(array)
    band.FlushCache()
    out_raster = None
    template = None

if __name__ == '__main__':
    cropped_raster, cropped_transform = main(src_raster)
    write_raster(src_raster, cropped_raster, cropped_transform, out_raster)

स्क्रिप्ट में है मेरी कोड गुप्त कोष लिंक थोड़ा चारों ओर 404 शिकार हो जाता है, Github पर; ये फ़ोल्डर्स कुछ पुनर्गठन के लिए परिपक्व हैं।


1
यह वास्तव में बड़े डेटासेट के लिए काम करता है। मुझे MemoryError Source raster (geo units): Origin (top left): 2519950.0001220703, 5520150.00012207 Pixel size (x,-y): 100.0, -100.0 Columns, rows : 42000, 43200 Traceback (most recent call last): File "D:/11202067_COACCH/local_checkout/crop_raster.py", line 72, in <module> cropped_raster, cropped_transform = main(src_raster) File "D:/11202067_COACCH/local_checkout/crop_raster.py", line 22, in main data = np.array(raster.ReadAsArray()) MemoryError
user32882

2

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

अपने सर्वोत्तम प्रयासों के बावजूद, और प्रोग्रामिंग का सहारा लिए बिना, मुझे छवि के आपके वांछित उप-भाग की सीमा (बिना रेखापुंज-वेक्टर रूपांतरण के जो बिना कम्प्यूटेशनल रूप से व्यर्थ है) पाने का कोई रास्ता नहीं मिल सका।

इसके बजाय, मैंने GIMP का उपयोग रंग उपकरण द्वारा चयन के नीले क्षेत्र का चयन करने के लिए किया और फिर चयन को उल्टा कर दिया, बाकी पिक्सल को हटाने के लिए डिलीट को हिट किया, चयन को फिर से उल्टा कर दिया, चयन के लिए छवि को क्रॉप कर दिया, और अंत में इसे वापस निर्यात करने के लिए पीएनजी। GIMP ने इसे 1-बिट डेप्थ इमेज के रूप में सेव किया। परिणाम नीचे है:

उत्पादन

बेशक, क्योंकि आपकी नमूना छवि में स्थानिक संदर्भ घटक का अभाव था, और GIMP स्थानिक रूप से जागरूक नहीं है, आउटपुट छवि आपके नमूना इनपुट के रूप में उपयोगी है। एक स्थानिक विश्लेषण में इसका उपयोग करने के लिए आपको इसे जियोजित करने की आवश्यकता होगी ।


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

@ जब मैंने आपका समाधान कहीं और देखा, लेकिन फिर भी मुझे यकीन नहीं हुआ कि मैं आपके तरीके को कैसे लागू कर सकता हूं। क्या आप मुझे इसका कुछ और विवरण दिखा सकते हैं?
देखा

@ इस साइट की एक त्वरित खोज gis.stackexchange.com/a/13467 पर विधि का एक खाता ढूंढती है
whuber

1

यहां SAGA GIS का उपयोग करने की एक संभावना है: http://permalink.gmane.org/gmane.comp.gis.gdal.devel/33021

सागा जीआईएस में "क्रॉप टू डेटा" मॉड्यूल (ग्रिड टूल्स मॉड्यूल लाइब्रेरी में) है, जो कार्य करता है।

लेकिन इसके लिए आपको GDAL आयात मॉड्यूल के साथ अपना जियोटीफ़ आयात करना होगा, इसे SAGA में संसाधित करना होगा, और अंत में इसे GDAL निर्यात मॉड्यूल के साथ फिर से जियोटीफ़ के रूप में निर्यात करना होगा।

केवल ArcGIS जीपी उपकरण का उपयोग कर एक और संभावना का उपयोग कर अपने रेखापुंज से एक टिन बनाना है, जिसमें टिन के लिए रेखापुंज , का उपयोग करते हुए अपनी सीमा की गणना टिन डोमेन , और क्लिप सीमा (या इसके लिफाफा का उपयोग करके अपने रेखापुंज बहुभुज को फ़ीचर लिफाफा )।

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