95

As I'm lead to believe, OpenCV reads images in BGR colorspace ordering and we usually have to convert it back to RGB like this:

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

But when I try to simply read an image and show it, the coloring seems fine (without the need to convert BGR to RGB):

img_bgr = cv2.imread(image_path)
cv2.imshow('BGR Image',img_bgr)
img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
cv2.imshow('RGB Image',img_rgb )
cv2.waitkey(0)

So is imshow() changing the ordering within the function automatically (from BGR to RGB) or the ordering has been BGR all along?

desertnaut
  • 57,590
  • 26
  • 140
  • 166
Cypher
  • 2,374
  • 4
  • 24
  • 36
  • 3
    You only need to convert from BGR to RGB when going to/from OpenCV and other tools that use RGB ordering. OpenCV is somewhat of the oddball. Most other tools and formats are in RGB order. When saving from OpenCV to standard image formats, OpenCV does the conversion automatically. But when going back and forth to matplotlib or PIL or skimage, you may need to convert to RGB format first depending upon the things you want to do in those other packages and whether you intend to come back to OpenCV. – fmw42 Nov 30 '21 at 00:31

6 Answers6

107

BGR and RGB are not color spaces, they are just conventions for the order of the different color channels. cv2.cvtColor(img, cv2.COLOR_BGR2RGB) doesn't do any computations (like a conversion to say HSV would), it just switches around the order. Any ordering would be valid - in reality, the three values (red, green and blue) are stacked to form one pixel. You can arrange them any way you like, as long as you tell the display what order you gave it.

OpenCV imread, imwrite and imshow indeed all work with the BGR order, so there is no need to change the order when you read an image with cv2.imread and then want to show it with cv2.imshow.

While BGR is used consistently throughout OpenCV, most other image processing libraries use the RGB ordering. If you want to use matplotlib's imshow but read the image with OpenCV, you would need to convert from BGR to RGB.

w-m
  • 10,772
  • 1
  • 42
  • 49
  • 5
    [Aside: Of course if you wanted to use `matplotlib`'s `imshow`, you would need to convert..] – jtlz2 Jan 10 '19 at 11:40
  • I did an experiment: I used only Open cv to imread and imshow but used image=cv2.cvtColor(image,cv2.COLOR_BGR2RGB) The image turned to blue(BGR).I cannot understand! Can aybody explain?? – THEODOROPOULOS DIMITRIS Nov 24 '20 at 11:57
  • 1
    Any ordering is technically valid, but I have never encountered any other software library that uses BGR and not RGB. Yet another way OpenCV has a terrible API. – qwr Feb 26 '22 at 20:09
  • A caveat: imread from OpenCV.js through HTML canvas is RGB and not BGR. – JustAMartin Nov 29 '22 at 09:30
19
screen = cv2.cvtColor(screen, cv2.COLOR_RGB2BGR)

this one line code changes rgb to bgr

Satyam Singh
  • 349
  • 3
  • 4
9

for matplotlib we need to change BGR to RGB:

img = cv2.imread("image_name")
img = img[...,::-1]

plt.imshow(img)
Ivan M.
  • 497
  • 6
  • 8
2
opencv_image_with_bgr_channels = cv2.imread('path/to/color_image.jpg')

matplotlib_compatible_image_with_rgb_channels = opencv_image_with_bgr_channels[:,:, ::-1]

This converts BGR to RGB Channels Image by reversing the channels.

Prasad
  • 1,028
  • 1
  • 11
  • 22
-1

If you do not need to use any other Image processing library (example Matplotlib's imshow), there is no need to do color scale conversion. Below code is an example, where the color scale conversion is done but when the image is loaded, it is still loaded in BGR. This conversion is not needed as the image is displayed using cv2.imshow().

import cv2

# read the image #
image = cv2.imread('<<Image Path>>')
                
image_rgb = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)

# write a function to draw circles on the image #
def draw_circle(event,x,y,flags,params):
    if event == cv2.EVENT_RBUTTONDOWN:
        cv2.circle(img=image_rgb,center=(x,y),radius=100,color=(0,0,255),thickness=10)

# Open CV callbacks #
cv2.namedWindow(winname='ImageWindow')
cv2.setMouseCallback('ImageWindow',draw_circle)

# display the image till the user hits the ESC key #
while True:
    cv2.imshow('ImageWindow',image_rgb)
    if cv2.waitKey(20) & 0xFF == 27:
        break
        
cv2.destroyAllWindows()

Praks
  • 67
  • 1
  • 1
  • 4
-3

Alternatively, you can use imutils.opencv2matplotlib() function, which does not need BGR to RGB conversion.