Python图像颜色空间

返回目录

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()
ColorSpace.png

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()
image.png

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()
Varing_the_saturation.png

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()
image.png

(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()
image.png

返回目录

你可能感兴趣的:(Python图像颜色空间)