OpenCV giving wrong color to colored images on loading

99,177

Solution 1

OpenCV uses BGR as its default colour order for images, matplotlib uses RGB. When you display an image loaded with OpenCv in matplotlib the channels will be back to front.

The easiest way of fixing this is to use OpenCV to explicitly convert it back to RGB, much like you do when creating the greyscale image.

RGB_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

And then use that in your plot.

Solution 2

As an alternative to the previous answer, you can use (slightly faster)

img = cv2.imread('lena_caption.png')[...,::-1]

%timeit [cv2.cvtColor(cv2.imread(f), cv2.COLOR_BGR2RGB) for f in files]
231 ms ± 3.08 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit [cv2.imread(f)[...,::-1] for f in files]
220 ms ± 1.81 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

Solution 3

Simple one-line solution

np.flip(img, axis=-1) 

This can convert both ways. From RGB to BGR, and from BGR to RGB.

Solution 4

You may also want to try cv2.IMREAD_UNCHANGED(). See more here to see how it differs from IMREAD_COLOR:

https://www.geeksforgeeks.org/python-opencv-cv2-imread-method/

Solution 5

If you try to read an image using OpenCV, it will use BGR as the default. So you have to use a different approach to read an Image. I have made the required changes to your code to get the desired output has been given below.

import cv2
import numpy as np
from numpy import array, arange, uint8 
from matplotlib import pyplot as plt


img = cv2.cvtColor(cv2.imread('lena_caption.png'), cv2.COLOR_BGR2RGB)
bw_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

images = []
images.append(img)
images.append(bw_img)

titles = ['Original Image','BW Image']

for i in xrange(len(images)):
    plt.subplot(1,2,i+1),plt.imshow(images[i],'gray')
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])

plt.show()

Output: enter image description here

Share:
99,177

Related videos on Youtube

gabbar0x
Author by

gabbar0x

Updated on January 09, 2022

Comments

  • gabbar0x
    gabbar0x over 2 years

    I'm loading in a color image in Python OpenCV and plotting the same. However, the image I get has it's colors all mixed up.

    Here is the code:

    import cv2
    import numpy as np
    from numpy import array, arange, uint8 
    from matplotlib import pyplot as plt
    
    
    img = cv2.imread('lena_caption.png', cv2.IMREAD_COLOR)
    bw_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
    images = []
    images.append(img)
    images.append(bw_img)
    
    titles = ['Original Image','BW Image']
    
    for i in xrange(len(images)):
        plt.subplot(1,2,i+1),plt.imshow(images[i],'gray')
        plt.title(titles[i])
        plt.xticks([]),plt.yticks([])
    
    plt.show()
    

    Here is the original image: enter image description here

    And here is the plotted image: enter image description here

  • Spiral Out
    Spiral Out about 5 years
    You can also use it in one line when you read the file img = cv2.imread('lena_caption.png', cv2.COLOR_BGR2RGB)
  • baldr
    baldr over 4 years
  • Avinash Singh
    Avinash Singh about 4 years
    Could you please explain how is it different from RGB_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
  • Alexander Chebykin
    Alexander Chebykin over 2 years
    @SpiralOut this doesn't seem to work anymore; the documentation also doesn't mention COLOR_BGR2RGB as a possible flag docs.opencv.org/3.4/d8/d6a/…
  • Demetry Pascal
    Demetry Pascal over 2 years
    @AvinashSingh. BGR means that 0 dimension is blue color, 1 - green, 2 - red, but RGB is red green blue, reversed order
  • Andrey
    Andrey over 2 years
    It's beautiful!
  • Salvatore Pannozzo Capodiferro
    Salvatore Pannozzo Capodiferro over 2 years
    confirmed, using cvtColor on image worked to me, while passing the parameter directly on the imread fucntion doesn't fix the issue
  • mochsner
    mochsner about 2 years
    Worked like a charm. For some reason the "chosen" answer is giving me trouble though.
  • mochsner
    mochsner about 2 years
    Is there a clever way to ensure that it's an RBG image, rather than a CV bitmap image? Seems this'll throw an error on CV bitmap images.