Convert opencv image format to PIL image format?

PythonOpencvImage ProcessingType ConversionPython Imaging-Library

Python Problem Overview


I want to convert an image loaded

TestPicture = cv2.imread("flowers.jpg")

I would like to run a PIL filter like on the example with the variable

TestPicture

but I'm unable to convert it back and forth between these types.

  • Is there a way to do these conversions?

  • Can OpenCV do all of the image filters that are in the PIL package?

Example:

enter image description here

Result:

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
threshold_img = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
im_pil = cv2_to_pil(threshold_img)
pytesseract.image_to_string(im_pil)
Out[5]: 'TUM'

Python Solutions


Solution 1 - Python

Yes OpenCV is more robust and flexible and can perform most of the image processing routines which are available out there, So probably this filter can be done with OpenCV> However, there may not be a straightforward API for that.

Anyways, as far as the conversion of image format from OpenCV to PIL is concerned you may use Image.fromarray as:

import cv2
import numpy as np
from PIL import Image

img = cv2.imread("path/to/img.png")

# You may need to convert the color.
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
im_pil = Image.fromarray(img)

# For reversing the operation:
im_np = np.asarray(im_pil)

But you must keep in mind that, OpenCV follows BGR convention and PIL follows RGB color convention, so to keep the things consistent you may need to do use cv2.cvtColor() before conversion.

Solution 2 - Python

Pillow and OpenCV use different formats of images. So you can't just read an image in Pillow and manipulate it into an OpenCV image. Pillow uses the RGB format as @ZdaR highlighted, and OpenCV uses the BGR format. So, you need a converter to convert from one format to another.

To convert from PIL image to OpenCV use:

import cv2
import numpy as np
from PIL import Image

pil_image=Image.open("demo2.jpg") # open image using PIL

# use numpy to convert the pil_image into a numpy array
numpy_image=numpy.array(pil_img)  

# convert to a openCV2 image, notice the COLOR_RGB2BGR which means that 
# the color is converted from RGB to BGR format
opencv_image=cv2.cvtColor(numpy_image, cv2.COLOR_RGB2BGR) 

To convert from OpenCV image to PIL image use:

import cv2
import numpy as np
from PIL import Image

opencv_image=cv2.imread("demo2.jpg") # open image using openCV2

# convert from openCV2 to PIL. Notice the COLOR_BGR2RGB which means that 
# the color is converted from BGR to RGB
color_coverted = cv2.cvtColor(opencv_image, cv2.COLOR_BGR2RGB)
pil_image=Image.fromarray(color_coverted)

Solution 3 - Python

Here are two functions to convert image between PIL and OpenCV:

def toImgOpenCV(imgPIL): # Conver imgPIL to imgOpenCV
    i = np.array(imgPIL) # After mapping from PIL to numpy : [R,G,B,A]
                         # numpy Image Channel system: [B,G,R,A]
    red = i[:,:,0].copy(); i[:,:,0] = i[:,:,2].copy(); i[:,:,2] = red;
    return i; 

def toImgPIL(imgOpenCV): return Image.fromarray(cv2.cvtColor(imgOpenCV, cv2.COLOR_BGR2RGB));

Convert from OpenCV img to PIL img will lost transparent channel. While convert PIL img to OpenCV img will able to keep transparent channel, although cv2.imshow not display it but save as png will gave result normally.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionArsenal FanaticView Question on Stackoverflow
Solution 1 - PythonZdaRView Answer on Stackoverflow
Solution 2 - Pythonalpha_989View Answer on Stackoverflow
Solution 3 - PythonphnghueView Answer on Stackoverflow