Transformación de color: búsquedas de tabla de adelgazamiento

Esta es una descripción general de la funcionalidad introducida en Pillow 5.2 : el uso de tablas de búsqueda tridimensionales (LUT 3D) para la transformación del color. Esta técnica está muy extendida en el procesamiento de video y los juegos 3D, pero pocas bibliotecas gráficas podrían presumir de transformaciones 3D LUT antes de eso.


Las tablas de búsqueda tridimensionales proporcionan una gran flexibilidad para describir las transformaciones de color, pero lo más importante, las transformaciones se realizan al mismo tiempo, sin importar cuán complejas sean.


from PIL import Image, ImageFilter

def washout(r, g, b):
    h, s, v = _rgb_to_hsv(r, g, b)
    if 0.3 < h < 0.7:
        s = 0
    return _hsv_to_rgb(h, s, v)

im = Image.open('./Puffins.jpg')
im = im.filter(ImageFilter.Color3DLUT.generate(17, washout))

Una característica totalmente escrita en Python se aplica a una imagen de 16.6 megapíxeles en 75 ms.



Trabajar con imágenes ya requiere muchos recursos, por lo que me encantan los algoritmos que eliminan la complejidad de los parámetros de entrada. Hace cinco años, implementé un desenfoque gaussiano en Pillow , trabajando al mismo tiempo para cualquier radio. No hace mucho tiempo, hablé sobre cómo puede reducir la imagen en tiempo constante con una pérdida mínima de calidad. Hoy te mostraré para qué tareas puedes usar 3D LUT, cuáles son sus limitaciones y presumiré del rendimiento alcanzado en Pillow-SIMD.


Hazlo normalmente, no será normal


: , . - , ( 0 255). , HSV , Hue, , , Saturation, , , Value, . , , Saturation - , . .


? , , . - , , . API, , , , . .


, , . , , , . , : , , , . API — .



- . , . , , , . , , - !


, . . , , RGB #e51288, [229, 18, 136]. — , RGB-. :



. 256³, 16 , 48 . 48 — . , L3 , . , 16 , 16 , , , . ?


, . , -- , . , , , 16³ . 12 , L3, L1 .



? — . , , ( ) .


, , . , , , . , .


3D LUT


, - . : , , , , . . . , -, . .


: , , , . , , .


, , . , , , . , . , , , - ( , ) .


?


, Pillow. API Color3DLUT PIL.ImageFilter. , :


from PIL.ImageFilter import Color3DLUT

table = [(0, 0, 0), (1, 0, 0), (0, 1, 0), (1, 1, 0),
         (0, 0, 1), (1, 0, 1), (0, 1, 1), (1, 1, 1)]
lut = Color3DLUT(2, table)

— . , . :


from PIL import Image
Image.open('in.jpg').filter(lut).save('out.jpg')

, . - , :



— - , generate, . , . 3D-.


def transform(r, g, b):
    r, g, b = (max(r, g, b), g, min(r, g, b))
    avg_v = r * 0.2126 + g * 0.7152 + b * 0.0722
    r += (r - avg_v) * 0.6
    g += (g - avg_v) * 0.6
    b += (b - avg_v) * 0.6
    return r, g, b

lut = Color3DLUT.generate(17, transform)
Image.open('in.jpg').filter(lut).save('out.jpg')


- , . : - , . , . Pillow-lut. rgb_color_enhance, :


from pillow_lut import rgb_color_enhance
lut = rgb_color_enhance(
    11, exposure=1, contrast=0.3, vibrance=-0.2, warmth=0.3)
Image.open('in.jpg').filter(lut).save('out.jpg')


, , ? : .cube ( , ) hald- — , .



Pillow-lut .


from pillow_lut import load_hald_image 
lut = load_hald_image('hald.6.hefe.png')
Image.open('in.jpg').filter(lut).save('out.jpg')


— , , ! , , . rgb_color_enhance , , :


lut = load_hald_image('hald.6.hefe.png')
lut = rgb_color_enhance(
    lut, exposure=1, contrast=0.3, vibrance=-0.2, warmth=0.3)
Image.open('in.jpg').filter(lut).save('out.jpg')


, . rgb_color_enhance. transform_lut, .


, «». ? . , 1, , — . . amplify_lut:


from pillow_lut import load_hald_image, amplify_lut
lut = load_hald_image('hald.6.hefe.png')
lut = amplify_lut(lut, scale=3.0)
Image.open('in.jpg').filter(lut).save('out.jpg')



: , . , ? , ( . : ).


, Pillow 5.2 16- ( ). , . 16- .


, 7 . 21 . , , . , ( 6 ), 2,5 , , . , SIMD-.


. ImageMagick GraphicsMagick. — LittleCMS — icc- . , , . , perf, PrelinEval8, , .



Intel Core i5-8279U.


Pillow-SIMD — Pillow, x86 . 100% Pillow . , , , Pillow 5.4, Pillow-SIMD 7.0. Pillow , . .



Como se puede ver en los resultados de la prueba, la transformación del color en Pillow es más rápida que las soluciones existentes, y con el uso de las instrucciones SIMD vuela al espacio. Debo decir que esto aún puede ser más lento que una implementación bien optimizada de un número bastante grande de transformaciones que podrían escribirse en C. Pero en el lado de las tablas de búsqueda, versatilidad, simplicidad y tiempo estable, independientemente del número y la complejidad de las transformaciones. Una API simple le permite comenzar rápidamente a usar transformaciones de color, y una biblioteca especial Pillow-lut hace que sea aún más fácil trabajar.


All Articles