颜色转换:稀疏表搜索

这是Pillow 5.2中引入的功能的概述:使用三维查找表(3D LUT)进行颜色转换。这项技术在视频处理和3D游戏中非常普遍,但是在此之前很少有图形库可以吹嘘3D LUT转换。


三维查找表为描述颜色转换提供了极大的灵活性,但是最重要的是,转换无论在多么复杂的情况下都可以同时执行。


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

完全用Python编写的功能可在75ms内应用于16.6百万像素的图片。



使用图像已经占用大量资源,因此我喜欢可以消除输入参数复杂性的算法。五年前,我在Pillow上实现了高斯模糊,同时在任何半径下工作。不久前,我谈到了如何在恒定时间内以最小的质量损失来缩小图像今天,我将向您展示可以使用3D LUT执行哪些任务,其局限性是什么,并且我在吹嘘Pillow-SIMD所实现的性能。


正常进行-这不正常


: , . - , ( 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 , . .



从测试结果可以看出,Pillow中的颜色转换比现有解决方案要快,并且使用SIMD指令可以飞向太空。我必须说,这仍然比对可以用C编写的大量转换进行优化的实现慢。但是,在搜索表方面,无论转换的数量和复杂性如何,通用性,简单性和稳定的时间。一个简单的API可让您快速开始使用颜色转换,而特殊的Pillow-lut库则使工作变得更加轻松。


All Articles