GPUImage 查找过滤器 - 创建大于 512² 颜色的颜色深度
Posted
技术标签:
【中文标题】GPUImage 查找过滤器 - 创建大于 512² 颜色的颜色深度【英文标题】:GPUImage Lookup Filter - creating a color depth greater than 512² colors 【发布时间】:2016-10-04 22:15:15 【问题描述】:GPUImage 的 LookupFilter 使用 512x512 的 RGB 像素图。当过滤器执行时,它会在此图像的修改版本与原始版本之间进行比较,并推断图像过滤器。
过滤器代码非常简单。这是一个摘录,因此您可以看到发生了什么:
void main()
highp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
highp float blueColor = textureColor.b * 63.0;
highp vec2 quad1;
quad1.y = floor(floor(blueColor) / 8.0);
quad1.x = floor(blueColor) - (quad1.y * 8.0);
highp vec2 quad2;
quad2.y = floor(ceil(blueColor) / 8.0);
quad2.x = ceil(blueColor) - (quad2.y * 8.0);
highp vec2 texPos1;
texPos1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);
texPos1.y = (quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g);
highp vec2 texPos2;
texPos2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);
texPos2.y = (quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g);
lowp vec4 newColor1 = texture2D(inputImageTexture2, texPos1);
lowp vec4 newColor2 = texture2D(inputImageTexture2, texPos2);
lowp vec4 newColor = mix(newColor1, newColor2, fract(blueColor));
gl_FragColor = mix(textureColor, vec4(newColor.rgb, textureColor.w), intensity);
);
看到过滤器映射依赖于 512x512 图像的位置吗?
我正在寻找将颜色深度提高 4 倍的方法,改用 1024x1024 源图像,但我不确定这个查找滤镜图像最初是如何生成的。
可以在代码中生成这样的东西吗?如果可以,我意识到这是一个非常广泛的问题,但我该怎么做呢?如果无法在代码中生成,我有什么选择?
——
更新:
原来原始 LUT 生成代码一直包含在头文件中。这里有问题的部分来自头文件:
查找纹理组织为 64x64 像素的 8x8 四边形,代表所有可能的 RGB 颜色:
64x64 如何是所有可能的 RGB 通道的映射? 64³ = 262,144,但这仅占 RGB 假定的 24 位容量的 1/64,即 64³ (16,777,216)。这里发生了什么?我错过了这个 LUT 的工作方式吗?我们如何仅用 1/64 的数据计算所有可能的 RGB 颜色?
for (int by = 0; by < 8; by++)
for (int bx = 0; bx < 8; bx++)
for (int g = 0; g < 64; g++)
for (int r = 0; r < 64; r++)
image.setPixel(r + bx * 64, g + by * 64, qRgb((int)(r * 255.0 / 63.0 + 0.5),
(int)(g * 255.0 / 63.0 + 0.5),
(int)((bx + by * 8.0) * 255.0 / 63.0 + 0.5)));
【问题讨论】:
【参考方案1】:我不太确定您实际上遇到了什么问题。当你说你想要“4x 颜色深度”时,你的实际意思是什么。颜色深度通常是指每个颜色通道(或每个像素)的位数,它与图像的分辨率完全无关。
就查找表精度(取决于分辨率)而言,假设您使用的是来自原始纹理的双线性过滤纹理输入,以及对变换表的过滤查找,那么您已经在查找表中的样本之间进行了线性插值。颜色通道的插值将比存储格式具有更高的精度;例如通常等效于 fp16,即使对于以每像素 8 位存储的纹理也是如此。
除非您在颜色转换中存在大量非线性(不常见),否则向查找表添加更多样本不太可能对输出产生显着影响 - 插值已经做得相当好填补空白。
【讨论】:
最终我认为这确实是有道理的 - 使用 1024x1024 像素查找表的实用性在这里可能在视觉上没有太大区别。我最感兴趣的是首先如何生成这样的查找表。可以用代码轻松完成吗?我该怎么做呢? 如何做取决于您要应用什么颜色变换;在大多数情况下,有一些理想化的数学方程式可以对色调映射进行编码,因此这只是在您关心的三个轴上进行迭代的情况。【参考方案2】:Lev Zelensky provided the original work for this,所以我不太了解其内部工作原理,但您可以查看着色器中执行的数学运算以了解发生了什么。
在 512x512 的查找中,您有一个 8x8 的单元格网格。在这些单元格中,您有一个 64x64 的图像补丁。红色值从 0 到 255(标准化值中为 0.0 到 1.0)在该补丁中从左到右,绿色值从 0 到 255 向下。这意味着红色有 64 级,绿色有 64 级。
然后,随着您从左到右,从上到下,沿着补丁前进,每个单元格似乎都会增加蓝色值。使用 64 个色块,可以为您提供 64 个蓝色值以匹配 64 个红色和绿色值。这使您可以在所有通道中对 RGB 值进行同等覆盖。
因此,如果您想将色阶数加倍,则必须将色块大小加倍至 128x128 并拥有 128 个网格。由于 128 没有整数平方根,它必须更像一个矩形。仅使用 1024x1024 可能会让您将红色和绿色通道的颜色深度加倍,但蓝色现在将是它们深度的一半。平衡这三者比将图像大小加倍要复杂一些。
【讨论】:
? 感谢 Brad 的周到回复。我必须做很多工作。以上是关于GPUImage 查找过滤器 - 创建大于 512² 颜色的颜色深度的主要内容,如果未能解决你的问题,请参考以下文章