Ps算法Python实现:图层混合模式-色相

1.相关文章

最近想要实现Photoshop图层混合中的色相模式,在网上查阅了众多关于混合模式实现的文章:

  1. Photoshop图层混合模式详解 
  2. PS中混合模式是什么意思?

  3. photoshop图层混合模式中色相模式的原理是什么?

  4. Sketch图层混合模式(Blending)详解 

  5. PS中27种图层混合模式原理详解

  6. Python: PS 图层混合算法汇总

  7. Python 模块layeris(GitHub:https://github.com/subwaymatch/layer-is-python/tree/fa10c2c7927a6a2b93f477bfdd57e254080308ce)

 其中关于色相模式的描述基本为:色相混合模式是选择基色的亮度和饱和度值与混合色进行混合而创建的效果,混合后的亮度及饱和度取决于基色,但色相取决于混合色。

其关于色相混合的Python实现是,背景变换到HSV然后直接替换色相H,再变换到rgb空间。并且实验GIMP软件(类似ps的开源软件),其效果也是如此。

    (代码来自layeris)
    def hue(self, target_hue):
        image_hsv_data = matplotlib.colors.rgb_to_hsv(self.image_data)
        image_hsv_data[:, :, 0] = target_hue

        self.image_data = matplotlib.colors.hsv_to_rgb(image_hsv_data)

        return self

Ps算法Python实现:图层混合模式-色相_第1张图片     Ps算法Python实现:图层混合模式-色相_第2张图片      Ps算法Python实现:图层混合模式-色相_第3张图片            

             原图                                     前景图                                  色相混合结果                           

Ps算法Python实现:图层混合模式-色相_第4张图片Ps算法Python实现:图层混合模式-色相_第5张图片

        GIMP色相混合结果         ps色相混合结果

分析:可以看到ps版本的结果看起来更加舒服,这是因为ps的结果除了应用了前景图的色相,还保持了原图的亮度。这里的亮度不是hsv空间的v,而是Lab空间的L。

2.类似Ps色相模式的Python实现

根据上述的实验和分析的结论,尝试同时进行两件事情:

  1. 原图保持使用前景图的色相H;
  2. 原图保持其原本的亮度L

然而,H更改将会导致L变化,L更改将会导致H、S变化,我采用了循环迭代上述2步操作,实现了和ps基本一致的色相混合。代码如下:

import cv2 as cv 
import numpy as np 
import matplotlib

class LayerImage(object):
    def __init__(self, image_data):
        self.image_data = image_data
    
    def hue_blend(self, blend_data, rep_times=2):
        '''
        色相模式图层混合,对前景图和底图,使用前景图在HSV空间的H(色相)替换底图的色相,同时保持底图在替换色相后Lab空间的L保持不变,
        而更改H和L是相互影响的,通过多次迭代H和L替换实现平衡
        blend_data: 提供色相的前景图,尺寸需和背景图一致
        rep_times: 迭代H和L替换的次数,为2时与ps效果相同
        '''
        assert self.image_data.shape[:2] == blend_data.shape[:2], 'the shape of blend_data is not same as image_data'
        
        image = self.image_data
        if self.image_data.shape[2] == 4:
            image_alpha = np.expand_dims(image[...,3], axis=2)
        else:
            image_alpha = None
       
        image_L = cv.cvtColor(image, cv.COLOR_BGR2LAB)[..., 0]
        color_map_H = cv.cvtColor(blend_data, cv.COLOR_BGR2HSV)[:,:,0]
        for i in range(rep_times):  #
            image_HSV =  cv.cvtColor(image, cv.COLOR_BGR2HSV)
            image_HSV[:,:,0] = color_map_H
            image_BGR = cv.cvtColor(image_HSV, cv.COLOR_HSV2BGR)
            image_Lab = cv.cvtColor(image_BGR, cv.COLOR_BGR2LAB)
            image_Lab[..., 0] = image_L 
            image = cv.cvtColor(image_Lab, cv.COLOR_LAB2BGR)

        image_HSV =  cv.cvtColor(image, cv.COLOR_BGR2HSV)
        image_HSV[:,:,0] = color_map_H
        image = cv.cvtColor(image_HSV, cv.COLOR_HSV2BGR)
        if not image_alpha is None:
            image = np.concatenate((image,image_alpha), axis=2)

        cv.imwrite('result3.png', image)
        return image

    def grayscale(self):
        self.image_data = np.dot(self.image_data[..., :3], [
                                 0.2989, 0.5870, 0.1140])

        self.image_data = np.stack(
            (self.image_data,) * 3, axis=-1)

        return self

if __name__ == "__main__":  
    color_map = cv.imread('标准主体_拓色副本.png', cv.IMREAD_UNCHANGED)
    image = cv.imread('标准主体.png', cv.IMREAD_UNCHANGED)

    a = LayerImage(image).grayscale().image_data
    cv.imwrite('result3.png', a)
    LayerImage(image).hue_blend(color_map, rep_times=2)
    

结果:

Ps算法Python实现:图层混合模式-色相_第6张图片     Ps算法Python实现:图层混合模式-色相_第7张图片       Ps算法Python实现:图层混合模式-色相_第8张图片      Ps算法Python实现:图层混合模式-色相_第9张图片

             原图                                     前景图                               实现效果                            ps色相混合结果              

 

         

 

你可能感兴趣的:(Photoshop图像处理,python)