Python Opencv Load Image from Byte String

Python OpenCV load image from byte string

This is what I normally use to convert images stored in database to OpenCV images in Python.

import numpy as np
import cv2
from cv2 import cv

# Load image as string from file/database
fd = open('foo.jpg')
img_str = fd.read()
fd.close()

# CV2
nparr = np.fromstring(img_str, np.uint8)
img_np = cv2.imdecode(nparr, cv2.CV_LOAD_IMAGE_COLOR) # cv2.IMREAD_COLOR in OpenCV 3.1

# CV
img_ipl = cv.CreateImageHeader((img_np.shape[1], img_np.shape[0]), cv.IPL_DEPTH_8U, 3)
cv.SetData(img_ipl, img_np.tostring(), img_np.dtype.itemsize * 3 * img_np.shape[1])

# check types
print type(img_str)
print type(img_np)
print type(img_ipl)

I have added the conversion from numpy.ndarray to cv2.cv.iplimage, so the script above will print:

<type 'str'>
<type 'numpy.ndarray'>
<type 'cv2.cv.iplimage'>

EDIT:
As of latest numpy 1.18.5 +, the np.fromstring raise a warning, hence np.frombuffer shall be used in that place.

Python - byte image to NumPy array using OpenCV

I created a 2x2 JPEG image to test this. The image has white, red, green and purple pixels. I used cv2.imdecode and numpy.frombuffer

import cv2
import numpy as np

f = open('image.jpg', 'rb')
image_bytes = f.read() # b'\xff\xd8\xff\xe0\x00\x10...'

decoded = cv2.imdecode(np.frombuffer(image_bytes, np.uint8), -1)

print('OpenCV:\n', decoded)

# your Pillow code
import io
from PIL import Image
image = np.array(Image.open(io.BytesIO(image_bytes)))
print('PIL:\n', image)

This seems to work, although the channel order is BGR and not RGB as in PIL.Image. There are probably some flags you might use to tune this. Test results:

OpenCV:
[[[255 254 255]
[ 0 0 254]]

[[ 1 255 0]
[254 0 255]]]
PIL:
[[[255 254 255]
[254 0 0]]

[[ 0 255 1]
[255 0 254]]]

Python OpenCV Image to byte string for json transfer

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)

Python3 OpenCV imshow() bytes string

So, found a solution:

# converting bytestring frame into imshow argument
nparr = np.fromstring(frame, np.uint8)
frame = cv2.imdecode(nparr, cv2.IMREAD_COLOR)

cv2.imshow('image', frame)
cv2.waitKey(1)

How to encode OpenCV Image as bytes using Python

I want to start by getting your test case working, we will do this by using a lossless format with no compression so we are comparing apples to apples:

import cv2

path_in = r".\test\frame1.jpg"
path_temp = r".\test\frame1.bmp"
img = cv2.imread(path_in, -1)
cv2.imwrite(path_temp, img) # save in lossless format for a fair comparison

with open(path_temp, "rb") as image:
image1 = image.read()

image2 = cv2.imencode(".bmp", img)[1].tobytes() #also tried tostring()

print(image1 == image2)
#This prints True.

This is not ideal since compression is desirable for moving around bytes, but it illustrates that there is nothing inherently wrong with your encoding.

Without knowing the details of your server it is hard to know why it isn't accepting the opencv encoded images. Some suggestions are:

  • provide format specific encoding parameters as described in the docs, available flags are here
  • try different extensions


Related Topics



Leave a reply



Submit