जीडीएएल और पायथन: विशिष्ट मूल्य वाले सभी कोशिकाओं के लिए निर्देशांक कैसे प्राप्त करें?


12

मुझे एक आर्क / जानकारी बाइनरी ग्रिड --- विशेष रूप से, एक आर्किस प्रवाह संचय रेखापुंज --- मिला है और मैं सभी कोशिकाओं को एक विशिष्ट मूल्य (या मूल्यों की श्रेणी में) पहचानना चाहूंगा। अंत में, मैं इन कोशिकाओं का प्रतिनिधित्व करने वाले बिंदुओं का एक आकार-प्रकार चाहूंगा।

मैं hdr.adf खोलने के लिए QGIS का उपयोग कर सकता हूं और यह परिणाम प्राप्त कर सकता हूं, वर्कफ़्लो है:

  • QGIS> रेखापुंज मेनू> रेखापुंज कैलकुलेटर (लक्ष्य मान के साथ सभी बिंदुओं को चिह्नित करें)
  • QGIS> रेखापुंज मेनू> बहुभुज
  • QGIS> वेक्टर मेनू> ज्यामिति सबमेनू> बहुभुज सेंट्रोइड्स
  • अवांछित पॉली सेंट्रोइड्स को हटाने के लिए सेंट्रोइड्स को संपादित करें (उन = 0)

यह दृष्टिकोण "काम करता है", लेकिन यह मुझे अपील नहीं करता है क्योंकि यह 2 फाइलें बनाता है जिन्हें मुझे हटाना है, फिर मुझे अवांछित रिकॉर्ड (सेंट) को सेंट्रोफाइल के आकार के निशान से निकालना होगा (अर्थात उन = 0)।

एक मौजूदा प्रश्न इस विषय पर आता है, लेकिन यह ArcGIS / ArcPy के लिए सिलवाया गया है, और मैं FOSS स्पेस में रहना चाहूंगा।

क्या किसी के पास GDAL / Python रेसिपी / स्क्रिप्ट मौजूद है जो किसी रैस्टर के सेल वैल्यू से पूछताछ करती है, और जब टारगेट वैल्यू --- या टारगेट रेंज में एक वैल्यू --- पाया जाता है, तो एक रिकॉर्ड को एक शेपफाइल में जोड़ा जाता है? यह न केवल UI इंटरैक्शन से बचता है, बल्कि यह एक एकल पास में एक साफ परिणाम पैदा करेगा।

मैंने क्रिस गेरार्ड की प्रस्तुतियों में से एक के खिलाफ काम करके इस पर एक शॉट लिया , लेकिन रेखापुंज का काम मेरे व्हीलहाउस में नहीं है और मैं अपने कमजोर कोड के साथ सवाल को टटोलना नहीं चाहता।

किसी को भी सटीक डाटासेट के साथ खेलने के लिए चाहिए, मैं एक .zip के रूप में यहाँ डाल दिया


[संपादित करें नोट्स] पोस्टीरिटी के लिए इसे पीछे छोड़ते हुए। Om_henners के साथ टिप्पणी विनिमय देखें। मूल रूप से x / y (पंक्ति / स्तंभ) मान फ़्लिप किए गए थे। मूल उत्तर में यह पंक्ति थी:

(y_index, x_index) = np.nonzero(a == 1000)

उलटा, इस तरह:

(x_index, y_index) = np.nonzero(a == 1000)

जब मुझे पहली बार स्क्रीनशॉट में दर्शाए गए मुद्दे का सामना करना पड़ा, तो मुझे आश्चर्य हुआ कि क्या मैंने ज्यामिति को गलत तरीके से लागू किया है, और मैंने इस पंक्ति में x / y निर्देशांक मानों को फ़्लिप करके प्रयोग किया है:

point.SetPoint(0, x, y)

..जैसा..

point.SetPoint(0, y, x)

हालांकि वह काम नहीं किया। और मैंने om_henners के Numpy अभिव्यक्ति में मानों को फ़्लिप करने की कोशिश करने के बारे में नहीं सोचा था, यह गलत तरीके से विश्वास करते हुए कि उन्हें या तो रेखा पर फ़्लिप करना बराबर था। मैं असली मुद्दे से संबंधित है लगता है x_sizeऔर y_sizeमूल्यों में क्रमश: 30और -30, जो जब पंक्ति और स्तंभ सूचकांक कोशिकाओं के लिए calculate बिंदु निर्देशांक के लिए उपयोग किया जाता है लागू होते हैं।

[मूल संपादन]

@om_henners, मैं (OGR का उपयोग कर बिंदु शेपफ़ाइलें बनाने के लिए एक जोड़े को recipies के साथ अपने समाधान कोशिश कर रहा हूँ, संगीत कार्यक्रम में invisibleroads.com , क्रिस Garrard ), लेकिन मैं एक मुद्दा जहां अंक के रूप में अगर एक लाइन गुजर में दिखाई दिखाई दे रहे हैं हो रही है 315/135-डिग्री के माध्यम से।

हल्के नीले बिंदु : मेरे QGIS दृष्टिकोण द्वारा निर्मित , ऊपर

बैंगनी बिंदु : नीचे GDAL / OGR py कोड द्वारा बनाया गया है

यहाँ छवि विवरण दर्ज करें


[हल किया]

यह पायथन कोड @om_henners द्वारा प्रस्तावित पूर्ण समाधान को लागू करता है। मैंने इसका परीक्षण किया है और यह काम करता है। धन्यवाद दोस्त!


from osgeo import gdal
import numpy as np
import osgeo.ogr
import osgeo.osr

path = "D:/GIS/greeneCty/Greene_DEM/GreeneDEM30m/flowacc_gree/hdr.adf"
print "\nOpening: " + path + "\n"

r = gdal.Open(path)
band = r.GetRasterBand(1)

(upper_left_x, x_size, x_rotation, upper_left_y, y_rotation, y_size) = r.GetGeoTransform()

a = band.ReadAsArray().astype(np.float)

# This evaluation makes x/y arrays for all cell values in a range.
# I knew how many points I should get for ==1000 and wanted to test it.
(y_index, x_index) = np.nonzero((a > 999) & (a < 1001))

# This evaluation makes x/y arrays for all cells having the fixed value, 1000.
#(y_index, x_index) = np.nonzero(a == 1000)

# DEBUG: take a look at the arrays..
#print repr((y_index, x_index))

# Init the shapefile stuff..
srs = osgeo.osr.SpatialReference()
#srs.ImportFromProj4('+proj=utm +zone=15 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs')
srs.ImportFromWkt(r.GetProjection())

driver = osgeo.ogr.GetDriverByName('ESRI Shapefile')
shapeData = driver.CreateDataSource('D:/GIS/01_tutorials/flow_acc/ogr_pts.shp')

layer = shapeData.CreateLayer('ogr_pts', srs, osgeo.ogr.wkbPoint)
layerDefinition = layer.GetLayerDefn()

# Iterate over the Numpy points..
i = 0
for x_coord in x_index:
    x = x_index[i] * x_size + upper_left_x + (x_size / 2) #add half the cell size
    y = y_index[i] * y_size + upper_left_y + (y_size / 2) #to centre the point

    # DEBUG: take a look at the coords..
    #print "Coords: " + str(x) + ", " + str(y)

    point = osgeo.ogr.Geometry(osgeo.ogr.wkbPoint)
    point.SetPoint(0, x, y)

    feature = osgeo.ogr.Feature(layerDefinition)
    feature.SetGeometry(point)
    feature.SetFID(i)

    layer.CreateFeature(feature)

    i += 1

shapeData.Destroy()

print "done! " + str(i) + " points found!"

1
अपने कोड के लिए त्वरित टिप: आप अपने आकार के प्रक्षेपण के साथ रेखापुंज प्रक्षेपण का उपयोग कर सकते हैं srs.ImportFromWkt(r.GetProjection())(इसके बजाय एक ज्ञात प्रोज स्ट्रिंग से प्रक्षेपण बनाने के लिए)।
om_henners 8

आपका कोड वह सब कुछ करता है, जिसे मैं इसके अलावा देख रहा हूं, इसमें रैस्टर सेल वैल्यू शामिल नहीं है, क्योंकि आपने अपने संख्यात्मक फ़िल्टर को केवल मान = 1000 शामिल करने के लिए लिखा है। क्या आप मुझे रैस्टर सेल मान शामिल करने के लिए सही दिशा में इंगित कर सकते हैं उत्पादन? धन्यवाद!
ब्रेंट एडवर्ड्स

जवाबों:


19

GDAL में आप रेखापुंज को एक सुस्पष्ट सरणी के रूप में आयात कर सकते हैं।

from osgeo import gdal
import numpy as np

r = gdal.Open("path/to/raster")
band = r.GetRasterBand(1) #bands start at one
a = band.ReadAsArray().astype(np.float)

फिर एक खंभे का प्रयोग करना एक साधारण बात है जो एक बूलियन एक्सप्रेशन से मेल खाते सरणी के अनुक्रमित को प्राप्त करने के लिए है:

(y_index, x_index) = np.nonzero(a > threshold)
#To demonstate this compare a.shape to band.XSize and band.YSize

रैस्टर जियोट्रांसफॉर्म से हम ऊपरी बाएँ x और y निर्देशांक और सेल आकार जैसी जानकारी प्राप्त कर सकते हैं।

(upper_left_x, x_size, x_rotation, upper_left_y, y_rotation, y_size) = r.GetGeoTransform()

ऊपरी बाएं सेल से मेल खाती है a[0, 0]। वाई आकार हमेशा नकारात्मक होगा, इसलिए एक्स और वाई सूचकांकों का उपयोग करके आप अनुक्रमित के आधार पर प्रत्येक सेल के निर्देशांक की गणना कर सकते हैं।

x_coords = x_index * x_size + upper_left_x + (x_size / 2) #add half the cell size
y_coords = y_index * y_size + upper_left_y + (y_size / 2) #to centre the point

यहाँ से OGR का उपयोग करके एक आकृति बनाने के लिए एक सरल पर्याप्त मामला है। कुछ नमूना कोड के लिए यह प्रश्न देखें कि बिंदु जानकारी के साथ नया डेटासेट कैसे बनाया जाए।


हे फेला, मैं इसे लागू करने के लिए एक छोटा सा मुद्दा रहा हूँ। मैंने उस कोड को शामिल करने के लिए प्रश्न को अपडेट किया जो मैं उपयोग कर रहा हूं और जो मुझे मिल रहा है उसका एक पेचकश। मूल रूप से .py कोड QGIS दृष्टिकोण उत्पन्न कर रहा है की एक दर्पण छवि (बिंदु प्लेसमेंट) बना रहा है। मेरे लागू होने के बिंदु रेखापुंज सीमा के बाहर आते हैं, इसलिए मुद्दे को मेरे कोड के साथ होना चाहिए। : = मुझे उम्मीद है कि आप कुछ प्रकाश डाल सकते हैं। धन्यवाद!
एलोबिस 15

इस बारे में क्षमा करें - पूरी तरह से मेरा बुरा। जब आप GDAL में एक रेखापुंज आयात करते हैं तो पंक्तियाँ y दिशा होती हैं और स्तंभ x दिशा होते हैं। मैंने ऊपर कोड को अपडेट किया है, लेकिन ट्रिक के साथ इंडेक्स प्राप्त करना है(y_index, x_index) = np.nonzero(a > threshold)
om_henners

1
इसके अलावा, बस मामले में, सेल में बिंदु को केंद्र करने के लिए दोनों दिशाओं में निर्देशांक में आधे सेल आकार को जोड़ने पर ध्यान दें।
om_henners

हाँ, यह मुद्दा था। जब मैंने पहली बार उस बग का सामना किया (जैसा कि स्क्रीन ग्रैब में दिखाया गया है), तो मुझे आश्चर्य हुआ कि क्या मैंने पॉइंट ज्योमेट्री को गलत तरीके से लागू किया है, इसलिए मैंने x / y को y / x के रूप में फ़्लिप करने की कोशिश की जब मैंने बनाया .shp--- केवल इतना ही नहीं काम, और न ही यह कहीं भी करीब था। जब से सौ-हज़ार में x मान है, और y लाखों में है, तो मैं हैरान नहीं था, इसलिए इसने मुझे बहुत उलझन में छोड़ दिया। मैं Numpy अभिव्यक्ति पर उन्हें वापस flipping की कोशिश करने के लिए नहीं सोचा था। आपकी मदद के लिए बहुत बहुत धन्यवाद, यह अच्छा है। बिल्कुल वही जो मैं चाहता था। :)
elrobis

4

क्यूजीआईएस में सेक्सेंट टूल टूलबॉक्स का उपयोग क्यों नहीं किया जाता है ? यह आर्कगिस के लिए मॉडल बिल्डर की तरह है। इस तरह, आप ऑपरेशन को चेन कर सकते हैं और इसे एक ऑपरेशन के रूप में मान सकते हैं। यदि मैं गलत नहीं हूँ, तो आप मध्यवर्ती फ़ाइलों को हटाने और अवांछित रिकॉर्ड को हटा सकते हैं।


1

यह डेटा को पोस्टगिस (रेखापुंज समर्थन के साथ) में आयात करने और वहां कार्यों का उपयोग करने में मददगार हो सकता है। इस ट्यूटोरियल में आपके लिए आवश्यक तत्व हो सकते हैं।

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