使用 PIL 而不是 imagio 库读取图像时图像无法正确显示
Image not showing properly when reading the image using PIL instead of imagio library
我有这段代码可以将图像从 RGB space 转换为 HSI space:
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, green, blue):
minimum = np.minimum(np.minimum(red, green), blue)
saturation = 1 - (minimum / calc_intensity(red, green, blue))
return saturation
# Calculate Hue
def calc_hue(red, green, 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], hsi[:, :, 2] = calc_hue(red, green, blue), calc_saturation(red, green, blue), calc_intensity(red, green, 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, green, blue):
minimum = np.minimum(np.minimum(red, green), blue)
saturation = 1 - (minimum / calc_intensity(red, green, blue))
return saturation
@njit # use numba to accelerate
def calc_hue(red, green, 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], hsi[:, :, 2] = calc_hue(red, green, blue), calc_saturation(red, green, blue), calc_intensity(red, green, 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 很神奇不是吗?)
我有这段代码可以将图像从 RGB space 转换为 HSI space:
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, green, blue):
minimum = np.minimum(np.minimum(red, green), blue)
saturation = 1 - (minimum / calc_intensity(red, green, blue))
return saturation
# Calculate Hue
def calc_hue(red, green, 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], hsi[:, :, 2] = calc_hue(red, green, blue), calc_saturation(red, green, blue), calc_intensity(red, green, 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, green, blue):
minimum = np.minimum(np.minimum(red, green), blue)
saturation = 1 - (minimum / calc_intensity(red, green, blue))
return saturation
@njit # use numba to accelerate
def calc_hue(red, green, 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], hsi[:, :, 2] = calc_hue(red, green, blue), calc_saturation(red, green, blue), calc_intensity(red, green, 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 很神奇不是吗?)