首页 > 解决方案 > 将图像从 RGB 转换为 LUV 并返回会导致不同的图像

问题描述

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

标签: pythonmatlabcolorsrgbspaces

解决方案


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

您可以在Wikipedia中查看转换公式。没有什么是不可逆的,转换是彼此完美的倒数。

但是,此转换包含 3幂,这确实会显着拉伸某些值。转换为整数的舍入可能会引入显着的颜色偏移。

此外,Luv 域是高度不规则的,可能不容易验证 Luv 值是否会导致一个有价值的 RGB 值。您的陈述“我已经验证 luv1 的条目都在允许的输入范围内”让我相信您认为 Luv 域是一个框。它不是。uv的范围随L变化。一个很好的练习是从 RGB 立方体的采样开始,并将它们映射到 Luv,然后绘制这些点以查看 Luv 域的形状。维基百科有一个sRGB 色域的例子。

OpenCVcvtColor函数会将 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-0632 位浮点数的数值精度。


推荐阅读