图像混合方法

from .imagefunc import *
# 从当前目录中的 imagefunc 模块导入所有函数和变量

NODE_NAME = 'ImageBlend'
# 定义节点名称为 'ImageBlend'

class ImageBlend:
    # 定义一个名为 ImageBlend 的类

    def __init__(self):
        # 初始化函数
        pass

    @classmethod
    def INPUT_TYPES(self):
        # 定义一个类方法 INPUT_TYPES,返回输入参数的类型
        return {
            "required": {
                "background_image": ("IMAGE", ),  # 背景图像
                "layer_image": ("IMAGE",),  # 图层图像
                "invert_mask": ("BOOLEAN", {"default": True}),  # 反转掩码,默认值为 True
                "blend_mode": (chop_mode,),  # 混合模式
                "opacity": ("INT", {"default": 100, "min": 0, "max": 100, "step": 1}),  # 透明度,默认值为 100,范围从 0 到 100,步长为 1
            },
            "optional": {
                "layer_mask": ("MASK",),  # 可选的图层掩码
            }
        }

    RETURN_TYPES = ("IMAGE",)
    # 返回类型为图像
    RETURN_NAMES = ("image",)
    # 返回的名称为图像
    FUNCTION = 'image_blend'
    # 定义主要功能函数为 'image_blend'
    CATEGORY = '😺dzNodes/LayerUtility'
    # 设置类别为 '😺dzNodes/LayerUtility'

    def image_blend(self, background_image, layer_image, invert_mask, blend_mode, opacity, layer_mask=None):
        # 定义图像混合的主要功能
        b_images = []
        # 初始化背景图像列表
        l_images = []
        # 初始化图层图像列表
        l_masks = []
        # 初始化图层掩码列表
        ret_images = []
        # 初始化返回图像列表

        for b in background_image:
            b_images.append(torch.unsqueeze(b, 0))
            # 将每个背景图像添加到背景图像列表中,并在第 0 维增加一个维度
        for l in layer_image:
            l_images.append(torch.unsqueeze(l, 0))
            # 将每个图层图像添加到图层图像列表中,并在第 0 维增加一个维度
            m = tensor2pil(l)
            # 将图层图像从张量转换为 PIL 图像
            if m.mode == 'RGBA':
                l_masks.append(m.split()[-1])
                # 如果图层图像是 RGBA 模式,将 Alpha 通道添加到图层掩码列表中
            else:
                l_masks.append(Image.new('L', m.size, 'white'))
                # 否则,创建一个白色的 L 模式图像作为掩码,并添加到图层掩码列表中

        if layer_mask is not None:
            if layer_mask.dim() == 2:
                layer_mask = torch.unsqueeze(layer_mask, 0)
                # 如果提供了图层掩码并且其维度为 2,增加一个维度
            l_masks = []
            for m in layer_mask:
                if invert_mask:
                    m = 1 - m
                    # 如果需要反转掩码,将掩码取反
                l_masks.append(tensor2pil(torch.unsqueeze(m, 0)).convert('L'))
                # 将掩码从张量转换为 PIL 图像并添加到图层掩码列表中

        max_batch = max(len(b_images), len(l_images), len(l_masks))
        # 计算批次的最大长度

        for i in range(max_batch):
            background_image = b_images[i] if i < len(b_images) else b_images[-1]
            # 获取当前批次的背景图像
            layer_image = l_images[i] if i < len(l_images) else l_images[-1]
            # 获取当前批次的图层图像
            _mask = l_masks[i] if i < len(l_masks) else l_masks[-1]
            # 获取当前批次的图层掩码

            _canvas = tensor2pil(background_image).convert('RGB')
            # 将背景图像转换为 RGB 模式的 PIL 图像
            _layer = tensor2pil(layer_image).convert('RGB')
            # 将图层图像转换为 RGB 模式的 PIL 图像

            if _mask.size != _layer.size:
                _mask = Image.new('L', _layer.size, 'white')
                # 如果掩码的大小与图层图像不同,创建一个白色的 L 模式掩码
                log(f"Warning: {NODE_NAME} mask mismatch, dropped!", message_type='warning')
                # 记录掩码大小不匹配的警告

            # 合成图层
            _comp = chop_image(_canvas, _layer, blend_mode, opacity)
            # 根据混合模式和透明度将图层图像合成到背景图像上
            _canvas.paste(_comp, mask=_mask)
            # 使用掩码将合成结果粘贴到背景图像上

            ret_images.append(pil2tensor(_canvas))
            # 将合成后的图像转换回张量并添加到返回图像列表中

        log(f"{NODE_NAME} Processed {len(ret_images)} image(s).", message_type='finish')
        # 记录处理的图像数量
        return (torch.cat(ret_images, dim=0),)
        # 返回连接后的结果图像张量

主要步骤和功能

  1. 类定义和初始化

    • ImageBlend 类用于图像混合操作,初始化函数为空。
  2. 定义输入类型

    • INPUT_TYPES 类方法定义了所需的输入类型,包括背景图像、图层图像、反转掩码选项、混合模式和透明度,以及可选的图层掩码。
  3. 定义返回类型

    • RETURN_TYPESRETURN_NAMES 定义了返回类型和名称为图像。
    • FUNCTION 定义了主要功能函数为 image_blend
  4. 图像混合方法

    • image_blend 方法是核心功能,处理图像混合逻辑。
    • 将背景图像、图层图像和掩码从张量转换为 PIL 图像,并根据输入参数进行图像混合。
    • 使用 chop_image 函数根据混合模式和透明度将图层图像合成到背景图像上,并使用掩码粘贴到背景图像上。
    • 最后,将合成后的图像转换回张量并返回。
  5. 节点映射

    • NODE_CLASS_MAPPINGSNODE_DISPLAY_NAME_MAPPINGS 将节点名称和显示名称映射到 ImageBlend 类。

 

分段解释

 1. 引入和类定义

```python
from .imagefunc import *
# 从当前目录中的 imagefunc 模块导入所有函数和变量

NODE_NAME = 'ImageBlend'
# 定义节点名称为 'ImageBlend'

class ImageBlend:
    # 定义一个名为 ImageBlend 的类

    def __init__(self):
        # 初始化函数
        pass
```

这段代码引入了当前目录中的 `imagefunc` 模块中的所有函数和变量,并定义了一个名为 `ImageBlend` 的类。`NODE_NAME` 用于指定节点的名称,`__init__` 初始化函数为空,不执行任何操作。

2. 输入类型定义

```python
    @classmethod
    def INPUT_TYPES(self):
        # 定义一个类方法 INPUT_TYPES,返回输入参数的类型
        return {
            "required": {
                "background_image": ("IMAGE", ),  # 背景图像
                "layer_image": ("IMAGE",),  # 图层图像
                "invert_mask": ("BOOLEAN", {"default": True}),  # 反转掩码,默认值为 True
                "blend_mode": (chop_mode,),  # 混合模式
                "opacity": ("INT", {"default": 100, "min": 0, "max": 100, "step": 1}),  # 透明度,默认值为 100,范围从 0 到 100,步长为 1
            },
            "optional": {
                "layer_mask": ("MASK",),  # 可选的图层掩码
            }
        }
```

这段代码定义了一个类方法 `INPUT_TYPES`,用于指定 `ImageBlend` 节点所需的输入类型。包括必需的参数(背景图像、图层图像、反转掩码选项、混合模式和透明度)和可选的参数(图层掩码)。

3. 返回类型和类别定义

```python
    RETURN_TYPES = ("IMAGE",)
    # 返回类型为图像
    RETURN_NAMES = ("image",)
    # 返回的名称为图像
    FUNCTION = 'image_blend'

```

这段代码定义了 `ImageBlend` 节点的返回类型和名称。`RETURN_TYPES` 和 `RETURN_NAMES` 分别指定了返回的类型和名称为图像。`FUNCTION` 指定了主要功能函数为 `image_blend`

4. 图像混合方法

```python
    def image_blend(self, background_image, layer_image, invert_mask, blend_mode, opacity, layer_mask=None):
        # 定义图像混合的主要功能
        b_images = []
        # 初始化背景图像列表
        l_images = []
        # 初始化图层图像列表
        l_masks = []
        # 初始化图层掩码列表
        ret_images = []
        # 初始化返回图像列表
```

`image_blend` 方法是 `ImageBlend` 类的核心功能,用于处理图像混合逻辑。首先初始化了背景图像列表、图层图像列表、图层掩码列表和返回图像列表。

### 5. 处理背景图像和图层图像

```python
        for b in background_image:
            b_images.append(torch.unsqueeze(b, 0))
            # 将每个背景图像添加到背景图像列表中,并在第 0 维增加一个维度
        for l in layer_image:
            l_images.append(torch.unsqueeze(l, 0))
            # 将每个图层图像添加到图层图像列表中,并在第 0 维增加一个维度
            m = tensor2pil(l)
            # 将图层图像从张量转换为 PIL 图像
            if m.mode == 'RGBA':
                l_masks.append(m.split()[-1])
                # 如果图层图像是 RGBA 模式,将 Alpha 通道添加到图层掩码列表中
            else:
                l_masks.append(Image.new('L', m.size, 'white'))
                # 否则,创建一个白色的 L 模式图像作为掩码,并添加到图层掩码列表中
```

这段代码将背景图像和图层图像分别添加到各自的列表中,并在第 0 维增加一个维度。同时,如果图层图像是 RGBA 模式,将其 Alpha 通道作为掩码添加到 `l_masks` 列表中,否则创建一个白色的 L 模式图像作为掩码。

 6. 处理图层掩码

```python
        if layer_mask is not None:
            if layer_mask.dim() == 2:
                layer_mask = torch.unsqueeze(layer_mask, 0)
                # 如果提供了图层掩码并且其维度为 2,增加一个维度
            l_masks = []
            for m in layer_mask:
                if invert_mask:
                    m = 1 - m
                    # 如果需要反转掩码,将掩码取反
                l_masks.append(tensor2pil(torch.unsqueeze(m, 0)).convert('L'))
                # 将掩码从张量转换为 PIL 图像并添加到图层掩码列表中
```

这段代码检查是否提供了图层掩码。如果提供了并且其维度为 2,则增加一个维度。然后,根据 `invert_mask` 参数决定是否反转掩码,并将掩码从张量转换为 PIL 图像,添加到 `l_masks` 列表中。

 7. 处理每批图像

```python
        max_batch = max(len(b_images), len(l_images), len(l_masks))
        # 计算批次的最大长度

        for i in range(max_batch):
            background_image = b_images[i] if i < len(b_images) else b_images[-1]
            # 获取当前批次的背景图像
            layer_image = l_images[i] if i < len(l_images) else l_images[-1]
            # 获取当前批次的图层图像
            _mask = l_masks[i] if i < len(l_masks) else l_masks[-1]
            # 获取当前批次的图层掩码
```

这段代码计算批次的最大长度,并在循环中处理每批图像。根据索引获取当前批次的背景图像、图层图像和图层掩码。

8. 图像合成和掩码应用

```python
            _canvas = tensor2pil(background_image).convert('RGB')
            # 将背景图像转换为 RGB 模式的 PIL 图像
            _layer = tensor2pil(layer_image).convert('RGB')
            # 将图层图像转换为 RGB 模式的 PIL 图像

            if _mask.size != _layer.size:
                _mask = Image.new('L', _layer.size, 'white')
                # 如果掩码的大小与图层图像不同,创建一个白色的 L 模式掩码
                log(f"Warning: {NODE_NAME} mask mismatch, dropped!", message_type='warning')
                # 记录掩码大小不匹配的警告

            # 合成图层
            _comp = chop_image(_canvas, _layer, blend_mode, opacity)
            # 根据混合模式和透明度将图层图像合成到背景图像上
            _canvas.paste(_comp, mask=_mask)
            # 使用掩码将合成结果粘贴到背景图像上

            ret_images.append(pil2tensor(_canvas))
            # 将合成后的图像转换回张量并添加到返回图像列表中
```

这段代码将背景图像和图层图像转换为 RGB 模式的 PIL 图像。如果掩码的大小与图层图像不同,创建一个白色的 L 模式掩码,并记录警告。然后,使用 `chop_image` 函数根据混合模式和透明度将图层图像合成到背景图像上,并使用掩码将合成结果粘贴到背景图像上。最后,将合成后的图像转换回张量并添加到返回图像列表中。

 9. 返回结果

```python
        log(f"{NODE_NAME} Processed {len(ret_images)} image(s).", message_type='finish')
        # 记录处理的图像数量
        return (torch.cat(ret_images, dim=0),)
        # 返回连接后的结果图像张量
```

这段代码记录处理的图像数量,并返回连接后的结果图像张量。

总结

这个 `ImageBlend` 类主要用于在图像处理工作流中,将背景图像和图层图像根据指定的混合模式和透明度进行混合,并返回合成后的图像。通过详细注释每段代码,可以更清晰地理解每一步的具体作用和处理逻辑。

  • 23
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值