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
Python - Having Trouble Opening a File With Spaces
How to Remove \N from a List Element
How to Clear All Variables in the Middle of a Python Script
How to Get the Return Value from a Thread in Python
How to Select Last Row and Also How to Access Pyspark Dataframe by Index
How to Bold Text in Telepot Telegram Bot
How to Append a List Withoud Adding the Quote
Save Variables in Every Iteration of for Loop and Load Them Later
Python Convert Comma Separated List to Pandas Dataframe
Python Handling Socket.Error: [Errno 104] Connection Reset by Peer
Convert CSV to Parquet File Using Python
How to Remove Zeros After Decimal from String Remove All Zero After Dot
Python 3 Error - Typeerror: Input Expected At Most 1 Arguments, Got 3
How to Create a Multiline Plot Using Seaborn
Csv File Written With Python Has Blank Lines Between Each Row