颜色空间的转换
CMY 空间
CMY 颜色空间正好与 RGB 颜色空间互补, 即用白色减去 RGB 颜色空间中的某一颜色值就等于这种颜色在 CMY 颜色空间中的值。
{ C = 1 − R M = 1 − G Y = 1 − B \begin{cases}C=1-R\\M=1-G\\Y=1-B\end{cases} ⎩ ⎨ ⎧C=1−RM=1−GY=1−B
HSV 空间
HSI/ HSV 颜色空间模型是从人的视觉系统出发, 用 H (Hue)、 S(Saturation)、 I(Intensity) 或 V(Value) 分别代表色调、 色饱和度、 亮度三种独立的颜色特征。
对于[0,1]的 R、G、B 值,HSV 各个分量计算如下
V = R + G + B 3 V=\frac{R+G+B}{3} V=3R+G+B
S = 1 − 3 R + G + B min ( R , G , B ) S=1-\frac{3}{R+G+B}\min(R,G,B) S=1−R+G+B3min(R,G,B)
H
=
{
θ
,
B
≤
G
36
0
∘
−
θ
,
B
>
G
H=\begin{cases}\theta,&B\le G\\360^\circ-\theta,&B>G\end{cases}
H={θ,360∘−θ,B≤GB>G
其中
θ
=
arccos
{
(
R
−
G
)
+
(
R
−
B
)
2
[
(
R
−
G
)
2
+
(
R
−
B
)
(
G
−
B
)
]
1
2
}
\theta=\arccos\left\{\frac{(R-G)+(R-B)}{2\Big[(R-G)^2+(R-B)(G-B)\Big]^{\frac{1}{2}}}\right\}
θ=arccos⎩
⎨
⎧2[(R−G)2+(R−B)(G−B)]21(R−G)+(R−B)⎭
⎬
⎫
YCbCr 空间
YCbCr 颜色空间采用一个亮度信号 (Y) 和两个色差信号 (Cb , Cr ) 来表示。
对于[0,1]的 R、G、B,Y、Cr、Cb 计算如下:
[ Y C r C b ] = [ 0.2990 0.5870 0.1140 0.5000 − 0.4187 − 0.0813 − 0.1687 − 0.3313 0.5000 ] [ R G B ] + [ 6 128 128 ] \begin{bmatrix}Y\\C_\mathrm{r}\\C_\mathrm{b}\end{bmatrix}=\begin{bmatrix}0.2990&0.5870&0.1140\\0.5000&-0.4187&-0.0813\\-0.1687&-0.3313&0.5000\end{bmatrix}\begin{bmatrix}R\\G\\B\end{bmatrix}+\begin{bmatrix}6\\128\\128\end{bmatrix} YCrCb = 0.29900.5000−0.16870.5870−0.4187−0.33130.1140−0.08130.5000 RGB + 6128128
import cv2
import numpy as np
import matplotlib.pyplot as plt
def read_show_image(img, flag=0):
img = np.squeeze(img)
if np.ndim(img) == 2:
plt.imshow(img, 'gray'), plt.title('灰度图'), plt.xticks([]), plt.yticks([])
plt.show()
elif np.ndim(img) == 3:
R = img[..., 0]
G = img[..., 1]
B = img[..., 2]
if flag == 1:
plt.subplot(221), plt.imshow(img, 'gray'), plt.title('彩色图'), plt.xticks([]), plt.yticks([])
plt.subplot(222), plt.imshow(R, 'gray'), plt.title('通道1'), plt.xticks([]), plt.yticks([])
plt.subplot(223), plt.imshow(G, 'gray'), plt.title('通道2'), plt.xticks([]), plt.yticks([])
plt.subplot(224), plt.imshow(B, 'gray'), plt.title('通道3'), plt.xticks([]), plt.yticks([])
plt.show()
else:
zeros = np.zeros(img.shape[:2], dtype='uint8')
plt.subplot(221), plt.imshow(img), plt.title('彩色图'), plt.xticks([]), plt.yticks([])
plt.subplot(222), plt.imshow(cv2.merge([R, zeros, zeros])), plt.title('通道1'), plt.xticks([]), plt.yticks([])
plt.subplot(223), plt.imshow(cv2.merge([zeros, G, zeros])), plt.title('通道2'), plt.xticks([]), plt.yticks([])
plt.subplot(224), plt.imshow(cv2.merge([zeros, zeros, B])), plt.title('通道3'), plt.xticks([]), plt.yticks([])
plt.show()
else:
print('Input error')
def RGB2CMY(img):
'''青 (Cyan)、 品红(Magenta) 和黄 (Yellow)'''
r, g, b = cv2.split(img) # split the channels
# normalization [0,1]
r = r / 255.0
g = g / 255.0
b = b / 255.0
c = 1 - r
m = 1 - g
y = 1 - b
result = cv2.merge((c, m, y))* 255 # merge the channels
return np.array(result).astype(np.uint8)
def RGB2HSV(rgb_Img):
''' 用 H(Hue)、 S(Saturation)、 I(Intensity) 或 V(Value) 分别代表色调、 色饱和度、 亮度'''
img_rows = int(rgb_Img.shape[0])
img_cols = int(rgb_Img.shape[1])
b, g, r = cv2.split(rgb_Img)
# normalization[0,1]
r = r / 255.0
g = g / 255.0
b = b / 255.0
hsv_Img = rgb_Img.copy()
for i in range(img_rows):
for j in range(img_cols):
num = 0.5 * ((r[i, j] - g[i, j]) + (r[i, j] - b[i, j]))
den = np.sqrt((r[i, j] - g[i, j]) ** 2 + (r[i, j] - b[i, j]) * (g[i, j] - b[i, j]))
theta = float(np.arccos(num / den))
if den == 0:
H = 0
elif b[i, j] <= g[i, j]:
H = theta
else:
H = np.pi - theta
min_RGB = min(min(b[i, j], g[i, j]), r[i, j])
sum = b[i, j] + g[i, j] + r[i, j]
if sum == 0:
S = 0
else:
S = 1 - 3 * min_RGB / sum
H = H / (np.pi)
V = sum / 3.0
# 输出HSI图像,扩充到255以方便显示,一般H分量在[0,2pi]之间,S和I在[0,1]之间
hsv_Img[i, j, 0] = H * 255
hsv_Img[i, j, 1] = S * 255
hsv_Img[i, j, 2] = V * 255
return hsv_Img
def RGB2YCbCr(rgb_image):
"""Y:亮度 Cb:色差 Cr:色差"""
if len(rgb_image.shape) != 3 or rgb_image.shape[2] != 3:
raise ValueError("input image is not a rgb image")
rgb_image = rgb_image.astype(np.float32)
transform_matrix = np.array([[0.299, 0.587, 0.114],
[0.5, 0.4187, -0.0813],
[-0.1687, -0.3313, 0.5]])
shift_matrix = np.array([16, 128, 128])
ycbcr_image = np.zeros(shape=rgb_image.shape)
w, h, _ = rgb_image.shape
for i in range(w):
for j in range(h):
ycbcr_image[i, j, :] = np.dot(transform_matrix, rgb_image[i, j, :]) + shift_matrix
return np.array(ycbcr_image).astype(np.uint8)
if __name__ == '__main__':
lena = cv2.imread('lena_std.bmp')
lena = np.array(lena)[..., ::-1]
cmy = RGB2CMY(lena)
hsv = RGB2HSV(lena)
ycbcr = RGB2YCbCr(lena)
plt.figure('RGB')
read_show_image(lena)
plt.figure('cmy')
read_show_image(cmy)
plt.figure('hsv')
read_show_image(hsv,flag=1)
plt.figure('ycbcr')
read_show_image(ycbcr,flag=1)
参考:
https://cloud.tencent.com/developer/article/1784017