Python OpenCV Image to byte string для передачи json

Я использую python3 с numpy, scipy и opencv.

Я пытаюсь преобразовать изображение, считываемое через OpenCV и подключенный интерфейс камеры, в двоичную строку, чтобы отправить его в объект json через какое-то сетевое соединение.

Я попытался заключить массив в jpg и декодировать строку UTF-16, но я не получил полезных результатов. например, с помощью

img = get_image()
converted = cv2.imencode('.jpg', img)[1].tostring()
print(converted)

В результате я получаю байтовую строку:

b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00\xff\xdb\x00C\x00\x02\x01\x01\x01\x01\x01\x02\x01....

Но эти данные нельзя использовать в качестве содержимого объекта json, поскольку они содержат недопустимые символы. Есть ли способ показать реальные байты за этой строкой? Я считаю, что \xff представляет значение байта FF, поэтому мне нужно как String, например FFD8FFE0... и так далее, вместо \xff\xd8\xff\xe0. Что я делаю не так?

Я попытался закодировать его как UTF-8 и UTF16 после кода выше, но я получаю несколько ошибок по этому поводу:

utf_string = converted.decode('utf-16-le')

UnicodeDecodeError: кодек "utf-16-le" не может декодировать байты в позиции 0-1: недопустимый суррогат UTF-16

text = strrrrrr.decode('utf-8')

UnicodeDecodeError: кодек "utf-8" не может декодировать байт 0xff в позиции 0: недопустимый начальный байт

Я не могу придумать, как это сделать правильно.

Я также попытался преобразовать ее в строку в кодировке base64, как описано в http://www.programcreek.com/2013/09/convert-image-to-string-in-python/ Но это тоже не работает. (Это решение не является предпочтительным, так как требует, чтобы изображение было временно записано на диск, что не совсем то, что мне нужно. Предпочтительно изображение должно храниться только в памяти, а не на диске.)

Решение должно содержать способ кодирования изображения в виде строки, соответствующей json, а также способ декодирования его обратно в массив numpy, чтобы его можно было снова использовать с cv2.imshow().

Спасибо за любую помощь.

Ответ 1

Вам не нужно сохранять буфер в файл. Следующий сценарий захватывает изображение с веб-камеры, кодирует его как изображение в формате JPG и затем преобразует эти данные в кодировку base64 для базы данных:

import cv2
import base64

cap = cv2.VideoCapture(0)
retval, image = cap.read()
retval, buffer = cv2.imencode('.jpg', image)
jpg_as_text = base64.b64encode(buffer)
print(jpg_as_text)
cap.release()

Даю вам что-то начинающее вроде:

/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAIBAQEBAQIBAQECAgICAgQDAgICAgUEBAMEBgUGBgYFBgYGBwkIBgcJBwYGCAsICQoKCg

Это можно расширить, чтобы показать, как преобразовать его обратно в двоичный файл, а затем записать данные в тестовый файл, чтобы показать, что преобразование было успешным:

import cv2
import base64

cap = cv2.VideoCapture(0)
retval, image = cap.read()
cap.release()

# Convert captured image to JPG
retval, buffer = cv2.imencode('.jpg', image)

# Convert to base64 encoding and show start of data
jpg_as_text = base64.b64encode(buffer)
print(jpg_as_text[:80])

# Convert back to binary
jpg_original = base64.b64decode(jpg_as_text)

# Write to a file to show conversion worked
with open('test.jpg', 'wb') as f_output:
    f_output.write(jpg_original)

Ответ 2

Некоторые, как ответ выше, не работает для меня, это нуждается в некотором обновлении. Вот новый ответ на это:

Чтобы кодировать для JSON:

import base64
import json
import cv2

img = cv2.imread('./0.jpg')
string = base64.b64encode(cv2.imencode('.jpg', img)[1]).decode()
dict = {
    'img': string
}
with open('./0.json', 'w') as outfile:
    json.dump(dict, outfile, ensure_ascii=False, indent=4)

Для декодирования обратно в np.array:

import base64
import json
import cv2
import numpy as np

response = json.loads(open('./0.json', 'r').read())
string = response['img']
jpg_original = base64.b64decode(string)
jpg_as_np = np.frombuffer(jpg_original, dtype=np.uint8)
img = cv2.imdecode(jpg_as_np, flags=1)
cv2.imwrite('./0.jpg', img)

Надеюсь, это может кому-то помочь: P