RGB vs BGR

使用 np.array 创建一张 255×255 的 RGB 值为 [255, 0, 0] 的红色图像,类型为 np.ndarray。使用 cv2.imwrite 方法保存这张图片为 red.png,在本地 red.png 显示为蓝色,它的 RGB 值为 [0, 0, 255]。再使用 cv2.imread 方法读取这张图片,得到的新图像的 RGB 值为 [255, 0, 0]。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import cv2
import numpy as np

color = np.array([255, 0, 0]) # R:255, G:0, B:0 -> Red
image = np.ones(shape=[255, 255, 1], dtype=np.uint8) * color.reshape([1, 1, -1])
print(f"image.shape: {image.shape}")
# image.shape: (255, 255, 3)

cv2.imwrite(filename="red.png", img=image)
# red.png is blue, its color is [0, 0, 255]

image = cv2.imread(filename="red.png")
print(f"RGB: {image[0][0]}")
# RGB: [255 0 0]

这表示使用 cv2.imwrite 方法保存图片时,cv2 将传入的 img 理解成 BGR 图像并保存成 RGB 图像。而使用 cv2.imread 方法读取图片时,cv2 将传入的图像理解成 RGB 图像,并转换成 BGR 图像。

1
2
3
4
RGBA -cv2.imread()-> BGRA
BGRA -cv2.imread()-> RGBA
RGBA -cv2.imwrite()-> BGRA
BGRA -cv2.imwrite()-> RGBA

其实 cv2 本身不能根据图片的通道信息知道图片的通道顺序是 RGB 还是 BGR,它默认本地中图片的顺序是 RGB 的,读取到内存中的图片的通道顺序是 BGR 的,所以 cv2.imread/cv2.imwrite 都会将传入的图像的第0个通道和第2个通道进行交换。同时我们也可以通过 cv2 提供的方法进行手动转换

1
2
3
4
image = cv2.imread(path2image, cv2.IMREAD_UNCHANGED) # RGB -> BGR
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # BGR -> RGB
mask = cv2.imread(path2mask, cv2.IMREAD_UNCHANGED) # RGBA -> BGRA
mask = cv2.cvtColor(mask, cv2.COLOR_BGRA2RGBA) # BGRA -> RGBA