Python OpenCV Image to byte string for json transfer

Question:

I use python3 with numpy, scipy and opencv.

I’m trying to convert a image read through OpenCV and connected camera interface into a binary string, to send it within a json object through some network connection.

I have tried enconding the array as jpg and the decode the UTF-16 string, but I get no usable results. as example, with

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

I get a byte-string as result:

b’xffxd8xffxe0x00x10JFIFx00x01x01x00x00x01x00x01x00x00xffxdbx00Cx00x02x01x01x01x01x01x02x01….

But this data cannot be used as content of a json object, because it contains invalid characters. Is there a way I can display the real bytes behind this string?
I believe that xff represents byte value FF, so I need as String like FFD8FFE0… and so on, instead of xffxd8xffxe0. What am I doing wrong?

I tried to encode it as UTF-8 and UTF16 after the code above, but I get several errors on that:

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

UnicodeDecodeError: ‘utf-16-le’ codec can’t decode bytes in position 0-1: illegal UTF-16 surrogate

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

UnicodeDecodeError: ‘utf-8’ codec can’t decode byte 0xff in position 0: invalid start byte

I can’t figure out a way to get this right.

I also tried to convert it into a base64 encoded string, like explained in
http://www.programcreek.com/2013/09/convert-image-to-string-in-python/
But that doesn’t work either. ( This solution is not preferred, as it requires the image being written temporarly to disk, which is not exactly what I need. Preferrably the image should only be hold in memory, never on disk.)

The solution should contain a way to encode the image as json-conform string and also a way to decode it back to numpy-array, so it can be used again with cv2.imshow().

Thanks for any help.

Asked By: Jack O'neill

||

Answers:

You do not need to save the buffer to a file. The following script captures an image from a webcam, encodes it as a JPG image, and then converts that data into a printable base64 encoding which can be used with your JSON:

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()

Giving you something starting like:

/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAIBAQEBAQIBAQECAgICAgQDAgICAgUEBAMEBgUGBgYFBgYGBwkIBgcJBwYGCAsICQoKCg

This could be extended to show how to convert it back to binary and then write the data to a test file to show that the conversion was successful:

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)

To get the image back as an image buffer (rather than JPG format) try:

jpg_as_np = np.frombuffer(jpg_original, dtype=np.uint8)
image_buffer = cv2.imdecode(jpg_as_np, flags=1)
Answered By: Martin Evans

Some how the above answer doesn’t work for me, it needs some update. Here is the new answer to this:

To encode for 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)

To decode back to 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)

Hope this could help someone 😛

Answered By: lamhoangtung
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.