【问题标题】:How do I convert Postgres bytea data or a Python memoryview object into a NumPy array?如何将 Postgres bytea 数据或 Python memoryview 对象转换为 NumPy 数组?
【发布时间】:2019-04-09 04:39:54
【问题描述】:

我有一个 PostgreSQL 数据库 (v 9.6),其中图像存储为 bytea 数据。我不知道图像编码。 (我没有设置这个数据库,也不清楚我是否可以改变这个设置,虽然我想,因为在 PostgreSQL 数据库中存储大图像不是(IIUC)最佳实践。)

我想将此数据提取到图像中,或者更好的是,直接提取到 NumPy 数组中。

使用 SQLAlchemy,我可以连接和提取数据:

engine = create_engine(postgresql+psycopg2://user:password@server:port/database)
connection = engine.connect()
result = connection.execute('SELECT image FROM database.table LIMIT 1;')

有问题的图像作为memoryview 对象返回;转换为numpy 数组,它看起来像这样(根据Cython: Convert memory view to NumPy array):

[b'\xaa' b'\x04' b'u' b'\x04' b'\x85' b'\x04' b'E' b'\x04' b'\x7f' b'\x04'
 b'\xa5' b'\x04' b'K' b'\x04' b'j' b'\x04' b'\x97' b'\x04' b';' b'\x04'
 b'w' b'\x04' b'k' b'\x04' b'E' b'\x04' b'b' b'\x04' b's' b'\x04']

我尝试保存为 jpg 或 tiff 文件(根据 Converting BLOB, stored on a database, to an image on an HTML website),但无法使用图像查看器打开生成的文件。

我也试过这个(Open PIL image from byte file),但是得到了这个结果:

OSError: cannot identify image file <_io.BytesIO object at 0x000002299F4DD830>

或者,来自How to convert hex string to color image in python?,我收到此错误:

ValueError: non-hexadecimal number found in fromhex() arg at position 0

那么:如何将 bytea 数据或 memoryview 对象转换为 NumPy 数组?

我可能遗漏了一些简单的东西,或者这可能只是图像不应该存储在 SQL 数据库中的原因之一。

【问题讨论】:

    标签: python postgresql numpy opencv matplotlib


    【解决方案1】:

    为了后代,这是我得出的最简单的解决方案。

    最佳做法是不要将图像存储在数据库中,而是在文件系统中存储多个版本(不同的分辨率,从缩略图(64x64 ish)到完整分辨率(在本例中为 2504x2504),以及这些图像的文件路径. 图像可以按哈希(一些开销)或时间戳之类的东西排序;后者对我们有用,因为所有数据都来自一个相机,因此会有不同的时间戳。

    相关数据是 16 位灰度 TIFF 文件。 Python 图像库 (PIL) 无法翻译这些图像。 OpenCV 可以。但是,由于无论如何我都想要一个 NumPy 数组,所以这并不重要。 MatPlotLib 可以直接显示数组。 Numpy 可以根据需要进行切片或下采样。

    engine = create_engine('postgresql+psycopg2://user:pass@server:port/database')
    connection = engine.connect()
    
    query = 'SELECT * FROM database.schema.table WHERE "ID" = 1234'
    result = connection.execute(query)
    
    for row in result:
        data = row[-1] # our image is the last column in the table
    
    connection.close()
    

    从这里,numpymatplotlib 可以完成提升。我知道图像的分辨率,但它也存储在数据库表的其他位置。

    img_array = np.reshape(np.frombuffer(data, dtype="Int16"), (2504, 2504))
    
    norm = cm.colors.Normalize(vmax=abs(img_array).max(), vmin=-abs(img_array).max())
    plt.matshow(img_array, norm=norm, cmap="gray")
    plt.show()
    

    plt.imshow() 也可以。

    使用 OpenCV,我们使用的代码是这样的:

    cv2.namedWindow("Image", cv2.WINDOW_NORMAL | cv2.WINDOW_KEEPRATIO)
    cv2.imshow("Image", img_array)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-17
      • 2021-07-06
      • 2013-04-08
      • 2017-06-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多