观察下图:
观察以下 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)
这是输出图像:
如果您看不到它,则此处图像的视觉保真度明显下降。为了便于比较,这是在黄色周围放大的输出图像旁边的原始图像:
这是怎么回事?有什么方法可以防止这些 block 状伪影出现吗?我需要转换到 HSL 色彩空间来旋转色调,但如果我要获得这些类型的伪像,我就不能这样做。
请注意,当我不进行两次转换时,输出图像没有伪影;转化本身确实是原因。
最佳答案
现在回到电脑前 - 像这样尝试:
#!/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 的范围变成 0..180 的范围,在 2度数递增以保持在 0..255 的 8 位无符号范围内,从而导致附近值之间出现阶跃。一种解决方案是移动到 32 位 float 并缩放到 0..1 范围。
关于Python CV2 色彩空间转换保真度损失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54065840/