返回目录
OpenCV提供了一系列的颜色空间转换模型
1. 颜色空间转换cv2.cvtColor
import cv2
import numpy as np
import matplotlib.pyplot as plt
img_file = './monarch.png'
# 1. Color space conversion with cv2.cvtColor
bgr = cv2.imread(img_file, cv2.IMREAD_UNCHANGED)
# BGR to RGB
rgb = cv2.cvtColor(bgr, cv2.COLOR_BGR2RGB)
# BGR to HSV
hsv = cv2.cvtColor(rgb, cv2.COLOR_BGR2HSV)
# BGR to GRAY scale
gray = cv2.cvtColor(rgb, cv2.COLOR_RGB2GRAY)
# Gray to binary
_, binary = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY)
fig1 = plt.figure('Color space conversion', figsize=(5,4))
plt.subplot(231), plt.imshow(bgr), plt.title('BGR'), plt.axis('off')
plt.subplot(232), plt.imshow(rgb), plt.title('RGB'), plt.axis('off')
plt.subplot(233), plt.imshow(hsv), plt.title('HSV'), plt.axis('off')
plt.subplot(234), plt.imshow(gray, cmap='gray'), plt.title('Gray'), plt.axis('off')
plt.subplot(235), plt.imshow(binary, cmap='gray'), plt.title('Binary'), plt.axis('off')
plt.show()
2. 图像读取时选择颜色空间cv2.imread
import cv2
import numpy as np
import matplotlib.pyplot as plt
img_file = './monarch.png'
# 2. Selecting color space when reading an image
# BGR format, rgb obtained with cv2 is in fact BGR format
bgr = cv2.imread(img_file, cv2.IMREAD_COLOR)
gray = cv2.imread(img_file, cv2.IMREAD_GRAYSCALE)
fig1 = plt.figure('Selecting color space when reading')
plt.subplot(121), plt.imshow(bgr), plt.title('BGR'), plt.axis('off')
plt.subplot(122), plt.imshow(gray, cmap='gray'), plt.title('Gray'), plt.axis('off')
plt.show()
3. RGB <==> HSI
3.1 RGB2HSI
# Covert RGB format to HSI format
def rgb2hsi(rgb):
"rgb is from cv2, therefore it is in fact BGR format"
img_rgb = rgb.astype(np.float32).copy()/255.0
B,G,R = cv2.split(img_rgb)
I = (R+G+B)/3.0
S = np.where((R+G+B) > 0, 1-3*np.minimum(np.minimum(R,G), B)/(R+G+B), 0)
den = 2*np.sqrt((R-G)**2+(R-B)*(G-B))
theta = np.where(den>0, np.arccos((2*R-B-G)/den), 0)
theta /= (2*np.pi)
H = np.where(B<=G, theta, 1-theta)
img_hsi = np.zeros(rgb.shape)
img_hsi[:,:,0] = H*255
img_hsi[:,:,1] = S*255
img_hsi[:,:,2] = I*255
img_hsi = np.array(img_hsi).astype(np.uint8)
return img_hsi
3.2 HSI2RGB
# Covert HSI format to RGB format
def hsi2rgb(hsi):
"The obtained rgb is in fact BGR format"
img_hsi = hsi.astype(np.float32).copy()/255.0
H,S,I = cv2.split(img_hsi)
B,G,R = cv2.split(np.zeros(img_hsi.shape))
H *= 2*np.pi
# 1. handle the case when H>=0 and H<2*np.pi/3
H_mask = np.logical_and(H>=0, H<2*np.pi/3)
tmp = np.cos(np.pi / 3 - H)
b = I * (1 - S)
r = np.where(tmp>0, I*(1+S*np.cos(H)/tmp), 0)
g = 3*I-r-b
R[H_mask] = r[H_mask]
G[H_mask] = g[H_mask]
B[H_mask] = b[H_mask]
# 2. handle the case when H>=2*np.pi/3 and H<2*2*np.pi/3
H_mask = np.logical_and(H>=2*np.pi/3, H<4*np.pi/3)
tmp = np.cos(np.pi - H)
r = I * (1 - S)
g = np.where(tmp>0, I*(1+S*np.cos(H-2*np.pi/3)/tmp), 0)
b = 3*I-r-g
R[H_mask] = r[H_mask]
G[H_mask] = g[H_mask]
B[H_mask] = b[H_mask]
# 3. handle the case when H>=2*2*np.pi/3 and H<3*2*np.pi/3
H_mask = np.logical_and(H>=4*np.pi/3, H<=2*np.pi)
tmp = np.cos(5 * np.pi / 3 - H)
g = I * (1 - S)
b = np.where(tmp>0, I*(1+S*np.cos(H-4*np.pi/3)/tmp), 0)
r = 3*I-g-b
R[H_mask] = r[H_mask]
G[H_mask] = g[H_mask]
B[H_mask] = b[H_mask]
img_rgb = np.zeros(img_hsi.shape)
img_rgb[:,:,0] = B*255
img_rgb[:,:,1] = G*255
img_rgb[:,:,2] = R*255
img_rgb = img_rgb.astype(np.uint8)
return img_rgb
3.3 颜色空间转换例子
import cv2
import numpy as np
import matplotlib.pyplot as plt
img_file = './monarch.png'
hsi = rgb2hsi(rgb)
rgb_r = hsi2rgb(hsi)
3.4 改变饱和度
# Modifying the color saturation
fig1 = plt.figure('Varing the saturation')
plt.subplot(221), plt.imshow(rgb), plt.title('RGB'), plt.axis('off')
hsi1 = hsi
hsi1[:,:,1] = hsi1[:,:,1]>>1
plt.subplot(222), plt.imshow(hsi2rgb(hsi1)), plt.title('RGB S/2'), plt.axis('off')
hsi1 = hsi
hsi1[:,:,1] = hsi1[:,:,1]>>2
plt.subplot(223), plt.imshow(hsi2rgb(hsi1)), plt.title('RGB S/4'), plt.axis('off')
hsi1 = hsi
hsi1[:,:,1] = hsi1[:,:,1]>>4
plt.subplot(224), plt.imshow(hsi2rgb(hsi1)), plt.title('RGB S/16'), plt.axis('off')
plt.show()
3.5 两张图像颜色通道互换
两张图像 lenna.bmp 和 baboon.bmp,完成如下两个任务:
lenna.bmp: http://pan-yz.chaoxing.com/share/info/b01e77ea99e70163
Baboon: http://pan-yz.chaoxing.com/share/info/da0e567a5ae20718
(1) 把Lena的B分量替换为Baboon的B分离,显示替换B分量后的Lena图像。
import cv2
import numpy as np
import matplotlib.pyplot as plt
bgr_lenna = cv2.imread('./lenna.bmp', cv2.IMREAD_COLOR)
bgr_baboon = cv2.imread('./baboon.bmp', cv2.IMREAD_COLOR)
hsi_lenna = rgb2hsi(bgr_lenna)
hsi_baboon = rgb2hsi(bgr_baboon)
rgb_lenna = cv2.cvtColor(bgr_lenna, cv2.COLOR_BGR2RGB)
rgb_baboon = cv2.cvtColor(bgr_baboon, cv2.COLOR_BGR2RGB)
fig = plt.figure('Switching channel B', figsize=(4,5))
plt.subplot(121), plt.imshow(rgb_lenna), plt.title('Before'), plt.axis('off')
rgb_lenna[:,:, 2] = rgb_baboon[:,:, 2]
plt.subplot(122), plt.imshow(rgb_lenna), plt.title('After'), plt.axis('off')
plt.show()
(2) 把Lena的S分量替换为Baboon的S分离,由HSI空间转回RGB空间后,显示替换S分量后的Lena图像。
import cv2
import numpy as np
import matplotlib.pyplot as plt
bgr_lenna = cv2.imread('./lenna.bmp', cv2.IMREAD_COLOR)
bgr_baboon = cv2.imread('./baboon.bmp', cv2.IMREAD_COLOR)
hsi_lenna = rgb2hsi(bgr_lenna)
hsi_baboon = rgb2hsi(bgr_baboon)
rgb_lenna = cv2.cvtColor(bgr_lenna, cv2.COLOR_BGR2RGB)
rgb_baboon = cv2.cvtColor(bgr_baboon, cv2.COLOR_BGR2RGB)
fig = plt.figure('Switching channel B', figsize=(6,5))
plt.subplot(131), plt.imshow(rgb_lenna), plt.title('B: Before'), plt.axis('off')
rgb_lenna[:,:, 2] = rgb_baboon[:,:, 2]
plt.subplot(132), plt.imshow(rgb_lenna), plt.title('B: After'), plt.axis('off')
hsi_lenna[:,:, 1] = hsi_baboon[:,:, 1]
bgr_lenna_new = hsi_bgr.rgb2hsi(hsi_lenna)
rgb_lenna_new = hsi_bgr.hsi2rgb(bgr_lenna_new)
plt.subplot(133), plt.imshow(rgb_lenna_new), plt.title('S: After'), plt.axis('off')
plt.show()
返回目录