Skip to content

Python OpenCV: How to Convert BGR to RGB with OpenCV in Python

Learn how to properly convert BGR images (OpenCV's default format) to RGB for compatibility with Matplotlib, PIL/Pillow, and other libraries using cv2.cvtColor() or NumPy slicing.

OpenCV reads images in BGR (Blue-Green-Red) order, while most other libraries like Matplotlib and PIL expect RGB (Red-Green-Blue). Understanding this difference is crucial for correct image display and processing.

The safest and most readable approach uses OpenCV's color conversion function:

import cv2

img_bgr = cv2.imread('photo.jpg')

img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)

Why BGR?

OpenCV uses BGR for historical reasons-early camera manufacturers and the Windows bitmap format used this ordering. Most modern libraries standardized on RGB, creating the need for conversion.

Using NumPy Slicing - Fast

Reverse the color channel axis directly:

import cv2
import numpy as np

img_bgr = cv2.imread('photo.jpg')

img_rgb = img_bgr[:, :, ::-1]

Understanding the Slice

import numpy as np


img_bgr = np.array([[[255, 0, 0]]])  # Pure blue in BGR
print(f"BGR: {img_bgr[0, 0]}")  # [255, 0, 0]

img_rgb = img_bgr[:, :, ::-1]
print(f"RGB: {img_rgb[0, 0]}")  # [0, 0, 255] - Pure blue in RGB

Matplotlib Compatibility

Matplotlib expects RGB, so always convert before displaying:

import cv2
import matplotlib.pyplot as plt

img = cv2.imread('photo.jpg')

fig, axes = plt.subplots(1, 2, figsize=(10, 5))

axes[0].imshow(img)
axes[0].set_title('Wrong: BGR in Matplotlib')

axes[1].imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
axes[1].set_title('Correct: Converted to RGB')

plt.show()

Converting Back: RGB to BGR

When passing images back to OpenCV functions:

import cv2
from PIL import Image
import numpy as np

pil_image = Image.open('photo.jpg')
img_rgb = np.array(pil_image)

img_bgr = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2BGR)

gray = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY)
cv2.imwrite('output.jpg', img_bgr)

Working with PIL/Pillow

import cv2
from PIL import Image
import numpy as np

img_bgr = cv2.imread('photo.jpg')
img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
pil_image = Image.fromarray(img_rgb)

pil_image = Image.open('photo.jpg')
img_rgb = np.array(pil_image)
img_bgr = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2BGR)

When NOT to Convert

OpenCV's own display function expects BGR:

import cv2

img = cv2.imread('photo.jpg')

cv2.imshow('Image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

cv2.imwrite('output.jpg', img)

Common Color Conversion Constants

Conversion Constant
BGR → RGB cv2.COLOR_BGR2RGB
RGB → BGR cv2.COLOR_RGB2BGR
BGR → Grayscale cv2.COLOR_BGR2GRAY
RGB → Grayscale cv2.COLOR_RGB2GRAY
BGR → HSV cv2.COLOR_BGR2HSV
BGR → LAB cv2.COLOR_BGR2LAB

Performance Comparison

import cv2
import numpy as np
import timeit

img = np.random.randint(0, 256, (1080, 1920, 3), dtype=np.uint8)

def cvtcolor_method():
    return cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

def numpy_method():
    return img[:, :, ::-1]

def numpy_copy_method():
    return img[:, :, ::-1].copy()

print(f"cv2.cvtColor: {timeit.timeit(cvtcolor_method, number=1000):.4f}s")
print(f"NumPy slice:  {timeit.timeit(numpy_method, number=1000):.4f}s")
print(f"NumPy copy:   {timeit.timeit(numpy_copy_method, number=1000):.4f}s")

Typical output:

cv2.cvtColor: 0.8234s
NumPy slice:  0.0003s
NumPy copy:   0.4521s

Practical Example: Complete Pipeline

import cv2
import matplotlib.pyplot as plt
import numpy as np

def process_and_display(image_path):
    """Load, process, and display an image correctly."""
    
    img_bgr = cv2.imread(image_path)
    
    if img_bgr is None:
        raise FileNotFoundError(f"Could not load {image_path}")
    
    blurred = cv2.GaussianBlur(img_bgr, (5, 5), 0)
    edges = cv2.Canny(blurred, 50, 150)
    
    img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
    blurred_rgb = cv2.cvtColor(blurred, cv2.COLOR_BGR2RGB)
    
    fig, axes = plt.subplots(1, 3, figsize=(12, 4))
    axes[0].imshow(img_rgb)
    axes[0].set_title('Original')
    axes[1].imshow(blurred_rgb)
    axes[1].set_title('Blurred')
    axes[2].imshow(edges, cmap='gray')
    axes[2].set_title('Edges')
    plt.show()

process_and_display('photo.jpg')

Summary

Scenario Action
OpenCV → Matplotlib/PIL Convert BGR to RGB
Matplotlib/PIL → OpenCV Convert RGB to BGR
OpenCV → OpenCV No conversion needed
Maximum speed Use img[:, :, ::-1]
Maximum clarity Use cv2.cvtColor()
  • Use cv2.cvtColor(img, cv2.COLOR_BGR2RGB) for explicit, readable conversions.
  • Use img[:, :, ::-1] when speed is critical in array-only pipelines.

Remember that OpenCV's own functions (imshow, imwrite) expect BGR, only convert when interfacing with external libraries.

Navigation