Python HSI 到 RGB 的转换 - 不是我所期望的
Python HSI to RGB conversion - not what I expect
我正在尝试使用公式手动处理 HSV -> RGB,而不使用 openCV。
我尝试计算 HSV -> RGB 颜色 space,并给出了我想要的几乎相同的图片,但有一些噪音。
有些图像有很多噪声,有些图像真的没有噪声(有“一些”噪声。)
我试过调试..但似乎不知道我的代码有什么问题。
是我写的Formulla吗?还是我错过了什么?..
我不知道我不知道什么。所以,我需要帮助..
这是我的代码,我将 post 原始图像和下面有噪声的结果图像。
首先,这是我的代码。
def HSI_to_bgr(h, s, i):
h = degrees(h)
if 0 < h <= 120 :
b = i * (1 - s)
r = i * (1 + (s * cos(radians(h)) / cos(radians(60) - radians(h))))
g = i * 3 - (r + b)
elif 120 < h <= 240:
h -= 120
r = i * (1 - s)
g = i * (1 + (s * cos(radians(h)) / cos(radians(60) - radians(h))))
b = 3 * i - (r + g)
elif 0 < h <= 360:
h -= 240
g = i * (1 - s)
b = i * (1 + (s * cos(radians(h)) / cos(radians(60) - radians(h))))
r = i * 3 - (g + b)
return [b, g, r]
def rgb_to_hue(b, g, r):
angle = 0
if b != g != r:
angle = 0.5 * ((r - g) + (r - b)) / sqrt(((r - g) ** 2) + (r - b) * (g - b))
if b <= g:
return acos(angle)
else:
return 2 * pi - acos(angle)
def rgb_to_intensity(b, g, r):
val = (b + g + r) / 3.
if val == 0:
return 0
else:
return val
def rgb_to_saturity(b, g, r):
if r + g + b != 0:
return 1. - 3. * np.min([r, g, b]) / (r + g + b)
else:
return 0
def point_process_colorscale_negative_intensity(file_path):
src = cv2.imread(file_path, cv2.IMREAD_COLOR)
height, width = src.shape[0], src.shape[1]
new_image = np.zeros((height, width, 3), dtype=np.uint8)
I = np.zeros((height, width))
S = np.zeros((height, width))
H = np.zeros((height, width))
for i in range(height) :
for j in range(width) :
b = src[i][j][0] / 255.
g = src[i][j][1] / 255.
r = src[i][j][2] / 255.
H[i][j] = rgb_hsi_conversion.rgb_to_hue(b, g, r)
S[i][j] = rgb_hsi_conversion.rgb_to_saturity(b, g, r)
I[i][j] = rgb_hsi_conversion.rgb_to_intensity(b, g, r)
# I[i][j] = 1. - I[i][j]
bgr_tuple = rgb_hsi_conversion.HSI_to_bgr(H[i][j], S[i][j], I[i][j])
new_image[i][j][0] = round(bgr_tuple[0] * 255.)
new_image[i][j][1] = round(bgr_tuple[1] * 255.)
new_image[i][j][2] = round(bgr_tuple[2] * 255.)
return new_image, src
这是我的结果图片。
他们都有一些噪音。尤其是狒狒的鼻子和小山羊的紫噪更厉害
先谢谢你了,如果我没有提供足够的信息,我会尽力补充。
主要问题是 b != g != r
行,意思是 b != g
或 g != r
,应该是:如果 b == g
和 g == r
return0
为了调试问题,您可以找到输出错误值的像素(通过比较 new_image
和 src
)。
找到该像素的 b、g、r 值。
实现少量代码来调试特定的 b、g、r 值。
使用调试器查找出错的地方。
这是用于调试值 b, g, r = 74, 74, 229
:
的代码示例
b = 74 / 255.
g = 74 / 255.
r = 229 / 255.
H = rgb_to_hue(b, g, r)
S = rgb_to_saturity(b, g, r)
I = rgb_to_intensity(b, g, r)
bgr_tuple = HSI_to_bgr(H, S, I)
new_b = round(bgr_tuple[0] * 255.)
new_g = round(bgr_tuple[1] * 255.)
new_r = round(bgr_tuple[2] * 255.)
这就是我发现 b != g != r
有问题的原因(因为 r==g
但 g!=r
)。
请记住,在很多情况下编写一些代码来查找错误(而不是调试原始代码)会更容易。
更正后的代码:
import cv2
import numpy as np
from math import sqrt, cos, acos, degrees, radians, pi
def HSI_to_bgr(h, s, i):
h = degrees(h)
if 0 <= h <= 120 :
b = i * (1 - s)
r = i * (1 + (s * cos(radians(h)) / cos(radians(60) - radians(h))))
g = i * 3 - (r + b)
elif 120 < h <= 240:
h -= 120
r = i * (1 - s)
g = i * (1 + (s * cos(radians(h)) / cos(radians(60) - radians(h))))
b = 3 * i - (r + g)
elif 0 < h <= 360:
h -= 240
g = i * (1 - s)
b = i * (1 + (s * cos(radians(h)) / cos(radians(60) - radians(h))))
r = i * 3 - (g + b)
return [b, g, r]
def rgb_to_hue(b, g, r):
if (b == g == r):
return 0
angle = 0.5 * ((r - g) + (r - b)) / sqrt(((r - g) ** 2) + (r - b) * (g - b))
if b <= g:
return acos(angle)
else:
return 2 * pi - acos(angle)
def rgb_to_intensity(b, g, r):
val = (b + g + r) / 3.
if val == 0:
return 0
else:
return val
def rgb_to_saturity(b, g, r):
if r + g + b != 0:
return 1. - 3. * np.min([r, g, b]) / (r + g + b)
else:
return 0
def point_process_colorscale_negative_intensity(file_path):
src = cv2.imread(file_path, cv2.IMREAD_COLOR)
height, width = src.shape[0], src.shape[1]
new_image = np.zeros((height, width, 3), dtype=np.uint8)
I = np.zeros((height, width))
S = np.zeros((height, width))
H = np.zeros((height, width))
for i in range(height):
for j in range(width):
b = src[i][j][0] / 255.
g = src[i][j][1] / 255.
r = src[i][j][2] / 255.
H[i][j] = rgb_to_hue(b, g, r)
S[i][j] = rgb_to_saturity(b, g, r)
I[i][j] = rgb_to_intensity(b, g, r)
bgr_tuple = HSI_to_bgr(H[i][j], S[i][j], I[i][j])
new_image[i][j][0] = np.clip(round(bgr_tuple[0] * 255.), 0, 255)
new_image[i][j][1] = np.clip(round(bgr_tuple[1] * 255.), 0, 255)
new_image[i][j][2] = np.clip(round(bgr_tuple[2] * 255.), 0, 255)
return new_image, src
new_image, src = point_process_colorscale_negative_intensity('mandrill.png') # The mandrill image I used is from MATLAB.
cv2.imwrite('new_image.png', new_image) # Save new_image for testing
cv2.imshow('new_image', new_image) # Show new_image for testing
cv2.imshow('abs diff*50', np.minimum(cv2.absdiff(src, new_image), 5)*50) # Show absolute difference of (src - new_image) multiply by 50 for showing small differences.
cv2.waitKey()
cv2.destroyAllWindows()
如果还有问题,请尝试使用一小段代码进行调试...
new_image:
我正在尝试使用公式手动处理 HSV -> RGB,而不使用 openCV。
我尝试计算 HSV -> RGB 颜色 space,并给出了我想要的几乎相同的图片,但有一些噪音。
有些图像有很多噪声,有些图像真的没有噪声(有“一些”噪声。)
我试过调试..但似乎不知道我的代码有什么问题。
是我写的Formulla吗?还是我错过了什么?..
我不知道我不知道什么。所以,我需要帮助..
这是我的代码,我将 post 原始图像和下面有噪声的结果图像。
首先,这是我的代码。
def HSI_to_bgr(h, s, i):
h = degrees(h)
if 0 < h <= 120 :
b = i * (1 - s)
r = i * (1 + (s * cos(radians(h)) / cos(radians(60) - radians(h))))
g = i * 3 - (r + b)
elif 120 < h <= 240:
h -= 120
r = i * (1 - s)
g = i * (1 + (s * cos(radians(h)) / cos(radians(60) - radians(h))))
b = 3 * i - (r + g)
elif 0 < h <= 360:
h -= 240
g = i * (1 - s)
b = i * (1 + (s * cos(radians(h)) / cos(radians(60) - radians(h))))
r = i * 3 - (g + b)
return [b, g, r]
def rgb_to_hue(b, g, r):
angle = 0
if b != g != r:
angle = 0.5 * ((r - g) + (r - b)) / sqrt(((r - g) ** 2) + (r - b) * (g - b))
if b <= g:
return acos(angle)
else:
return 2 * pi - acos(angle)
def rgb_to_intensity(b, g, r):
val = (b + g + r) / 3.
if val == 0:
return 0
else:
return val
def rgb_to_saturity(b, g, r):
if r + g + b != 0:
return 1. - 3. * np.min([r, g, b]) / (r + g + b)
else:
return 0
def point_process_colorscale_negative_intensity(file_path):
src = cv2.imread(file_path, cv2.IMREAD_COLOR)
height, width = src.shape[0], src.shape[1]
new_image = np.zeros((height, width, 3), dtype=np.uint8)
I = np.zeros((height, width))
S = np.zeros((height, width))
H = np.zeros((height, width))
for i in range(height) :
for j in range(width) :
b = src[i][j][0] / 255.
g = src[i][j][1] / 255.
r = src[i][j][2] / 255.
H[i][j] = rgb_hsi_conversion.rgb_to_hue(b, g, r)
S[i][j] = rgb_hsi_conversion.rgb_to_saturity(b, g, r)
I[i][j] = rgb_hsi_conversion.rgb_to_intensity(b, g, r)
# I[i][j] = 1. - I[i][j]
bgr_tuple = rgb_hsi_conversion.HSI_to_bgr(H[i][j], S[i][j], I[i][j])
new_image[i][j][0] = round(bgr_tuple[0] * 255.)
new_image[i][j][1] = round(bgr_tuple[1] * 255.)
new_image[i][j][2] = round(bgr_tuple[2] * 255.)
return new_image, src
这是我的结果图片。
他们都有一些噪音。尤其是狒狒的鼻子和小山羊的紫噪更厉害
先谢谢你了,如果我没有提供足够的信息,我会尽力补充。
主要问题是 b != g != r
行,意思是 b != g
或 g != r
,应该是:如果 b == g
和 g == r
return0
为了调试问题,您可以找到输出错误值的像素(通过比较 new_image
和 src
)。
找到该像素的 b、g、r 值。
实现少量代码来调试特定的 b、g、r 值。
使用调试器查找出错的地方。
这是用于调试值 b, g, r = 74, 74, 229
:
b = 74 / 255.
g = 74 / 255.
r = 229 / 255.
H = rgb_to_hue(b, g, r)
S = rgb_to_saturity(b, g, r)
I = rgb_to_intensity(b, g, r)
bgr_tuple = HSI_to_bgr(H, S, I)
new_b = round(bgr_tuple[0] * 255.)
new_g = round(bgr_tuple[1] * 255.)
new_r = round(bgr_tuple[2] * 255.)
这就是我发现 b != g != r
有问题的原因(因为 r==g
但 g!=r
)。
请记住,在很多情况下编写一些代码来查找错误(而不是调试原始代码)会更容易。
更正后的代码:
import cv2
import numpy as np
from math import sqrt, cos, acos, degrees, radians, pi
def HSI_to_bgr(h, s, i):
h = degrees(h)
if 0 <= h <= 120 :
b = i * (1 - s)
r = i * (1 + (s * cos(radians(h)) / cos(radians(60) - radians(h))))
g = i * 3 - (r + b)
elif 120 < h <= 240:
h -= 120
r = i * (1 - s)
g = i * (1 + (s * cos(radians(h)) / cos(radians(60) - radians(h))))
b = 3 * i - (r + g)
elif 0 < h <= 360:
h -= 240
g = i * (1 - s)
b = i * (1 + (s * cos(radians(h)) / cos(radians(60) - radians(h))))
r = i * 3 - (g + b)
return [b, g, r]
def rgb_to_hue(b, g, r):
if (b == g == r):
return 0
angle = 0.5 * ((r - g) + (r - b)) / sqrt(((r - g) ** 2) + (r - b) * (g - b))
if b <= g:
return acos(angle)
else:
return 2 * pi - acos(angle)
def rgb_to_intensity(b, g, r):
val = (b + g + r) / 3.
if val == 0:
return 0
else:
return val
def rgb_to_saturity(b, g, r):
if r + g + b != 0:
return 1. - 3. * np.min([r, g, b]) / (r + g + b)
else:
return 0
def point_process_colorscale_negative_intensity(file_path):
src = cv2.imread(file_path, cv2.IMREAD_COLOR)
height, width = src.shape[0], src.shape[1]
new_image = np.zeros((height, width, 3), dtype=np.uint8)
I = np.zeros((height, width))
S = np.zeros((height, width))
H = np.zeros((height, width))
for i in range(height):
for j in range(width):
b = src[i][j][0] / 255.
g = src[i][j][1] / 255.
r = src[i][j][2] / 255.
H[i][j] = rgb_to_hue(b, g, r)
S[i][j] = rgb_to_saturity(b, g, r)
I[i][j] = rgb_to_intensity(b, g, r)
bgr_tuple = HSI_to_bgr(H[i][j], S[i][j], I[i][j])
new_image[i][j][0] = np.clip(round(bgr_tuple[0] * 255.), 0, 255)
new_image[i][j][1] = np.clip(round(bgr_tuple[1] * 255.), 0, 255)
new_image[i][j][2] = np.clip(round(bgr_tuple[2] * 255.), 0, 255)
return new_image, src
new_image, src = point_process_colorscale_negative_intensity('mandrill.png') # The mandrill image I used is from MATLAB.
cv2.imwrite('new_image.png', new_image) # Save new_image for testing
cv2.imshow('new_image', new_image) # Show new_image for testing
cv2.imshow('abs diff*50', np.minimum(cv2.absdiff(src, new_image), 5)*50) # Show absolute difference of (src - new_image) multiply by 50 for showing small differences.
cv2.waitKey()
cv2.destroyAllWindows()
如果还有问题,请尝试使用一小段代码进行调试...
new_image: