Psycopg2 का उपयोग करके पोस्टगिस से अजगर में रैस्टर डेटा डाउनलोड करना


13

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

क्या किसी को पता है कि इस स्ट्रिंग को कैसे लेना है और एक सुपीरियर सरणी में बदलना है?

मैंने रैस्टर को डाउनलोड करने के लिए अन्य विकल्पों का पता लगाया जैसे कि st_astiff का उपयोग करें और हेक्स फ़ाइल डाउनलोड करने के लिए एन्कोड करें और xxd का उपयोग करें लेकिन यह काम नहीं किया। मैं त्रुटि 'rt_raster_to_gdal: आउटपुट GDAL ड्राइवर लोड नहीं कर सका' प्राप्त करता रहता हूं और मेरे पास ड्राइवर को चालू करने में सक्षम होने के लिए पर्यावरण चर सेट करने की अनुमति नहीं है।

टीएल, डीआर: रेखापुंज डेटा को एक संख्यात्मक सरणी (अजगर का उपयोग करके) में आयात करना चाहते हैं।

जवाबों:


14

rt_raster_to_gdal: आउटपुट GDAL ड्राइवर लोड नहीं कर सका

ST_AsTIFF के साथ पहली त्रुटि के लिए , आपको अपने GDAL ड्राइवरों को सक्षम करने की आवश्यकता है, जो डिफ़ॉल्ट रूप से PostGr 2.1 के लिए सक्षम नहीं हैं। ऐसा करने के तरीकों पर मैनुअल देखें । उदाहरण के लिए, मेरे पास विंडोज कंप्यूटर पर एक पर्यावरण चर है:

POSTGIS_GDAL_ENABLED_DRIVERS=GTiff PNG JPEG GIF XYZ DTED USGSDEM AAIGrid

जिसकी पुष्टि PostGIS के साथ की जा सकती है:

SELECT short_name, long_name
FROM ST_GDALDrivers();

PostGIS to Numpy

आप GDAL को Numpy सरणी में पढ़ने के लिए किसी वर्चुअल मेमोरी GeoTIFF फ़ाइल में आउटपुट निर्यात कर सकते हैं। GDAL में उपयोग की जाने वाली वर्चुअल फ़ाइलों के संकेत के लिए, इस ब्लॉग पोस्ट को देखें ।

import os
import psycopg2
from osgeo import gdal

# Adjust this to connect to a PostGIS database
conn = psycopg2.connect(...)
curs = conn.cursor()

# Make a dummy table with raster data
curs.execute("""\
    SELECT ST_AsRaster(ST_Buffer(ST_Point(1, 5), 10), 10, 10, '8BUI', 1) AS rast
    INTO TEMP mytable;
""")

# Use a virtual memory file, which is named like this
vsipath = '/vsimem/from_postgis'

# Download raster data into Python as GeoTIFF, and make a virtual file for GDAL
curs.execute("SELECT ST_AsGDALRaster(rast, 'GTiff') FROM mytable;")
gdal.FileFromMemBuffer(vsipath, bytes(curs.fetchone()[0]))

# Read first band of raster with GDAL
ds = gdal.Open(vsipath)
band = ds.GetRasterBand(1)
arr = band.ReadAsArray()

# Close and clean up virtual memory file
ds = band = None
gdal.Unlink(vsipath)

print(arr)  # this is a 2D numpy array

एक विचित्र बफ़र्ड पॉइंट दिखाता है।

[[0 0 0 1 1 1 1 0 0 0]
 [0 1 1 1 1 1 1 1 1 0]
 [0 1 1 1 1 1 1 1 1 0]
 [1 1 1 1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1 1 1 1]
 [0 1 1 1 1 1 1 1 1 0]
 [0 1 1 1 1 1 1 1 1 0]
 [0 0 0 1 1 1 1 0 0 0]]

ध्यान दें कि मैंने उदाहरण में 'GTiff' प्रारूप का उपयोग किया है, लेकिन अन्य प्रारूप बेहतर अनुकूल हो सकते हैं। उदाहरण के लिए, यदि आपके पास एक बड़ा रेखापुंज है जिसे एक धीमे इंटरनेट कनेक्शन पर स्थानांतरित करने की आवश्यकता है, तो इसे संपीड़ित करने के लिए 'PNG' का उपयोग करके देखें।


यह बहुत मददगार है।
जॉन पॉवेल

बहुत मददगार। धन्यवाद! मैं अभी भी इस मुद्दे पर चल रहा हूं कि: ERROR: rt_raster_to_gdal: आउटपुट GDAL ड्राइवर लोड नहीं कर सका, लेकिन मुझे लगता है कि मेरे पास इसके लिए एक वर्कअराउंड है। एक बार फिर धन्यवाद!
मयंक अग्रवाल

@MayankAgarwal ने rt_raster_to_gdal त्रुटि के लिए अद्यतन उत्तर दिया।
माइक टी

6

मुझे लगता है कि सवाल यह था कि क्या आप पोस्टगिस रेखापुंज से पढ़ सकते हैं बिना गाल्ड ड्राइवरों को सक्षम किए। सभी चीजों के रूप में अजगर, आप कर सकते हैं!

सुनिश्चित करें कि आप WKBinary के रूप में अपने रेखापुंज परिणाम का चयन करें:

St_AsBinary (rast) चुनें ...

एक अजगर छवि प्रारूप में WKBinary डिक्रिप्ट करने के लिए नीचे स्क्रिप्ट का उपयोग करें। मैं opencv को पसंद करता हूं, क्योंकि यह मनमाने ढंग से इमेज बैंड की संख्या को संभालता है, लेकिन 1 या 3 बैंड अधिक सामान्य होने पर पीआईएल / कम का उपयोग कर सकते हैं।

मैं केवल अब के लिए बाइट इमेजरी संभालता हूं, लेकिन यह अन्य डेटाटाइप्स के विस्तार के लिए अपेक्षाकृत तुच्छ है।

आशा है कि यह उपयोगी है।

आयात संरचना
आयात एनपीपी के रूप में सुन्न
आयात cv2

# WKB हेडर को डिक्रिप्ट करने का कार्य
def wkbHeader (कच्चा):
    # देखें http://trac.osgeo.org/postgis/browser/trunk/raster/doc/RFC2-WellKnownBinaryFormat

    हैडर = {}

    शीर्ष लेख ['अंत्येष्टि'] = struct.unpack ('बी', कच्चा [0]) [0]
    शीर्ष लेख ['संस्करण'] = struct.unpack ('एच', कच्चा [1: 3]) [0]
    हेडर ['nbands'] = struct.unpack ('एच', कच्चा [3: 5]) [0]
    हेडर ['स्केलएक्स'] = स्ट्रक्चर.ऑनपैक ('डी', कच्चा [5:13]) [0]
    हेडर ['स्केल'] = स्ट्रक्च.न्यूपैक ('डी', कच्चा [13:21]) [0]
    हैडर ['ipX'] = struct.unpack ('d', कच्चा [21:29]) [0]
    हेडर ['ipY'] = struct.unpack ('d', कच्चा [29:37]) [0]
    शीर्ष लेख ['skewX'] = struct.unpack ('d', कच्चा [37:45]) [0]
    शीर्षक ['skewY'] = struct.unpack ('d', कच्चा [45:53]) [0]
    हेडर ['श्रीड'] = स्ट्रक्च.न्यूपैक ('आई', रॉ [53:57]) [0]
    हेडर ['चौड़ाई'] = स्ट्रक्चर.पंक्चर ('एच', कच्चा [57:59]) [0]
    शीर्ष लेख ['ऊँचाई'] = struct.unpack ('H', कच्चा [59:61]) [0]

    शीर्ष लेख लौटाएँ

# WKB रेखापुंज डेटा को डिक्रिप्ट करने का कार्य 
def wkbImage (कच्चा):
    h = wkbHeader (कच्चा)
    img = [] # छवि बैंड स्टोर करने के लिए सरणी
    ऑफसेट = 61 # हैडर कच्ची लंबाई बाइट्स में
    के लिए मैं रेंज में (एच ['nbands']):
        # इस बैंड के लिए Pixtype निर्धारित करें
        पिक्सपाइप = स्ट्रक्चर.पंक ('बी', कच्चा [ऑफसेट]) [0] >> 4
        # अभी के लिए, हम केवल अहस्ताक्षरित बाइट को संभालते हैं
        यदि Pixtype == 4:
            बैंड = np.frombuffer (कच्चा, dtype = 'uint8', count = h ['width'] * h [’’ height ’], ऑफसेट = ऑफसेट + १)
            img.append ((np.reshape (बैंड, (एच ['ऊंचाई'], एच ['चौड़ाई']))))
            ऑफसेट = ऑफसेट + 2 + एच ['चौड़ाई'] * एच ['ऊंचाई']
        # करने के लिए: अन्य डेटा प्रकारों को संभालें 

    वापसी cv2.merge (ट्यूपल (img))


यह बहुत मददगार है। मुझे एक कॉन्डा वातावरण में गदल के साथ बहुत सारी समस्याएं हो रही हैं, लेकिन इस दृष्टिकोण ने पहली बार काम किया है, और संरचना में थोड़ा सा भी बदलाव करने में सक्षम होना अच्छा है।
जॉन पॉवेल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.