我目前正在尝试从原始RGB图像开始,将其转换为LUV,执行一些操作(即旋转色相),然后将其旋转回RGB以用于显示。但是,我遇到了一个令人烦恼的问题,其中RGB到LUV的转换(反之亦然)似乎正在改变图像。具体来说,如果我从LUV图像开始,将其转换为RGB,然后将其更改回LUV,而不更改其他任何内容,则原始图像会有所不同。对于颜色转换算法的Python(cv2)和Matlab(开放源代码)实现,以及我自己基于的手动编码实现,都已经发生了这种情况。这是一个示例:
luv1 = np.array([[[100,6.12,0]]]).astype('float32')
rgb1 = cv2.cvtColor(luv1,cv2.COLOR_Luv2RGB)
luv2 = cv2.cvtColor(rgb1,cv2.COLOR_RGB2Luv)
print(luv2)
[[[99.36293 1.3064307 -1.0494182]]]
如您所见,LUV坐标已从输入中更改。这是因为某些LUV坐标在RGB空间中没有直接匹配吗?
答案 0 :(得分:3)
是的,删除代码中的astype('uint8')
位,如果正确实现了转换,差异应该会消失。
您可以在Wikipedia中看到转换公式。没有什么是不可逆的,转换是彼此的完美逆。
但是,此转换包含3 rd 次幂,它确实可以显着扩展某些值。将转换舍入为整数可能会导致颜色发生明显变化。
此外,Luv域是高度不规则的,因此验证Luv值将导致RGB值可能并不容易。您的陈述“我已验证luv1的条目都在允许的输入范围内”,这使我相信您认为Luv域是一个框。它不是。 u 和 v 的范围随 L 改变。一个好的练习是从RGB立方体的采样开始,然后将其映射到Luv,然后绘制这些点以查看Luv域的形状。维基百科提供了一个for the sRGB gamut外观的示例。
OpenCV cvtColor
函数会将RGB值限制在[0,1]范围内(如果类型为float32
),如果输入超出色域,则会导致不可逆的颜色变化。
以下是显示转换是可逆的示例。我从RGB值开始,因为这些值很容易验证为有效:
import numpy as np
import cv2
rgb1 = np.array([[[1.0,1.0,1.0],[0.5,1.0,0.5],[0.0,0.5,0.5],[0.0,0.0,0.0]]], 'float32')
luv1 = cv2.cvtColor(rgb1, cv2.COLOR_RGB2Luv)
rgb2 = cv2.cvtColor(luv1, cv2.COLOR_Luv2RGB)
np.max(np.abs(rgb2-rgb1))
这将返回2.8897537e-06
,这是32位浮点数的数字精度。