【问题标题】:How to use 3d lookup table and map its pixel value to an image?如何使用 3d 查找表并将其像素值映射到图像?
【发布时间】:2019-07-10 15:21:22
【问题描述】:

我正在尝试将 png 颜色表应用于图像,但无法将 png 中的像素与目标图像匹配。

颜色表是 64^3 的 png

据我了解,大图像中的每个像素,都需要在颜色表中使用相似的值。这似乎将颜色限制为 262144 = 64 x 64 x 64。但我不确定这是我得到的效果,结果是完全黑色的图像,这意味着没有价值,或者看起来很奇怪的颜色。

这是我的代码


// The table is 64 x 64 x 64
float size = 64.0;

// This is the original image
// This function returns a pixel value inside a 3d space
//  and the `rgb` method will return a vector with the rgb values
vec3 source_image = sample(src_i, samplerCoord(src_i)).rgb;
// Here I take the pixel value of the image for the red channel
//  and multiply it by 64.0, then divide by 255.0 for the 8-bit image
float x = floor(floor(source_image.r * size)/255.0);
// The same thing for the green value on the y axis
float y = floor(floor(source_image.g * size)/255.0);

// Match a value from the image in the color table
vec3 color = sample(src_l, vec2(x, y)).rgb;

src_i.r = color.r;
src_i.g = color.g;
// The blue should be on the z axis, or the nth tile, so I think for this
//   case it will be easier to convert the color table to one long row
src_i.b = floor(floor(source_image.b * size)/255.0);

// The image is black

原图

预期结果

如果我乘以 255(这似乎是正确的),那么我会得到这个结果

float x = floor(source_image.r * 255.0);
float y = floor(source_image.g * 255.0);

如果您能指出数学有什么问题,我将不胜感激

【问题讨论】:

  • 是像素值,我会编辑这部分。感谢您添加照片

标签: opengl image-processing glsl core-image


【解决方案1】:

查找表不是 64*64*64,而是 8*8 栅格中的 64*64。 texture2D 读取的颜色通道在 [0, 1] 范围内,纹理坐标也在 [0, 1] 范围内。

vec2 tiles    = vec2(8.0);
vec2 tileSize = vec2(64.0);

vec3 imageColor = texture(src_i, samplerCoord(src_i)).rgb;

图块的索引被编码到蓝色通道。有 64 个图块,第一个图块的索引为 0,最后一个图块的索引为 63。这意味着必须将 [0, 1] 范围内的蓝色通道映射到 [0, 63] 范围内:

float index = imageColor.b * (tiles.x * tiles.y - 1.0);

从这个线性瓦片索引中,必须计算二维瓦片索引在 [0, 8] 范围内:

vec2 tileIndex;
tileIndex.y = floor(index / tiles.x);
tileIndex.x = floor(index - tileIndex.y * tiles.x);

纹理缩小功能(GL_TEXTURE_MIN_FILTER)和纹理放大功能(GL_TEXTURE_MAG_FILTER应设置为GL_LINEAR。这导致每个图块上的颜色可以进行线性插值。
每个图块有 64x64 纹素。左下纹素的相对坐标为(0.5/64.0, 0.5/64.0),右上纹素的相对坐标为(63.5/64.0, 63.5/64.0)。
[0, 1] 范围内的红色和绿色通道必须映射到 [0.5/64.0, 63.5/64.0] 范围内:

vec2 tileUV = mix(0.5/tileSize, (tileSize-0.5)/tileSize, imageColor.rg);

最后可以计算出 [0, 1] 范围内颜色查找表的纹理坐标:

vec2 tableUV = tileIndex / tiles + tileUV / tiles;

在片段着色器中解码颜色的最终代码可能如下所示:

vec2 tiles    = vec2(8.0, 8.0);
vec2 tileSize = vec2(64.0);

vec4 imageColor = texture(src_i, samplerCoord(src_i));

float index = imageColor.b * (tiles.x * tiles.y - 1.0);

vec2 tileIndex;
tileIndex.y = floor(index / tiles.x);
tileIndex.x = floor(index - tileIndex.y * tiles.x);

vec2 tileUV = mix(0.5/tileSize, (tileSize-0.5)/tileSize, imageColor.rg);

vec2 tableUV = tileIndex / tiles + tileUV / tiles;

vec3 lookUpColor = texture(src_l, tableUV).rgb;

通过在表格的 2 个图块之间进行插值,可以进一步改进该算法。计算蓝色通道下方的tile的索引和蓝色通道上方的tile的索引:

float index     = imageColor.b * (tiles.x * tiles.y - 1.0);
float index_min = min(62.0, floor(index));
float index_max = index_min + 1.0;

最后使用mix 函数在两个图块的颜色之间进行插值:

vec3 lookUpColor_1 = texture(src_l, tableUV_1).rgb;
vec3 lookUpColor_2 = texture(src_l, tableUV_1).rgb;
vec3 lookUpColor   = mix(lookUpColor_1, lookUpColor_2, index-index_min); 

最终代码:

vec2 tiles    = vec2(8.0, 8.0);
vec2 tileSize = vec2(64.0);

vec4 imageColor = texture(src_i, samplerCoord(src_i));

float index     = imageColor.b * (tiles.x * tiles.y - 1.0);
float index_min = min(62.0, floor(index));
float index_max = index_min + 1.0;

vec2 tileIndex_min;
tileIndex_min.y = floor(index_min / tiles.x);
tileIndex_min.x = floor(index_min - tileIndex_min.y * tiles.x);
vec2 tileIndex_max;
tileIndex_max.y = floor(index_max / tiles.x);
tileIndex_max.x = floor(index_max - tileIndex_max.y * tiles.x);

vec2 tileUV = mix(0.5/tileSize, (tileSize-0.5)/tileSize, imageColor.rg);

vec2 tableUV_1 = tileIndex_min / tiles + tileUV / tiles;
vec2 tableUV_2 = tileIndex_max / tiles + tileUV / tiles;

vec3 lookUpColor_1 = texture(src_l, tableUV_1).rgb;
vec3 lookUpColor_2 = texture(src_l, tableUV_2).rgb;
vec3 lookUpColor   = mix(lookUpColor_1, lookUpColor_2, index-index_min); 

查看对比原始图像(左上角)和颜色查找修改后图像(右下角)的图像:

【讨论】:

    【解决方案2】:

    在颜色表中查找对应位置的计算似乎已关闭。我认为您必须首先找到在正确的“红绿平面”内着陆的偏移量(由输入的蓝色通道确定,考虑到由于地图中的 8x8 布局而导致的 8 步幅),然后将此偏移量添加到 xy 值的计算中。

    但是,我建议您先查看内置的 CIColorCube filter,因为它完全符合您的要求。

    【讨论】:

    • 感谢您的解释,我还没有找到解决方案。但是,它使用 CIColorCube 和水平 lut 而不是正方形。但我正在尝试使用并理解查找功能
    猜你喜欢
    • 2020-07-01
    • 2021-08-03
    • 1970-01-01
    • 2019-04-04
    • 2013-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多