Tabla de búsqueda de colores LUT

La tabla de búsqueda (LUT, LookUp Table) es una poderosa herramienta para la conversión del color de la imagen, utilizada en muchos editores de gráficos y video.

LUT 2D

CLUT-de-imágenes

Generación de LUT 2D

def generate_identify_color_matrix(width, height, channel):
    img = np.zeros((width, height, channels), dtype=np.uint8)
    for by in range(8):
        for bx in range(8):
            for g in range(64):
                for r in range(64):
                    x = r + bx * 64
                    y = g + by * 64
                    img[y][x][0] = int(r * 255.0 / 63.0 + 0.5)
                    img[y][x][1] = int(g * 255.0 / 63.0 + 0.5)
                    img[y][x][2] = int((bx + by * 8.0) * 255.0 / 63.0 + 0.5)
    return img
 identity_lut = generate_identify_color_matrix()

Inserte la descripción de la imagen aquí

LUT 2D para conversión de imágenes

from typing import Tuple
from functools import lru_cache
from math import floor
import numpy as np
import cv2

def lut_apply(image, lut):
    img_list = image.tolist()
    # dst_img = image.copy()
    dst_img = np.zeros((image.shape[0], image.shape[1], image.shape[2]), dtype=np.uint8)
    for iy in range(image.shape[0]):
        for ix in range(image.shape[1]):
            b, g, r = img_list[iy][ix] #bgr mode
            x, y, bx, by = color_coordinate(r, g, b)
            lut_y = y + by * 64
            lut_x = x + bx * 64
            dst_img[iy][ix][0] = lut[lut_y][lut_x][0]
            dst_img[iy][ix][1] = lut[lut_y][lut_x][1]
            dst_img[iy][ix][2] = lut[lut_y][lut_x][2]
    return dst_img
@lru_cache(maxsize=512)
def color_coordinate(r, g, b) -> Tuple[int, int, int, int]:
    x, y, bx, by = 0, 0, 0, 0
    x = floor(r / 4.0)
    y = floor(g / 4.0)
    bx, by = blue_coordinate(floor(b / 4.0))
    return x, y, bx, by


@lru_cache(maxsize=64)
def blue_coordinate(b: int) -> Tuple[int, int]:
    assert b >= 0 and b <= 63, 'GOT {}'.format(b)
    x, y = 0, 0
    y = floor(floor(b) / 8.0)
    x = int(floor(b) - y * 8.0)
    return x, y
    
image = cv2.imread('./test.jpg')
lut = cv2.imread('./YV2.JPG')
result_img = lut_apply(image, lut)
cv2.imwrite('./test_YV2_cv.jpg', result_img)
Manera rápida:
class LUT_WHITEN:
    def __init__(self, lut):
        cube64rows = 8
        cube64size = 64
        cube256size = 256
        cubescale = (int)(cube256size / cube64size) #4

        reshapelut = np.zeros((cube256size, cube256size, cube256size, 3))
        for i in range(cube64size):
            tmp = math.floor(i / cube64rows)
            cx = int((i - tmp * cube64rows) * cube64size)
            cy = int(tmp * cube64size)
            cube64 = lut[cy:cy+cube64size, cx:cx+cube64size]#cube64 in lut(512*512 (512=8*64))
            _rows, _cols, _ = cube64.shape
            if _rows == 0 or _cols == 0:
                continue
            cube256 = cv2.resize(cube64, (cube256size, cube256size))
            i = i * cubescale
            for k in range(cubescale):
                reshapelut[i + k] = cube256
        self.lut = reshapelut
        # print('reshapelut shape:', reshapelut.shape)

    def imageInLut(self, src):
        arr = src.copy()
        bs = arr[:, :, 0]
        gs = arr[:, :, 1]
        rs = arr[:, :, 2]
        arr[:, :] = self.lut[bs, gs, rs]
        return arr

3D LUT

Formatos comunes de 3D LUT:

  • Hald CLUT (.png)
  • 3D LUT (.3dl)
  • Cubo LUT (.cube)

Generación 3D LUT (Hald CLUT)

reconstrucción-filtros-de-color

  • Crear imagen de identidad (3D LUT)

    ./bin/generate.py
    
    def generate_hald(size):
        b, g, r = numpy.mgrid[
            0 : 255 : size**2*1j,
            0 : 255 : size**2*1j,
            0 : 255 : size**2*1j
        ].astype(numpy.uint8)
    
        rgb = numpy.stack((r, g, b), axis=-1)
        return Image.fromarray(rgb.reshape(size**3, size**3, 3))
    

    Para evitar la distorsión que pueda ocurrir durante la transformación, como viñeteado, rayones, gradación y artefactos JPEG. Generado 25 × 25 × 25 25 \ times 25 \ times 252 5×2 5×La imagen de hadl de 2 5 d es la siguiente (se muestran 4):
    Tabla de consulta de 25x25x25

  • Utilice un software de procesamiento de imágenes para transformar la imagen hald para obtener la imagen hald filtrada del mismo tamaño.
    Inserte la descripción de la imagen aquí

  • Método mejorado, que utiliza la imagen filtrada Desenfoque gaussiano para procesar y reducir el ruido.
    Si el filtro de destino está muy distorsionado a nivel local o el centro de la imagen tiene un gradiente significativo, pueden aparecer algunos efectos indeseables. La imagen filtrada en cuestión es la siguiente:
    Inserte la descripción de la imagen aquí

     ./bin/convert.py raw/15.Hudson.jpg halds/ --smooth 1.5
    
  • Convierta la imagen filtrada en una imagen de hald real (una de las 4 mostradas está recortada).
    Inserte la descripción de la imagen aquí

3D LUT (Hald CLUT) aplicado a imágenes (biblioteca de almohadas)

pillow-lut-tools Herramientas
Pillow LUT Las herramientas
Pillow LUT contienen herramientas para cargar, operar y generar tablas de búsqueda 3D, y están diseñadas específicamente para la biblioteca Pillow.

from PIL import Image
from pillow_lut import load_hald_image

hefe = load_hald_image('./res/test_hald.5.png')
img = Image.open('./res/test.jpg')
img.filter(hefe).save('./res/test.hald.jpg')

Funciones incluidas en Pillow LUT:

  • load_cube_file carga la tabla de búsqueda 3D desde el formato de archivo .cube
    Inserte la descripción de la imagen aquí

  • load_hald_image carga una tabla de búsqueda 3D desde una imagen Hald (generalmente un archivo .png o .tiff).
    Inserte la descripción de la imagen aquí

  • identity_table devuelve una tabla de búsqueda noop con valores distribuidos linealmente.
    Inserte la descripción de la imagen aquí

  • rgb_color_enhance genera una tabla de búsqueda de color tridimensional basada en el valor dado de la configuración de color básica.
    Inserte la descripción de la imagen aquí

  • sample_lut_linear utiliza la interpolación lineal para calcular nuevos valores de puntos a partir de una tabla de búsqueda tridimensional determinada.
    Inserte la descripción de la imagen aquí

  • sample_lut_cubic usa interpolación cúbica para calcular nuevos valores de puntos a partir de una tabla de búsqueda tridimensional dada.
    Inserte la descripción de la imagen aquí

  • resize_lut usa la interpolación para cambiar el tamaño de la tabla de búsqueda dada al nuevo tamaño.
    Inserte la descripción de la imagen aquí

  • transform_lut usa otra tabla para transformar la tabla de búsqueda dada y devuelve el resultado.
    Inserte la descripción de la imagen aquí

  • amplity_lut amplifica la tabla de búsqueda dada
    Inserte la descripción de la imagen aquí

Ejemplo de uso de la función Pillow LUT:

from PIL import Image
from pillow_lut import load_hald_image

hefe = load_hald_image('./res/hald.6.hefe.png')
im = Image.open('./res/pineapple.jpeg')
im.filter(hefe).save('./res/pineapple.hefe.jpeg')

Inserte la descripción de la imagen aquí

from pillow_lut import rgb_color_enhance

lut = rgb_color_enhance(11, exposure=0.2, contrast=0.1, vibrance=0.5, gamma=1.3)
im = Image.open('./res/pineapple.jpeg')
im.filter(lut).save('./res/pineapple.enhance.jpeg')

Inserte la descripción de la imagen aquí

from pillow_lut import load_hald_image, rgb_color_enhance

hefe = load_hald_image('./res/hald.6.hefe.png')
lut = rgb_color_enhance(hefe, exposure=0.2, contrast=0.1, vibrance=0.5, gamma=1.3)
im = Image.open('./res/pineapple.jpeg')
im.filter(lut).save('./res/pineapple.hefe.enhance.jpeg')

Inserte la descripción de la imagen aquí

3D LUT (Hald CLUT) convertido a 2D cuadrado CLUT

import numpy, cv2

hald = cv2.imread('1.Clarendon.png')

size = int(hald.shape[0] ** (1.0/3.0) + .5)
clut = numpy.concatenate([
    numpy.concatenate(im.reshape((size, size, size**2, size**2, 3))[row], axis=1)
    for row in range(size)
])

cv2.imwrite("clut.png", clut)

Conversión entre 2D LUT y 3D LUT

El diagrama de conversión de un solo canal es fácil de entender Las áreas propensas a errores de 3D LUT a 2D LUT se han marcado en rojo.
Inserte la descripción de la imagen aquí

Conversión de 2D LUT a 3D LUT

# 2D LUT(size**3, size**3, 3) ->  3D LUT(size**3, size**3, 3)
clut = cv2.imread('./identity_clut_8.png')
size = int(clut.shape[0] ** (1.0 / 3.0) + 0.5)
clut_result = np.zeros((size ** 2, size ** 2, size ** 2, 3))
for i in range(size ** 2):
    tmp1 = math.floor(i / size)
    cx = int((i - tmp1 * size) * size ** 2)
    cy = int(tmp1 * size ** 2)
    clut_result[i] = clut[cy: cy + size ** 2, cx : cx + size ** 2]

hald = clut_result.reshape((size ** 3, size ** 3, 3))

cv2.imwrite('./identity_hald_{}_test.png'.format(size), hald)

Conversión de 3D LUT a 2D LUT

#3D LUT(size**3, size**3, 3) ->  2D LUT(size**3, size**3, 3)
hald = cv2.imread('./identity_hald_8.png')

size = int(hald.shape[0] ** (1.0/3.0) + .5)
#method1
clut = np.concatenate([
    np.concatenate(hald.reshape((size, size, size**2, size**2, 3))[row], axis=1)
    for row in range(size)
])
cv2.imwrite("2d_identity.png", clut)
#method2
hald_reshape = hald.reshape((size, size, size ** 2, size ** 2, 3))
print('hald_reshape shape:', hald_reshape.shape)
img_list = []
for i in range(size):
    print('hald_reshape[i] shape:', hald_reshape[i].shape)
    tmp = np.concatenate(hald_reshape[i], axis=1)
    print('tmp shape:', tmp.shape)
    img_list.append(tmp)

result = np.concatenate(img_list)
print('result shape:', result.shape)

cv2.imwrite("identity_clut_8_test.png", result)

Referencia

filtros de color-reconstrucción
de almohada-LUT herramientas
herramientas Almohada LUT
Crear su propio LUT
CLUT-de-imágenes

Supongo que te gusta

Origin blog.csdn.net/studyeboy/article/details/112554067
Recomendado
Clasificación