c++ - 为 sRGB 到 CIELAB 色彩空间转换生成 3DLUT(.3dl 文件)

标签 c++ image-processing

我们的 API 中已经有一个高度优化的类来读取 3D Lut(Nuke 格式)文件并将转换应用于图像。因此,与其使用复杂的公式逐个像素地迭代并将 RGB 值转换为 Lab (RGB->XYZ->Lab) 值,我认为如果我生成一个 RGB 到 LAB(或 XYZ 到实验室)变换。这可能吗?

我了解 3D Lut 如何用于从 RGB 到 RGB 的转换,但我对 RGB 到 Lab 感到困惑,因为 L、a 和 b 具有不同的范围。有什么提示吗?

编辑:

你能解释一下 Lut 是如何工作的吗? 这是一种解释:link

例如,下面是我对 RGB->RGB 变换的 3D Lut 的理解: 示例 Nuke 3dl Lut 文件:

0    64   128   192   256   320   384   448   512   576   640   704   768   832   896   960  1023 
R, G, B 
0, 0, 0 
0, 0, 64 
0, 0, 128 
0, 0, 192 
0, 0, 256 
.
.
.
0, 64, 0
0, 64, 64
0, 64, 128
.
.

此处不是为源 10 位 RGB 值生成 1024*1024*1024 表,而是将每个 R、G 和 B 范围量化为 17 个值,生成 4913 行表。 第一行给出了可能的量化值(我认为这里只有长度和最大值很重要)。现在假设,如果源 RGB 值为 (20, 20, 190),输出将是第 4 行 (0, 0, 192)(使用一些插值技术)。那是对的吗? 这是一个用于 10 位源的源代码,您可以通过将范围从 0 更改为 255 来生成一个用于 8 位源的相似源代码吗?

同样,您将如何进行 sRGB->Lab 转换?

最佳答案

另一种方法是使用图形硬件,也就是“通用 GPU 计算”。为此有一些不同的工具,例如OpenGL GLSL、OpenCL、CUDA……与 CPU 解决方案相比,您应该获得大约 100 倍甚至更多的令人难以置信的加速。

最“兼容”的解决方案是将 OpenGL 与特殊的片段着色器结合使用,您可以使用该着色器执行计算。这意味着:将输入图像作为纹理上传到 GPU,使用特殊着色器程序将其渲染到(目标)帧缓冲区中,将 RGB 数据转换为 Lab(或者它也可以使用查找表,但大多数浮点计算在 GPU 上比表/纹理查找更快,所以我们不会在这里这样做)。

首先,将您的 RGB 到 Lab 转换函数移植到 GLSL。它应该适用于 float ,因此如果您在原始转换中使用整数值,请摆脱它们。 OpenGL 使用“钳位”值,即 0.01.0 之间的浮点值。它看起来像这样:

vec3 rgbToLab(vec3 rgb) {
    vec3 lab = ...;
    return lab;
}

然后,编写着色器的其余部分,它将获取 (RGB) 纹理的像素,调用转换函数并将像素写入颜色输出变量(不要忘记 alpha channel ):

uniform sampler2D texture;
varying vec2 texCoord;

void main() {
    vec3 rgb = texture2D(texture, texCoord).rgb;
    gl_FragColor = vec4(lab, 1.0);
}

相应的顶点着色器应该在左下角写入(0,0)texCoord值,在左下角写入(1,1)填充整个屏幕(帧缓冲区)的目标四边形的右上角。

最后,通过在与图像大小相同的帧缓冲区上渲染,在您的应用程序中使用此着色器程序。渲染一个填充整个区域的四边形(不设置任何变换,只渲染一个从二维顶点 (-1,-1)(1,1) 的四边形) .将统一值 texture 设置为您作为纹理上传的 RGB 图像。然后,从设备中读回帧缓冲区,它应该包含您在 Lab 色彩空间中的图像。

关于c++ - 为 sRGB 到 CIELAB 色彩空间转换生成 3DLUT(.3dl 文件),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17188859/

相关文章:

c++ - vector 分配困惑

c++ - 使用 OpenCV 检测视频中的特定(定性)颜色

c++ - ifstream::close 是否会重置 failbit 和/或 badbit?

c++ - 如何打印目录树?

c# - 识别图像中的对象

python - 检测网格的角

matlab - 如何使用 Matlab 提取图像中的文本区域?

java - 将(之前将 RGB 转换为)灰度 MAT 转换回 RGB

C++:模板 模板参数的模板成员作为模板类的参数 需要模板 模板参数

c++ - g++ 编译存在于另一个目录中的源文件