gpt4 book ai didi

python - 无法显示图像 HSI 转换为 RGB python

转载 作者:太空宇宙 更新时间:2023-11-03 21:50:17 24 4
gpt4 key购买 nike

我一直在研究一种算法,在 python 3 中将 RGB 转换为 HSI,反之亦然,它使用 matplotlib 显示结果图像和每个 channel 。

问题是显示 HSI 到 RGB 结果图像:每个 channel 单独显示正确,但当它同时显示树 channel 时,我得到一个奇怪的图像。

顺便说一句,当我用 OpenCV 保存生成的图像时,它会正确显示图像。

Resulted display

我做了什么,但没有任何改变:

  • 对值进行四舍五入,如果超过 1,则将 1 赋给像素

  • 在 HSI 到 RGB 的转换中,用零定义 R、G 和 B 数组,用 1 定义数组

  • 在RGB转HSI中,将[0,360]、[0,1]、[0,1]之间的值改为[0,360]、[0,255]、[0,255]之间的值是否四舍五入

  • 改用 Jupyter notebook,使用 collab.research by google 或 Spider

  • 在终端上执行代码,但出现空白窗口

显示图片的函数:

def show_images(T, cols=1):
N = len(T)
fig = plt.figure()
for i in range(N):
a = fig.add_subplot(np.ceil(N/float(cols)), cols, i+1)
try:
img,title = T[i]
except ValueError:
img,title = T[i], "Image %d" % (i+1)
if(img.ndim == 2):
plt.gray()
plt.imshow(img)
a.set_title(title)
plt.xticks([0,img.shape[1]]), plt.yticks([0,img.shape[0]])
fig.set_size_inches(np.array(fig.get_size_inches()) * N)
plt.show()

然后主函数做这个:

image = bgr_to_rgb(cv2.imread("rgb.png"))

img1 = rgb_to_hsi(image)
img2 = hsi_to_rgb(img1)

show_images([(image,"RGB"),
(image[:,:,0],"Red"),
(image[:,:,1],"Green"),
(image[:,:,2],"Blue")], 4)
show_images([(img1,"RGB->HSI"),
(img1[:,:,0],"Hue"),
(img1[:,:,1],"Saturation"),
(img1[:,:,2],"Intensity")], 4)
show_images([(img2,"HSI->RGB"),
(img2[:,:,0],"Red"),
(img2[:,:,1],"Green"),
(img2[:,:,2],"Blue")], 4)

将 RGB 转换为 HSI:

def rgb_to_hsi(img):
zmax = 255 # max value
# values in [0,1]
R = np.divide(img[:,:,0],zmax,dtype=np.float)
G = np.divide(img[:,:,1],zmax,dtype=np.float)
B = np.divide(img[:,:,2],zmax,dtype=np.float)

# Hue, when R=G=B -> H=90
a = (0.5)*np.add(np.subtract(R,G), np.subtract(R,B)) # (1/2)*[(R-G)+(R-B)]
b = np.sqrt(np.add(np.power(np.subtract(R,G), 2) , np.multiply(np.subtract(R,B),np.subtract(G,B))))
tetha = np.arccos( np.divide(a, b, out=np.zeros_like(a), where=b!=0) ) # when b = 0, division returns 0, so then tetha = 90
H = (180/math.pi)*tetha # convert rad to degree
H[B>G]=360-H[B>G]

# saturation = 1 - 3*[min(R,G,B)]/(R+G+B), when R=G=B -> S=0
a = 3*np.minimum(np.minimum(R,G),B) # 3*min(R,G,B)
b = np.add(np.add(R,G),B) # (R+G+B)
S = np.subtract(1, np.divide(a,b,out=np.ones_like(a),where=b!=0))

# intensity = (1/3)*[R+G+B]
I = (1/3)*np.add(np.add(R,G),B)

return np.dstack((H, zmax*S, np.round(zmax*I))) # values between [0,360], [0,255] e [0,255]

将 HSI 转换为 RGB:

  def f1(I,S): # I(1-S)
return np.multiply(I, np.subtract(1,S))
def f2(I,S,H): # I[1+(ScosH/cos(60-H))]
r = math.pi/180
a = np.multiply(S, np.cos(r*H)) # ScosH
b = np.cos(r*np.subtract(60,H)) # cos(60-H)
return np.multiply(I, np.add(1, np.divide(a,b)) )
def f3(I,C1,C2): # 3I-(C1+C2)
return np.subtract(3*I, np.add(C1,C2))

def hsi_to_rgb(img):
zmax = 255 # max value
# values between[0,360], [0,1] and [0,1]
H = img[:,:,0]
S = np.divide(img[:,:,1],zmax,dtype=np.float)
I = np.divide(img[:,:,2],zmax,dtype=np.float)

R,G,B = np.ones(H.shape),np.ones(H.shape),np.ones(H.shape) # values will be between [0,1]
# for 0 <= H < 120
B[(0<=H)&(H<120)] = f1(I[(0<=H)&(H<120)], S[(0<=H)&(H<120)])
R[(0<=H)&(H<120)] = f2(I[(0<=H)&(H<120)], S[(0<=H)&(H<120)], H[(0<=H)&(H<120)])
G[(0<=H)&(H<120)] = f3(I[(0<=H)&(H<120)], R[(0<=H)&(H<120)], B[(0<=H)&(H<120)])

# for 120 <= H < 240
H = np.subtract(H,120)
R[(0<=H)&(H<120)] = f1(I[(0<=H)&(H<120)], S[(0<=H)&(H<120)])
G[(0<=H)&(H<120)] = f2(I[(0<=H)&(H<120)], S[(0<=H)&(H<120)], H[(0<=H)&(H<120)])
B[(0<=H)&(H<120)] = f3(I[(0<=H)&(H<120)], R[(0<=H)&(H<120)], G[(0<=H)&(H<120)])

# for 240 <= H < 360
H = np.subtract(H,120)
G[(0<=H)&(H<120)] = f1(I[(0<=H)&(H<120)], S[(0<=H)&(H<120)])
B[(0<=H)&(H<120)] = f2(I[(0<=H)&(H<120)], S[(0<=H)&(H<120)], H[(0<=H)&(H<120)])
R[(0<=H)&(H<120)] = f3(I[(0<=H)&(H<120)], G[(0<=H)&(H<120)], B[(0<=H)&(H<120)])

return np.dstack( ((zmax*R) , (zmax*G) , (zmax*B)) ) # values between [0,255]

最佳答案

如果你看一下 imshow documentation在 matplotlib 中,您将看到以下几行:

X : array-like or PIL image The image data. Supported array shapes are:

(M, N): an image with scalar data. The data is visualized using a colormap. (M, N, 3): an image with RGB values (float or uint8). (M, N, 4): an image with RGBA values (float or uint8), i.e. including transparency. The first two dimensions (M, N) define the rows and columns of the image.

The RGB(A) values should be in the range [0 .. 1] for floats or [0 .. 255] for integers. Out-of-range values will be clipped to these bounds.

它告诉您它应该处于的范围...在您的例子中,HSI 值在 Hue 中从 0-360 变化,高于它的任何值将被裁剪为 255。这就是 OpenCV 使用 0-180 的色调范围以使其适合该范围的原因之一。

然后HSI->RGB好像返回的是float的图片,然后1.0会被clip掉。

这只会发生在显示器上,但如果您保存图像,它很可能会被剪裁,可能会被保存为 16 位图像。

可能的解决方案:

  • 标准化 0-1 或 0-255 的值(这可能会改变最小值和最大值),然后显示它(不要忘记将其转换为 np.uint8)。

    <
  • 创建一个始终在可能值内的范围。

这是为了显示或保存目的...如果你使用 0-360 至少保存 16 位

关于python - 无法显示图像 HSI 转换为 RGB python,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52939362/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com