Как мне преобразовать данные Postgres bytea или объект памяти Python в массив NumPy? - PullRequest
0 голосов
/ 05 ноября 2018

У меня есть база данных 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: преобразование представления памяти в массив NumPy ):

[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 (за Преобразование BLOB, хранящегося в базе данных, в изображение на веб-сайте HTML ), но не смог открыть полученные файлы с помощью средства просмотра изображений.

Я тоже пробовал это ( Открыть образ PIL из байтового файла ), но получить такой результат:

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

Или, из Как преобразовать шестнадцатеричную строку в цветное изображение в python? , я получаю эту ошибку:

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

Итак: Как мне преобразовать эти bytea данные или этот memoryview объект в массив NumPy?

Возможно, мне не хватает чего-то простого, или это может быть одной из причин, по которой изображения не должны храниться в базах данных SQL.

1 Ответ

0 голосов
/ 09 ноября 2018

Для потомков вот самое простое решение, к которому я пришел.

Рекомендуется НЕ хранить изображения в базе данных, а хранить в файловой системе несколько версий (с разным разрешением, от миниатюр (до 64х64)) до полного разрешения (в нашем случае 2504х2504) с путями к файлам. Изображения могут быть отсортированы по хешу (некоторые издержки) или по метке времени, последняя работает для нас, потому что все данные поступают с одной камеры и поэтому будут иметь разные метки времени.

Данные, о которых идет речь, представляют собой 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()

Отсюда numpy и matplotlib могут сделать подъем. Я знаю разрешение изображения, но оно также хранится в другом месте таблицы базы данных.

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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...