Python 将图像从RGB转换为LUV和back会产生不同的图像

Python 将图像从RGB转换为LUV和back会产生不同的图像,python,matlab,colors,rgb,spaces,Python,Matlab,Colors,Rgb,Spaces,我目前正在尝试从原始RGB图像开始,将其转换为LUV,执行一些操作(即旋转色调),然后将其旋转回RGB以显示。然而,我遇到了一个棘手的问题,RGB到LUV的转换(反之亦然)似乎正在改变图像。具体来说,如果我从LUV图像开始,将其转换为RGB,然后将其更改回LUV,而不更改任何其他内容,则原始图像是不同的。对于颜色转换算法的Python(cv2)和Matlab(开源)实现,以及我自己基于的手工编码算法,都发生了这种情况。以下是一个例子: luv1 = np.array([[[100,6.12,0]

我目前正在尝试从原始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空间中没有直接匹配吗?

是的,删除代码中的
astype('uint8')
位,如果正确执行转换,则差异应该消失

您可以在中查看转换的方程式。没有什么是不可逆的,转换是彼此的完美反比

但是,此转换包含第三次方,这确实会显著拉伸某些值。将转换四舍五入为整数可能会导致显著的颜色偏移

此外,Luv域是高度不规则的,要验证Luv值是否会导致有值的RGB值可能并不容易。您的声明“我已经验证了luv1包含的条目都在允许的输入范围内”,这让我相信您认为Luv域是一个盒子。事实并非如此。u和v的范围随L而变化。一个好的练习是从RGB立方体的采样开始,将它们映射到Luv,然后绘制这些点以查看Luv域的形状。Wikipedia提供了一个这样的例子

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位浮点的数字精度。

添加了一个编辑:这是有意义的,但并不能解决问题。@buldog91:在这种情况下,您可能从与有效RGB值不对应的Luv值开始。请参阅此答案的编辑。您能否给出一个具体的RGB或LUV值,以显示您在此报告的差异类型?您的代码不包含任何输入。添加了,很抱歉原来的格式不正确。如果您有兴趣在不需要LUV的情况下旋转色调,您可以查看。奇怪的是,我在Objective-C问题上留下了Python的答案。正如我所建议的,您的Luv值超出了范围。当L=100时,u和v只能为0,因为L=100是纯白色,颜色无法区分。请看我在回答中链接的Luv色域的图片。