如何解决使用 PIL 而不是 imagio 库读取图像时,图像无法正确显示
import numpy as np
import imageio
from matplotlib import pyplot as plt
def RGB_TO_HSI(img):
with np.errstate(divide='ignore',invalid='ignore'):
rgb = np.float32(img) / 255
# Separate color channels
red = rgb[:,:,0]
green = rgb[:,1]
blue = rgb[:,2]
# Calculate Intensity
def calc_intensity(red,green,blue):
intensity = (red + green + blue + 0.001) / 3
return intensity
# Calculate Saturation
def calc_saturation(red,blue):
minimum = np.minimum(np.minimum(red,green),blue)
saturation = 1 - (minimum / calc_intensity(red,blue))
return saturation
# Calculate Hue
def calc_hue(red,blue):
hue = np.copy(red) # Basically have our hue = red for Now; we only need its size/dimensions
for i in range(0,blue.shape[0]):
for j in range(0,blue.shape[1]):
if blue[i][j] <= green[i][j]:
hue[i][j] = np.arccos(0.5 * ((red[i][j] - green[i][j]) + (red[i][j] - blue[i][j])) / (np.sqrt((red[i][j] - green[i][j]) ** 2 + (red[i][j] - blue[i][j]) * (green[i][j] - blue[i][j]))))
else:
hue[i][j] = 2 * np.pi - np.arccos(0.5 * ((red[i][j] - green[i][j]) + (red[i][j] - blue[i][j])) / (np.sqrt((red[i][j] - green[i][j]) ** 2 + (red[i][j] - blue[i][j]) * (green[i][j] - blue[i][j]))))
return hue
# Merge channels into picture and return image
hsi = np.zeros(img.shape) # instead of having 3 channels,one for each color (RGB),here we have a channel; for "hue",another for "saturation" and another for "intensity"
hsi[:,0],hsi[:,1],2] = calc_hue(red,blue),calc_saturation(red,calc_intensity(red,blue)
return hsi
cat = imageio.imread("Path...")
hsi_cat = RGB_TO_HSI(cat)
plt.imshow(hsi_cat)
plt.show()
但是,将代码中的行调整为:hsi = np.zeros(rgb.shape,dtype=np.uint8)
,然后使用 PIL 加载图像,并将其作为参数传递给函数:
cat_p = Image.open("Path...") # Using PIL Now
his_cat_p = RGB_TO_HSI(cat_p) # Passing the JPEG image into the function
his_cat_p = Image.fromarray(his_cat_p) # Converting the result back from an array (return hsi),into JPEG format
his_cat_p.show() # Black image appears
这个结果是一个黑色的图像,我不太确定为什么!
解决方法
函数 Image.fromarray
仅支持具有典型范围的有限 modes。如果只是想将数据正确渲染为图像,也许最好从 HSI 转换回 RGB 值,然后输出它。类似的东西,
cat_hsi = RGB_TO_HSI(cat)
result = modify(cat_hsi) # I guess you want to operate on hsi instead of rgb
result_rgb = HSI_TO_RGB(result)
img = Image.fromarray(result_rgb,mode='RGB')
img.show()
此外,我对代码进行了一些修改,使其在我的机器上运行。
- 确保将形状为 (X,Y,3) 的 RGB 数组传递给函数
- 在
calc_hue
函数中明确处理可能出现的零除情况。
import numpy as np
from numba import njit # code gets significantly faster
from matplotlib import pyplot as plt
from PIL import Image
def RGB_TO_HSI(img):
rgb = np.float32(img) / 255
red = rgb[:,:,0]
green = rgb[:,1]
blue = rgb[:,2]
def calc_intensity(red,green,blue):
intensity = (red + green + blue + 0.001) / 3
return intensity
def calc_saturation(red,blue):
minimum = np.minimum(np.minimum(red,green),blue)
saturation = 1 - (minimum / calc_intensity(red,blue))
return saturation
@njit # use numba to accelerate
def calc_hue(red,blue):
hue = np.copy(red)
for i in range(0,blue.shape[0]):
for j in range(0,blue.shape[1]):
denominator = np.sqrt(
(red[i][j] - green[i][j]) ** 2 + (red[i][j] - blue[i][j]) * (green[i][j] - blue[i][j])
)
if abs(denominator) < 1e-10: # exliciply handle the possible zero-division cases
hue[i][j] = np.nan
else:
if blue[i][j] <= green[i][j]:
hue[i][j] = np.arccos(0.5 * ((red[i][j] - green[i][j]) + (red[i][j] - blue[i][j])) / denominator)
else:
hue[i][j] = 2 * np.pi - np.arccos(0.5 * ((red[i][j] - green[i][j]) + (red[i][j] - blue[i][j])) / denominator)
return hue
# Merge channels into picture and return image
hsi = np.zeros(img.shape) # instead of having 3 channels,one for each color (RGB),here we have a channel; for "hue",another for "saturation" and another for "intensity"
hsi[:,0],hsi[:,1],2] = calc_hue(red,blue),calc_saturation(red,calc_intensity(red,blue)
return hsi
cat = np.array(Image.open("test.png"))
hsi_cat = RGB_TO_HSI(cat[:,:3]) # sometims images are in RGBA format
plt.imshow(hsi_cat)
plt.show()
(numba 很神奇吧?)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。