27

I have an image in bytes:

print(image_bytes)

b'\xff\xd8\xff\xfe\x00\x10Lavc57.64.101\x00\xff\xdb\x00C\x00\x08\x04\x04\x04\x04\x04\x05\x05\x05\x05\x05\x05\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x07\x07\x07\x08\x08\x08\x07\x07\x07\x06\x06\x07\x07\x08\x08\x08\x08\t\t\t\x08\x08\x08\x08\t\t\n\n\n\x0c\x0c\x0b\x0b\x0e\x0e\x0e\x11\x11\x14\xff\xc4\x01\xa2\x00\x00\x01\x05\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x01\x00\x03\x01\x01\x01\x01\x01\x01\x01\x01\x01\x00\x00\ ... some other stuff

I am able to convert it to a NumPy array using Pillow:

image = numpy.array(Image.open(io.BytesIO(image_bytes))) 

But I don't really like using Pillow. Is there a way to use clear OpenCV, or directly NumPy even better, or some other faster library?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Martin Brisiak
  • 3,872
  • 12
  • 37
  • 51
  • 2
    Possible duplicate of [Convert a byte arry to OpenCV image in C++](https://stackoverflow.com/questions/12114605/convert-a-byte-arry-to-opencv-image-in-c) – GPPK Mar 27 '18 at 11:32
  • 3
    Thanks for your feed back, although that's c++, not python. – Martin Brisiak Mar 27 '18 at 11:33
  • Yes but it's the same code for python just with less brackets... https://docs.opencv.org/3.0-beta/modules/imgcodecs/doc/reading_and_writing_images.html – GPPK Mar 27 '18 at 11:35
  • @Norrius I read "I have image in bytes" and "image_bytes" and had to make the assumption it was. If that is not the case then OP needs to clarify in the question why it is different. – GPPK Mar 27 '18 at 12:07
  • @GPPK "byte image to numpy array using opencv" seems reasonably clear to me. The only question is what format the image is in. OP? – Norrius Mar 27 '18 at 12:10
  • about the format i have to admit that i'm not completely sure, looks like char representation of hex in `bytes` format to me but otherwise i'm lost :( `type(image_bytes) = bytes` – Martin Brisiak Mar 27 '18 at 12:18
  • 1
    It's a JPEG image since `ff,d8,ff` is the JPEG signature, so you will need to `imdecode()` it. See here... https://stackoverflow.com/a/49492989/2836621 – Mark Setchell Mar 27 '18 at 12:50

2 Answers2

46

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]]]
Norrius
  • 7,558
  • 5
  • 40
  • 49
0

I searched all over the internet finally I solved:

NumPy array (cv2 image) - Convert

NumPy to bytes

and

bytes to NumPy

:.

#data = cv2 image array
def encodeImage(data):
    #resize inserted image
    data= cv2.resize(data, (480,270))
    # run a color convert:
    data= cv2.cvtColor(data, cv2.COLOR_BGR2RGB)
    return bytes(data) #encode Numpay to Bytes string



def decodeImage(data):
    #Gives us 1d array
    decoded = np.fromstring(data, dtype=np.uint8)
    #We have to convert it into (270, 480,3) in order to see as an image
    decoded = decoded.reshape((270, 480,3))
    return decoded;

# Load an color image
image= cv2.imread('messi5.jpg',1)

img_code = encodeImage(image) #Output: b'\xff\xd8\xff\xe0\x00\x10...';
img = decodeImage(img_code) #Output: normal array
cv2.imshow('image_deirvlon',img);
print(decoded.shape)

You can get full code from here

Kamran Gasimov
  • 1,445
  • 1
  • 14
  • 11