Как использовать 3D-таблицу поиска и сопоставить ее значение пикселя с изображением?

Я пытаюсь применить таблицу цветов png к изображению, но не могу сопоставить пиксель из png с целевым изображением.

Таблица цветов представляет собой png 64 ^ 3.

Из того, что я понимаю, каждый пиксель в самом большом изображении должен использовать аналогичное значение в таблице цветов. Это, кажется, ограничивает цвета до 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);

Я был бы очень признателен, если бы вы могли указать, что не так с математикой


person MIkael    schedule 16.02.2019    source источник
comment
Значение в пикселях, я отредактирую эту часть. Спасибо за добавление фотографий   -  person MIkael    schedule 17.02.2019


Ответы (2)


Таблица поиска не 64*64*64, а 64*64 в растре 8*8. Цветовые каналы, которые считывает 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. Это приводит к тому, что цвета на каждой плитке могут быть линейными. интерполированный.
Каждая плитка имеет тексели 64 x 64. Относительная координата нижнего левого текселя – (0,5/64,0, 0,5/64,0), а относительная координата верхнего правого текселя – (63,5/64,0, 63,5/64,0).< br> Красный и зеленый цветовые каналы в диапазоне [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;

Этот алгоритм можно дополнительно улучшить путем интерполяции между двумя тайлами таблицы. Вычислить индекс плитки ниже канала синего цвета и индекс плитки выше канала синего цвета:

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); 

Посмотрите изображение, которое сравнивает исходное изображение (вверху слева) и измененное изображение с поиском цвета (внизу справа):

person Rabbid76    schedule 17.02.2019

Расчет для нахождения соответствующей позиции в таблице цветов, похоже, отключен. Я думаю, вам нужно было бы сначала найти смещение для приземления внутри правильной "красно-зеленой плоскости" (определяется синим каналом ввода, с учетом шага 8 из-за макета 8x8 в карте), а затем добавьте это смещение к вычислению значений x и y.

Однако я бы порекомендовал вам ознакомиться со встроенным CIColorCube filter в первую очередь, потому что он делает именно то, чего вы хотите достичь.

person Frank Schlegel    schedule 17.02.2019
comment
Спасибо за объяснение, решения пока не нашел. Однако он работал с CIColorCube и горизонтальным лютом вместо квадрата. Но я пытаюсь работать и понимать функцию поиска - person MIkael; 20.02.2019