123

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

svec
  • 3,477
  • 2
  • 27
  • 28
gabbar0x
  • 4,046
  • 5
  • 31
  • 51

7 Answers7

243

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.

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
TobyD
  • 2,614
  • 1
  • 9
  • 6
  • 15
    You can also use it in one line when you read the file `img = cv2.imread('lena_caption.png', cv2.COLOR_BGR2RGB)` – Spiral Out May 05 '19 at 14:51
  • 5
    @SpiralOut this doesn't seem to work anymore; the documentation also doesn't mention COLOR_BGR2RGB as a possible flag https://docs.opencv.org/3.4/d8/d6a/group__imgcodecs__flags.html#ga61d9b0126a3e57d9277ac48327799c80 – Alexander Chebykin Sep 15 '21 at 09:30
28

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)

okk
  • 420
  • 5
  • 7
  • 9
    NO. And this is why: https://answers.opencv.org/question/219040/fastest-way-to-convert-bgr-rgb-aka-do-not-use-numpy-magic-tricks/ – baldr Oct 05 '19 at 16:38
  • 2
    Could you please explain how is it different from ```RGB_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)``` – Avinash Singh Apr 17 '20 at 04:23
  • @AvinashSingh. `BGR` means that 0 dimension is blue color, 1 - green, 2 - red, but `RGB` is red green blue, reversed order – Demetry Pascal Oct 15 '21 at 10:16
16

Simple one-line solution

np.flip(img, axis=-1) 

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

3

If you are using PyCharm in dark mode you will find out that changing from BGR to RGB is not enough. This is because PyCharm has a setting called "Invert image outputs for dark themes"

Disabling Preferences | Languages & Frameworks | Jupyter | Invert image outputs for dark themes should help

Invert image is ON: Invert image is ON

Invert image is OFF: Invert image is OFF

Please note that the code is the same in both examples. Only the setting in PyCharm is different.

dc914337
  • 415
  • 4
  • 14
2

after reading the image, reverting the order of bgr matrix to rgb by reading the matrix from right to left:

x = cv2.imread('./image.jpg')

x=x[:,:,::-1]

plt.imshow(x)
1

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

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
Jaied
  • 900
  • 9
  • 13
1

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/

BV2K
  • 11
  • 1