メインコンテンツへスキップ
ComfyUI ネイティブ Recraft Image Inpainting ノード Recraft Image Inpainting ノードは、画像の特定領域のみを編集し、残りの部分は変更せずに保持することができます。入力として画像、マスク、およびテキストプロンプトを指定することで、マスクで指定された領域に新しいコンテンツを生成・挿入できます。

パラメーター

基本パラメーター

パラメーターデフォルト説明
image画像-編集対象の入力画像
maskマスク-編集対象領域を定義する白黒マスク
prompt文字列""マスク領域内に生成するコンテンツの説明
n整数1生成する結果の数(1~6)
seed整数0乱数シード値

オプションパラメーター

パラメーター説明
recraft_styleRecraft Style生成コンテンツのスタイル設定
negative_prompt文字列生成コンテンツに含めたくない要素の指定
recraft_controlsRecraft Controls色など、その他の制御オプション

出力

出力説明
IMAGE画像編集後の画像結果

ソースコード

[ノードのソースコード(2025-05-03 更新)]
class RecraftImageInpaintingNode:
    """
    Modify image based on prompt and mask.
    """

    RETURN_TYPES = (IO.IMAGE,)
    DESCRIPTION = cleandoc(__doc__ or "")  # Handle potential None value
    FUNCTION = "api_call"
    API_NODE = True
    CATEGORY = "api node/image/Recraft"

    @classmethod
    def INPUT_TYPES(s):
        return {
            "required": {
                "image": (IO.IMAGE, ),
                "mask": (IO.MASK, ),
                "prompt": (
                    IO.STRING,
                    {
                        "multiline": True,
                        "default": "",
                        "tooltip": "Prompt for the image generation.",
                    },
                ),
                "n": (
                    IO.INT,
                    {
                        "default": 1,
                        "min": 1,
                        "max": 6,
                        "tooltip": "The number of images to generate.",
                    },
                ),
                "seed": (
                    IO.INT,
                    {
                        "default": 0,
                        "min": 0,
                        "max": 0xFFFFFFFFFFFFFFFF,
                        "control_after_generate": True,
                        "tooltip": "Seed to determine if node should re-run; actual results are nondeterministic regardless of seed.",
                    },
                ),
            },
            "optional": {
                "recraft_style": (RecraftIO.STYLEV3,),
                "negative_prompt": (
                    IO.STRING,
                    {
                        "default": "",
                        "forceInput": True,
                        "tooltip": "An optional text description of undesired elements on an image.",
                    },
                ),
            },
            "hidden": {
                "auth_token": "AUTH_TOKEN_COMFY_ORG",
            },
        }

    def api_call(
        self,
        image: torch.Tensor,
        mask: torch.Tensor,
        prompt: str,
        n: int,
        seed,
        auth_token=None,
        recraft_style: RecraftStyle = None,
        negative_prompt: str = None,
        **kwargs,
    ):
        default_style = RecraftStyle(RecraftStyleV3.realistic_image)
        if recraft_style is None:
            recraft_style = default_style

        if not negative_prompt:
            negative_prompt = None

        request = RecraftImageGenerationRequest(
            prompt=prompt,
            negative_prompt=negative_prompt,
            model=RecraftModel.recraftv3,
            n=n,
            style=recraft_style.style,
            substyle=recraft_style.substyle,
            style_id=recraft_style.style_id,
            random_seed=seed,
        )

        # prepare mask tensor
        _, H, W, _ = image.shape
        mask = mask.unsqueeze(-1)
        mask = mask.movedim(-1,1)
        mask = common_upscale(mask, width=W, height=H, upscale_method="nearest-exact", crop="disabled")
        mask = mask.movedim(1,-1)
        mask = (mask > 0.5).float()

        images = []
        total = image.shape[0]
        pbar = ProgressBar(total)
        for i in range(total):
            sub_bytes = handle_recraft_file_request(
                image=image[i],
                mask=mask[i:i+1],
                path="/proxy/recraft/images/inpaint",
                request=request,
                auth_token=auth_token,
            )
            images.append(torch.cat([bytesio_to_image_tensor(x) for x in sub_bytes], dim=0))
            pbar.update(1)

        images_tensor = torch.cat(images, dim=0)
        return (images_tensor, )