python - 将图像从 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 空间中没有直接匹配吗?
解决方案
是的,删除astype('uint8')
代码中的位,如果转换正确实现,差异应该消失。
您可以在Wikipedia中查看转换公式。没有什么是不可逆的,转换是彼此完美的倒数。
但是,此转换包含 3次幂,这确实会显着拉伸某些值。转换为整数的舍入可能会引入显着的颜色偏移。
此外,Luv 域是高度不规则的,可能不容易验证 Luv 值是否会导致一个有价值的 RGB 值。您的陈述“我已经验证 luv1 的条目都在允许的输入范围内”让我相信您认为 Luv 域是一个框。它不是。u和v的范围随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-06
32 位浮点数的数值精度。
推荐阅读
- javascript - 处理请求中的多个克隆输入
- html - 管理角度组件高度以适应屏幕的最佳方法
- javascript - 如何在 VueJs 的数据表中显示数据?
- javascript - 在 iframe / object 标签内运行时更新初始路由器 url
- javascript - 如何在 Express 中重复某些内容?
- python - 为什么在 Python 3.8 中是 sqrt(x*x + y*y) != math.hypot(x, y)?
- unity3d - Unity:NavMesh Agent 自定义移动而不是基本变换位置
- windows - 使用 Apache 和 mod_wsgi 运行烧瓶应用程序不起作用
- react-native - 我们如何访问位于世博会项目之外的图像?
- google-chrome-extension - Google Chrome 扩展程序自行重启