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','rb')
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.

Answer from jabaldonedo on Stack Overflow
Top answer
1 of 2
47

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]]]
2 of 2
1

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

Discussions

How to convert byte array to OpenCV Mat in Python - Stack Overflow
How do I convert a byte array to Mat object in Python. import numpy as np mat = np.asarray(0, 0, data) print 'Cols n Row ' + str(mat.cols) + " " + str(mat.rows) But it is not working. Can some one help. ... data is the byte array, which I want to convert as OpenCV Mat. More on stackoverflow.com
🌐 stackoverflow.com
April 26, 2017
[Help!] How to encoded byte array to Mat??
Hi. I want to send webcam image to another computer using UDP socket communication. So I made the code using python. More on github.com
🌐 github.com
4
December 30, 2020
How to read raw png from an array in python opencv? - Stack Overflow
This solution is tested under opencv ... and/or python 2.7x. Fewer imports. This can all be done with numpy and opencv directly, no need for StringIO and PIL. Here is how I create an opencv image decoded directly from a file object, or from a byte buffer read from a file object. import cv2 import numpy as np #read the data from the file with open(somefile, 'rb') as infile: buf = infile.read() #use numpy to construct an array from the bytes ... More on stackoverflow.com
🌐 stackoverflow.com
Python OpenCV convert image to byte string? - Stack Overflow
I'm working with PyOpenCV. How to convert cv2 image (numpy) to binary string for writing to MySQL db without a temporary file and imwrite? I googled it but found nothing... I'm trying imencode, b... More on stackoverflow.com
🌐 stackoverflow.com
Top answer
1 of 2
3

Updated Again

I looked into JPEG decoding from the memory buffer using PyTurboJPEG, the code goes like this to compare with OpenCV's imdecode():

#!/usr/bin/env python3

import cv2
from turbojpeg import TurboJPEG, TJPF_GRAY, TJSAMP_GRAY

# Load image into memory
r = open('image.jpg','rb').read()
inp = np.asarray(bytearray(r), dtype=np.uint8)

# Decode JPEG from memory into Numpy array using OpenCV
i0 = cv2.imdecode(inp, cv2.IMREAD_COLOR)

# Use default library installation
jpeg = TurboJPEG()

# Decode JPEG from memory using turbojpeg
i1 = jpeg.decode(r)
cv2.imshow('Decoded with TurboJPEG', i1)
cv2.waitKey(0)

And the answer is that TurboJPEG is 7x faster! That is 4.6ms versus 32.2ms.

In [18]: %timeit i0 = cv2.imdecode(inp, cv2.IMREAD_COLOR)                                           
32.2 ms ± 346 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [19]: %timeit i1 = jpeg.decode(r)                                                                
4.63 ms ± 55.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Kudos to @Nuzhny for spotting it first!

Updated Answer

I have been doing some further benchmarks on this and was unable to verify your claim that it is faster to save an image to disk and read it with imread() than it is to use imdecode() from memory. Here is how I tested in IPython:

import cv2

# First use 'imread()'

%timeit i1 = cv2.imread('image.jpg', cv2.IMREAD_COLOR)
116 ms ± 2.86 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

# Now prepare the exact same image in memory
r = open('image.jpg','rb').read()  
inp = np.asarray(bytearray(r), dtype=np.uint8)

# And try again with 'imdecode()'
%timeit i0 = cv2.imdecode(inp, cv2.IMREAD_COLOR)
113 ms ± 1.17 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

So, I find imdecode() around 3% faster than imread() on my machine. Even if I include the np.asarray() into the timing, it is still quicker from memory than disk - and I have seriously fast 3GB/s NVME disks on my machine...

Original Answer

I haven't tested this but it seems to me that you are doing this in a loop:

read 1k bytes
append it to a buffer
look for JPEG SOI marker (0xffdb)
look for JPEG EOI marker (0xffd9)
if you have found both the start and the end of a JPEG frame, decode it

1) Now, most JPEG images with any interesting content I have seen are between 30kB to 300kB so you are going to do 30-300 append operations on a buffer. I don't know much abut Python but I guess that may cause a re-allocation of memory, which I guess may be slow.

2) Next you are going to look for the SOI marker in the first 1kB, then again in the first 2kB, then again in the first 3kB, then again in the first 4kB - even if you have already found it!

3) Likewise, you are going to look for the EOI marker in the first 1kB, the first 2kB...

So, I would suggest you try:

1) allocating a bigger buffer at the start and acquiring directly into it at the appropriate offset

2) not searching for the SOI marker if you have already found it - e.g. set it to -1 at the start of each frame and only try and find it if it is still -1

3) only look for the EOI marker in the new data on each iteration, not in all the data you have already searched on previous iterations

4) furthermore, actually, don't bother looking for the EOI marker unless you have already found the SOI marker, because the end of a frame without the corresponding start is no use to you anyway - it is incomplete.

I may be wrong in my assumptions, (I have been before!) but at least if they are public someone cleverer than me can check them!!!

2 of 2
0

I recommend to use turbo-jpeg. It has a python API: PyTurboJPEG.

🌐
Finxter
blog.finxter.com › home › learn python blog › 5 best ways to convert python bytearray to image
5 Best Ways to Convert Python Bytearray to Image - Be on the Right Side of Change
February 24, 2024 - If you’re dealing with images, especially in the context of computer vision, converting a bytearray to an image using OpenCV can be a practical choice. This method also allows additional image processing steps to be easily integrated. ... import cv2 import numpy as np image_byte_array = bytearray(b'...') # your byte data here np_array = np.asarray(image_byte_array, dtype=np.uint8) image = cv2.imdecode(np_array, cv2.IMREAD_UNCHANGED) cv2.imwrite('output.jpg', image)
🌐
Finxter
blog.finxter.com › 5-best-ways-to-convert-python-bytes-to-a-cv2-image
5 Best Ways to Convert Python Bytes to a cv2 Image – Be on the Right Side of Change
This snippet converts a byte string into a numpy array and then decodes it into an image using OpenCV’s cv2.imdecode().
Find elsewhere
🌐
GitHub
github.com › EnoxSoftware › OpenCVForUnity › issues › 91
[Help!] How to encoded byte array to Mat?? · Issue #91 · EnoxSoftware/OpenCVForUnity
December 30, 2020 - import socket import cv2 import numpy HOST = '127.0.0.1' PORT = 9999 server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) capture = cv2.VideoCapture(0) while True: ret, frame = capture.read() if ret == False: continue encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), 90] result, imgencode = cv2.imencode('.jpg', frame, encode_param) data = numpy.array(imgencode) stringData = data.tobytes() // send total image byte size server_socket.sendto(str(len(stringData)).encode(), (HOST, PORT)) // send image data server_socket.sendto(stringData, (HOST, PORT)) if key == 27: break server_socket.close()
Author   EnoxSoftware
🌐
Saturn Cloud
saturncloud.io › blog › converting-byte-images-to-numpy-arrays-using-opencv-in-python
Converting Byte Images to NumPy Arrays Using OpenCV ...
July 23, 2023 - Saturn Cloud is the white-labeled control plane for GPU clouds: multi-tenant isolation, day-2 support, and integrated billing, running in your cloud under your brand.
Top answer
1 of 6
21

@Andy Rosenblum's works, and it might be the best solution if using the outdated cv python API (vs. cv2).

However, because this question is equally interesting for users of the latest versions, I suggest the following solution. The sample code below may be better than the accepted solution because:

  1. It is compatible with newer OpenCV python API (cv2 vs. cv). This solution is tested under opencv 3.0 and python 3.0. I believe only trivial modifications would be required for opencv 2.x and/or python 2.7x.
  2. Fewer imports. This can all be done with numpy and opencv directly, no need for StringIO and PIL.

Here is how I create an opencv image decoded directly from a file object, or from a byte buffer read from a file object.

import cv2
import numpy as np

#read the data from the file
with open(somefile, 'rb') as infile:
     buf = infile.read()

#use numpy to construct an array from the bytes
x = np.fromstring(buf, dtype='uint8')

#decode the array into an image
img = cv2.imdecode(x, cv2.IMREAD_UNCHANGED)

#show it
cv2.imshow("some window", img)
cv2.waitKey(0)

Note that in opencv 3.0, the naming convention for the various constants/flags changed, so if using opencv 2.x, you will need to change the flag cv2.IMREAD_UNCHANGED. This code sample also assumes you are loading in a standard 8-bit image, but if not, you can play with the dtype='...' flag in np.fromstring.

2 of 6
16

another way,

also in the case of a reading an actual file this will work for a unicode path (tested on windows)

with open(image_full_path, 'rb') as img_stream:
    file_bytes = numpy.asarray(bytearray(img_stream.read()), dtype=numpy.uint8)
    img_data_ndarray = cv2.imdecode(file_bytes, cv2.CV_LOAD_IMAGE_UNCHANGED)
    img_data_cvmat = cv.fromarray(img_data_ndarray) #  convert to old cvmat if needed
🌐
Reddit
reddit.com › r/learnpython › how to have a bytes image read by open cv2?
r/learnpython on Reddit: How to have a bytes image read by open cv2?
November 18, 2021 - for dictkey, dictvalue in hardcoded_images_reference.items(): with open('../assets/' + dictvalue, 'rb') as original_file: original = original_file.read() encrypted = cipher.encrypt(original) with open('../assets/' + dictkey, 'wb') as encrypted_file: encrypted_file.write(encrypted) print(hardcoded_images_reference) decrypted_images = {} # decrypt images for dictkey, dictvalue in hardcoded_images_reference.items(): with open('../assets/' + dictkey, 'rb') as encrypted_file: encrypted = encrypted_file.read() data = cipher.decrypt(encrypted) print(type(data)) data = np.asarray(bytearray(data.read()
🌐
O'Reilly
oreilly.com › library › view › learning-opencv-4 › 9781789531619 › 06e3c7bb-ea14-47b4-a0d5-c7e066808f1e.xhtml
Converting between an image and raw bytes - Learning OpenCV 4 Computer Vision with Python 3 - Third Edition [Book]
We may access these values by using an expression such as image[0, 0] or image[0, 0, 0]. The first index is the pixel's y coordinate or row, 0 being the top. The second index is the pixel's x coordinate or column, 0 being the leftmost.
🌐
Reddit
reddit.com › r/opencv › [question] how to decode a byte arrray
r/opencv on Reddit: [Question] How to decode a byte arrray
November 2, 2021 -

Hi, I'm new to opencv and I'm trying to decode a byte array

From one side I'm sending I need to send a message in bytes format, and I'm using this code:

image_bytes = cv2.imencode('.jpg', imageRGB)[1].tobytes()

And from the receiving side, I'm am receiving a message with the following type: <class 'str'>
with this content: /9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAIBAQEBAQIBAQECAgICAgQDAgICAgUEBAMEBgUGBgYFBgYGBwkIBgcJBwYGCAsICQoK ...

I tried the following: (x['other']['contentBytes'] is where the bytes are)

nparr = np.fromstring(x['other']['contentBytes'], np.uint8)

This returns a ( <class 'numpy.ndarray'> ) with the following shape: (40672,)

And when I try to

newFrame = cv2.imdecode(nparr, cv2.IMREAD_COLOR)

I get a <class 'NoneType'> type.

🌐
jdhao's digital space
jdhao.github.io › 2020 › 03 › 17 › base64_opencv_pil_image_conversion
Conversion between base64 and OpenCV or PIL Image · jdhao's digital space
May 7, 2021 - When we are building web services using Python, we often send or receive images in base64 encoded format. However, when we are doing image processing tasks, we need to use PIL or OpenCV. In this post, I will share how to convert between OpenCV or PIL image and base64 encoded image. import base64 from io import BytesIO from PIL import Image with open("test.jpg", "rb") as f: im_b64 = base64.b64encode(f.read()) im_bytes = base64.b64decode(im_b64) # im_bytes is a binary image im_file = BytesIO(im_bytes) # convert image to file-like object img = Image.open(im_file) # img is now PIL Image object
🌐
OpenCV Q&A Forum
answers.opencv.org › question › 190515 › i-want-to-generate-a-gray-scale-image-from-byte-arrayis-it-possible-to-do-it-with-opencv
i want to generate a gray-scale image from byte array,is it possible to do it with opencv ? - OpenCV Q&A Forum
//2. Convert byte to image Mat img1 = new Mat(256,256, CvType.CV_8UC1); img1.put(0, 0, pixels); String filename = "C:\\Users\\domin\\Desktop\\Sop\\dreams.png"; Highgui.imwrite(filename, img1); ... Exception in thread "main" java.lang.UnsupportedOperationException: Provided data element number ...
🌐
Google Sites
sites.google.com › site › hellobenchen › home › wiki › python › bytes-image-cv2
BEN CHEN's Homepage - bytes image cv2
Save an image into bytes. Read an image from bytes. The bytes can be stored in database as binary. from io import BytesIO from PIL import Image import cv2 import numpy as np img = Image.open(r'C:\temp\sample.jpg') bytes_io = BytesIO() img.save(bytes_io, 'JPEG', quality = 95) content =
🌐
OpenCV
docs.opencv.org › 3.4.20 › d5 › d98 › tutorial_mat_operations.html
OpenCV: Operations with images
Python · img = cv.imread('image.jpg') ... greyscale image img · C++ img = Scalar(0); Java · byte[] imgData = new byte[(int) (img.total() * img.channels())]; Arrays.fill(imgData, (byte) 0); img.put(0, 0, imgData); Python ·...
🌐
jdhao's digital space
jdhao.github.io › 2019 › 07 › 06 › python_opencv_pil_image_to_bytes
Convert PIL or OpenCV Image to Bytes without Saving to Disk · jdhao's digital space
October 6, 2020 - What if we want to resize the original image and convert it to binary data, without saving the resized image and re-read it from the hard disk? How should we do it? We can do it with the help of OpenCV or PIL. ... import cv2 im = cv2.imread('test.jpg') im_resize = cv2.resize(im, (500, 500)) is_success, im_buf_arr = cv2.imencode(".jpg", im_resize) byte_im = im_buf_arr.tobytes() # or using BytesIO # io_buf = io.BytesIO(im_buf_arr) # byte_im = io_buf.getvalue()