Python CV2 颜色 Space 转换保真度损失

Python CV2 Color Space Conversion Fidelity Loss

观察下图:

遵守以下 Python 代码:

import cv2
img = cv2.imread("rainbow.png", cv2.IMREAD_COLOR)
img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # convert it to hsv
img = cv2.cvtColor(img, cv2.COLOR_HSV2BGR) # convert back to BGR
cv2.imwrite("out.png", img)

这是输出图像:

如果您看不到,则此处的图像明显失去了视觉保真度。为了便于比较,这是在黄色周围放大的输出图像旁边的原始图像:

这是怎么回事?有什么方法可以防止这些块状伪影出现吗?我需要转换为 HSL 颜色 space 来旋转色调,但如果我要得到这些类型的人工制品,我不能这样做。

请注意,当我不进行两次转换时,输出图像没有伪影;转换本身确实是原因。

现在回到电脑前 - 像这样尝试:

#!/usr/bin/env python3
import numpy as np
import cv2

img = cv2.imread("rainbow.png", cv2.IMREAD_COLOR)
img = img.astype(np.float32)/255           # go to 32-bit float on 0..1

img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # convert it to hsv
img = cv2.cvtColor(img, cv2.COLOR_HSV2BGR) # convert back to BGR
cv2.imwrite("output.png", (img*255).astype(np.uint8))

我认为问题在于,当您使用无符号的 8 位表示时,色调从 0..360 的范围变为 "squished" 到0..180,以 2 度为增量,以保持在 0..255 的 8 位无符号范围内,从而在附近的值之间产生阶跃。一个解决方案是移动到 32 位浮点数并缩放到范围 0..1.