由于OpenCV没有内置的RGB和HSI颜色模型的转换,网上也很少python下的转换,所以分享下我写的。
RGB转HSI 的转换原理如下:
HSI转RGB的原理如下:
要注意的重点就是RGB原来是在[0,255]之间,通过上述转换为[0,1]之间的HSI颜色模型后,最后应该通过都乘上255扩张为[0,255]范围,以方便显示。HSI在转换回RGB时,也是需要先放缩到[0,1]间,然后R乘360,来计算RGB的值,结果再放大到[0,255]以方便显示。
还有一个需要注意的地方就是math库里的余弦函数cos(x)里的参数x是弧度表示的,所以对于角度y,我们需要通过y*math.pi/180来转换成对应弧度。
import cv2
import numpy as np
import math
def rgbtohsi(rgb_lwpImg):
rows = int(rgb_lwpImg.shape[0])
cols = int(rgb_lwpImg.shape[1])
B, G, R = cv2.split(rgb_lwpImg)
# 归一化到[0,1]
B = B / 255.0
G = G / 255.0
R = R / 255.0
hsi_lwpImg = rgb_lwpImg.copy()
H, S, I = cv2.split(hsi_lwpImg)
for i in range(rows):
for j in range(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 = 2 * 3.14169265 - 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 / (2 * 3.14159265)
I = sum / 3.0
# 输出HSI图像,扩充到255以方便显示,一般H分量在[0,2pi]之间,S和I在[0,1]之间
hsi_lwpImg[i, j, 0] = H * 255
hsi_lwpImg[i, j, 1] = S * 255
hsi_lwpImg[i, j, 2] = I * 255
return hsi_lwpImg
def hsitorgb(hsi_img):
h = int(hsi_img.shape[0])
w = int(hsi_img.shape[1])
H, S, I = cv2.split(hsi_img)
H = H / 255.0
S = S / 255.0
I = I / 255.0
bgr_img = hsi_img.copy()
B, G, R = cv2.split(bgr_img)
for i in range(h):
for j in range(w):
if S[i, j] < 1e-6:
R = I[i, j]
G = I[i, j]
B = I[i, j]
else:
H[i, j] *= 360
if H[i, j] > 0 and H[i, j] <= 120:
B = I[i, j] * (1 - S[i, j])
R = I[i, j] * (1 + (S[i, j] * math.cos(H[i, j]*math.pi/180)) / math.cos((60 - H[i, j])*math.pi/180))
G = 3 * I[i, j] - (R + B)
elif H[i, j] > 120 and H[i, j] <= 240:
H[i, j] = H[i, j] - 120
R = I[i, j] * (1 - S[i, j])
G = I[i, j] * (1 + (S[i, j] * math.cos(H[i, j]*math.pi/180)) / math.cos((60 - H[i, j])*math.pi/180))
B = 3 * I[i, j] - (R + G)
elif H[i, j] > 240 and H[i, j] <= 360:
H[i, j] = H[i, j] - 240
G = I[i, j] * (1 - S[i, j])
B = I[i, j] * (1 + (S[i, j] * math.cos(H[i, j]*math.pi/180)) / math.cos((60 - H[i, j])*math.pi/180))
R = 3 * I[i, j] - (G + B)
bgr_img[i, j, 0] = B * 255
bgr_img[i, j, 1] = G * 255
bgr_img[i, j, 2] = R * 255
return bgr_img
以下三幅图依次是原图像,转换成HSI下的图像,以及转换回rgb下的图像: