3

I found the previous answer related to a more general conversion from RGB image here: Convert image from PIL to openCV format

I would like to know the difference when an image has to be read as a grayscale format.

images = [None, None]

images[0] = Image.open('image1')
images[1] = Image.open('image2')

print(type(images[0]))

a = np.array(images[0])
b = np.array(images[1])

print(type(a))

im_template = cv2.imread(a, 0)
im_source = cv2.imread(b, 0)

I get the following output:

<class 'PIL.JpegImagePlugin.JpegImageFile'>
<class 'numpy.ndarray'>

Even though I am able to convert the image to ndarray, cv2 says: "bad argument type for built-in operation". I do not need an RGB to BGR conversion. What else should I consider while passing a cv2 read argument?

ABK
  • 145
  • 1
  • 14
  • The first argument you sent to imread must be a string. Imread only open image from file. In python there is no OpenCV data type for manage the images, there is for some algorithms, but not for the image themself. Once you have converted your data to an numpy.ndarray every OpenCV function should work with it. – John_Sharp1318 Mar 06 '19 at 16:51
  • I found this really helpful: "To use an OpenCV function, it is not really necessary to read it using Imread". So if I may, is it then valid to use all ndarrays as such to do the openCV functions such as filters? without detailed knowledge, I was under the impression that openCV reads images in BGR format (although my aim is to use it with grayscale) and PIL in RGB. Is this not going to create a colour mismatch later on? – ABK Mar 07 '19 at 09:03

2 Answers2

4

You are making life unnecessarily difficult for yourself. If you want to load an image as greyscale, and use it with OpenCV, you should just do:

im = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)

and that's all. No need to use PIL (which is slower), no need to use cvtColor() because you have already wasted all the memory reading it in BGR anyway.

If you absolutely want to read it using PIL (for some odd reason), use:

import numpy as np
from PIL import Image

# Read in and make greyscale
PILim = Image.open('image.jpg').convert('L')

# Make Numpy/OpenCV-compatible version
openCVim = np.array(PILim)

By the way, if you want to go back to a PIL image from an OpenCV/Numpy image, use:

PILim = Image.fromarray(openCVim)
Mark Setchell
  • 191,897
  • 31
  • 273
  • 432
  • I do not know if this is an odd reason, but the functions that I need to use on my images are spread between PIL, OpenCV, QtGui and numpy. Therefore I could not see any alternative option. I am trying to minimise the conversions since some of them like getdata() to convert the images into an array are even slower. – ABK Mar 07 '19 at 09:19
  • and as a follow up que, do you think the additional conversions can affect the image quality in anyway? for example if I need to convert a QImage into an openCV acceptable array. – ABK Mar 07 '19 at 09:22
  • 1
    As long as you don't needlessly encode/decode via any lossy formats such as JPEG (after initial load obviously) the quality should be retained. – Mark Setchell Mar 07 '19 at 09:40
2

Since you already have loaded the image, you should use an image conversion function:

im_template = cv2.cvtColor(a, cv2.COLOR_RGB2GRAY)
im_source = cv2.cvtColor(b, cv2.COLOR_RGB2GRAY)
Pärt Johanson
  • 1,570
  • 1
  • 13
  • 13