Nathan Ortega
Nathan Ortega

Reputation: 658

Convert base64 String to an Image that's compatible with OpenCV

I'm trying to convert a base64 representation of a JPEG to an image that can be used with OpenCV. The catch is that I'd like to be able to do this without having to physically save the photo (I'd like it to remain in memory). Is there an updated way of accomplishing this?

I'm using python 3.6.2 and OpenCV 3.3

Here is a partial example of the type of input I'm trying to convert:

/9j/4AAQSkZJRgABAQAASABIAAD/4QBYRXhpZgAATU0AKgAAAAgAAgESAAMAAAA....

I've already tried the solutions provided by these questions, but keep getting the same "bad argument type for built-in operation" error:

Upvotes: 15

Views: 42616

Answers (5)

iampritamraj
iampritamraj

Reputation: 316

I have tried all these method but not works for me and have unidentified encoding error.

script that work for me. directly download image using requests and show using PIL

import requests
from io import BytesIO
import base64
from PIL import Image
def image_show(image_url=None):
    img_response = requests.get(image_url)
    if img_response.ok:
        image_bytes = BytesIO(base64.b64decode(base64.b64encode(img_response.content)))
        img = Image.open(image_bytes)
        return img
    else:
        print("invalid image url response")
image_show(image_url= 'https://images.unsplash.com/photo-1515628640587-603301d8a4d4?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&dl=shane-stagner-mdS-6oNgRXc-unsplash.jpg')

Upvotes: 0

abcd1234
abcd1234

Reputation: 67

Here are some commands that could be helpful

import io
import cv2
import base64 
import numpy as np
from PIL import Image

#convert image to byte type
with open("tes-img/example27.png", "rb") as image_file:
    encoded_string1 = base64.b64encode(image_file.read())

#convert byte to string
encoded_string = encoded_string1.decode("utf-8")

#convert string to byte
base64_image = str.encode(encoded_string)

#save image locally
with open("tes-img/example27_2.png", "wb") as fh:
    fh.write(base64.decodebytes(base64_image))

#convert byte to numpy array for cv2 
img_color = cv2.cvtColor(np.array(Image.open(io.BytesIO(base64.b64decode(base64_image)))), cv2.COLOR_BGR2RGB)

Upvotes: 1

Anthony Anyanwu
Anthony Anyanwu

Reputation: 1047

You can also try this:

import numpy as np
import cv2

def to_image_string(image_filepath):
    return open(image_filepath, 'rb').read().encode('base64')

def from_base64(base64_data):
    nparr = np.fromstring(base64_data.decode('base64'), np.uint8)
    return cv2.imdecode(nparr, cv2.IMREAD_ANYCOLOR)

You can now use it like this:

filepath = 'myimage.png'
encoded_string = to_image_string(filepath)

load it with open cv like this:

im = from_base64(encoded_string)
cv2.imwrite('myloadedfile.png', im)

Upvotes: 9

andre
andre

Reputation: 373

Here an example for python 3.6 that uses imageio instead of PIL. It first loads an image and converts it to a b64_string. This string can then be sent around and the image reconstructed as follows:

import base64
import io
import cv2
from imageio import imread
import matplotlib.pyplot as plt

filename = "yourfile.jpg"
with open(filename, "rb") as fid:
    data = fid.read()

b64_bytes = base64.b64encode(data)
b64_string = b64_bytes.decode()

# reconstruct image as an numpy array
img = imread(io.BytesIO(base64.b64decode(b64_string)))

# show image
plt.figure()
plt.imshow(img, cmap="gray")

# finally convert RGB image to BGR for opencv
# and save result
cv2_img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
cv2.imwrite("reconstructed.jpg", cv2_img)
plt.show()

Upvotes: 19

Nathan Ortega
Nathan Ortega

Reputation: 658

I've been struggling with this issue for a while now and of course, once I post a question - I figure it out.

For my particular use case, I needed to convert the string into a PIL Image to use in another function before converting it to a numpy array to use in OpenCV. You may be thinking, "why convert to RGB?". I added this in because when converting from PIL Image -> Numpy array, OpenCV defaults to BGR for its images.

Anyways, here's my two helper functions which solved my own question:

import io
import cv2
import base64 
import numpy as np
from PIL import Image

# Take in base64 string and return PIL image
def stringToImage(base64_string):
    imgdata = base64.b64decode(base64_string)
    return Image.open(io.BytesIO(imgdata))

# convert PIL Image to an RGB image( technically a numpy array ) that's compatible with opencv
def toRGB(image):
    return cv2.cvtColor(np.array(image), cv2.COLOR_BGR2RGB)

Upvotes: 20

Related Questions