Answers:
至于ST_AsTIFF的第一个错误,您需要启用GDAL驱动程序,默认情况下未为PostGIS 2.1启用该驱动程序。有关方法,请参见手册。例如,我在Windows计算机上使用以下命令设置了环境变量:
POSTGIS_GDAL_ENABLED_DRIVERS=GTiff PNG JPEG GIF XYZ DTED USGSDEM AAIGrid
可以通过PostGIS通过以下方式进行确认:
SELECT short_name, long_name
FROM ST_GDALDrivers();
您可以将输出导出到虚拟内存GeoTIFF文件中,以供GDAL读取到Numpy数组中。有关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”格式,但其他格式可能更适合。例如,如果您有较大的栅格需要通过缓慢的Internet连接传输,请尝试使用“ PNG”对其进行压缩。
我认为问题是,如果不启用gdal驱动程序,是否可以从Postgis栅格表中读取。就像Python一样,您可以!
确保将栅格结果选择为WKBinary:
选择St_AsBinary(rast)...
使用下面的脚本将WKBinary解密为python图像格式。我更喜欢opencv,因为它可以处理任意数量的图像带,但是如果更常用1或3个带,则可以使用PIL / low。
我现在只处理字节图像,但是扩展到其他数据类型相对来说并不容易。
希望这是有用的。
导入结构 将numpy导入为np 导入cv2 #解密WKB标头的函数 def wkbHeader(raw): #参见http://trac.osgeo.org/postgis/browser/trunk/raster/doc/RFC2-WellKnownBinaryFormat 标头= {} header ['endianess'] = struct.unpack('B',raw [0])[0] header ['version'] = struct.unpack('H',raw [1:3])[0] 标头['nbands'] = struct.unpack('H',raw [3:5])[0] header ['scaleX'] = struct.unpack('d',raw [5:13])[0] 标头['scaleY'] = struct.unpack('d',raw [13:21])[0] 标头['ipX'] = struct.unpack('d',raw [21:29])[0] 标头['ipY'] = struct.unpack('d',raw [29:37])[0] 标头['skewX'] = struct.unpack('d',raw [37:45])[0] 标头['skewY'] = struct.unpack('d',raw [45:53])[0] 标头['srid'] = struct.unpack('i',raw [53:57])[0] header ['width'] = struct.unpack('H',raw [57:59])[0] header ['height'] = struct.unpack('H',raw [59:61])[0] 返回头 #解密WKB栅格数据的功能 def wkbImage(原始): h = wkbHeader(原始) img = []#存储图像波段的数组 offset = 61#标头原始长度(以字节为单位) 对于范围内的我(h ['nbands']): #确定该乐队的像素类型 pixtype = struct.unpack('B',raw [offset])[0] >> 4 #目前,我们只处理无符号字节 如果pixtype == 4: band = np.frombuffer(原始,dtype ='uint8',count = h ['width'] * h ['height'],offset = offset + 1) img.append((np.reshape(band,((h ['height'],h ['width']))))))) 偏移量=偏移量+ 2 + h ['width'] * h ['height'] #要做的:处理其他数据类型 返回cv2.merge(tuple(img))