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

                       

             原图                                     前景图                                  色相混合结果                           

        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色相混合结果              

 

         

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值