Chuyển đến nội dung chính

レッスン 10: AI 編集アシスタント — 自然言語でのデザインの編集

英語/ベトナム語のコマンド「ネオンを明るくする」、「デザインを上に移動する」、「色を紫に変更する」を受け取る AI エディターを構築します。画像編集用の InstructPix2Pix、Instruct-NeRF2NeRF。 LLM ルーティングの意図。

🧠 AI と ML — レッスン 9 レッスン 10: AI 編集アシスタント — 編集 自然言語でデザインする

AI の活用: ファッションとプリント オン デマンド向けの AI プラットフォームの構築

パート 3: AI 設計の最適化と編集

xdev.asia

はじめに

デザインを作成した後、ユーザーは編集したいと考えています: 「ネオンを明るくする」、「デザインを上に移動する」、「色を紫に変更する」。このプラットフォームでは、ユーザーに Photoshop の使用を強制するのではなく、自然言語でのデザイン編集が可能です。この記事では AI 編集アシスタントを構築します。


1. カテゴリを編集する

User instructions phân loại thành 4 nhóm:

1. LAYOUT EDITING
   "move design higher"
   "make it smaller"
   "rotate 15 degrees"
   "center the design"

2. STYLE EDITING
   "make neon brighter"
   "add shadow effect"
   "change to grayscale"
   "add texture"

3. COLOR EDITING
   "change color to purple"
   "make it more vibrant"
   "darken the background"
   "invert colors"

4. CONTENT EDITING
   "remove the text"
   "add a skull"
   "replace cat with dog"
   "add lightning effect"

2. インテントルーター (LLM 搭載)

class EditIntentRouter:
    """Phân tích lệnh edit và route đến handler phù hợp"""

    ROUTING_PROMPT = """
You are an edit intent classifier for a t-shirt design editor.

Classify the user's edit instruction into exactly ONE category:
- LAYOUT: move, resize, rotate, center, align, position
- STYLE: brightness, contrast, shadow, glow, texture, filter, effect
- COLOR: change color, hue, saturation, vibrance, invert, grayscale
- CONTENT: add element, remove element, replace, modify content
- REGENERATE: completely redo, start over, try again

Also extract parameters:
- For LAYOUT: direction, amount, anchor
- For COLOR: target_color, source_color
- For STYLE: effect_name, intensity
- For CONTENT: action, subject

Respond in JSON format.
User instruction: {instruction}
"""

    async def route(self, instruction: str) -> EditIntent:
        response = await self.llm.chat.completions.create(
            model="gpt-4o-mini",
            messages=[{
                "role": "system",
                "content": self.ROUTING_PROMPT.format(
                    instruction=instruction
                )
            }],
            response_format={"type": "json_object"},
            temperature=0,
        )

        intent_data = json.loads(
            response.choices[0].message.content
        )

        return EditIntent(
            category=intent_data["category"],
            params=intent_data.get("params", {}),
            original_instruction=instruction,
        )

3. レイアウトエディター (プログラムによる)

class LayoutEditor:
    """Xử lý layout editing — không cần AI model"""

    def apply(
        self, design: Image.Image, intent: EditIntent
    ) -> Image.Image:
        params = intent.params

        action = params.get("action", "move")

        if action == "move":
            return self._move(
                design,
                direction=params.get("direction", "up"),
                amount=params.get("amount", 10),  # percent
            )
        elif action == "resize":
            return self._resize(
                design,
                scale=params.get("scale", 1.1),
            )
        elif action == "rotate":
            return self._rotate(
                design,
                angle=params.get("angle", 15),
            )
        elif action == "center":
            return self._center(design)

        return design

    def _move(
        self, img: Image.Image, direction: str, amount: int
    ) -> Image.Image:
        """Move design trong canvas"""
        canvas = Image.new("RGBA", img.size, (0, 0, 0, 0))
        offset_px = int(img.height * amount / 100)

        offsets = {
            "up": (0, -offset_px),
            "down": (0, offset_px),
            "left": (-offset_px, 0),
            "right": (offset_px, 0),
        }
        dx, dy = offsets.get(direction, (0, 0))
        canvas.paste(img, (dx, dy), img)
        return canvas

4. スタイルエディター (AI 搭載)

class StyleEditor:
    """AI-based style editing với InstructPix2Pix"""

    def __init__(self):
        from diffusers import (
            StableDiffusionInstructPix2PixPipeline
        )
        self.pipe = (
            StableDiffusionInstructPix2PixPipeline.from_pretrained(
                "timbrooks/instruct-pix2pix",
                torch_dtype=torch.float16,
            )
        )
        self.pipe.to("cuda")

    def apply(
        self,
        design: Image.Image,
        instruction: str,
        strength: float = 0.5,
    ) -> Image.Image:
        """
        Apply style edit bằng natural language

        strength: 0.3 (subtle) → 0.8 (dramatic)
        """
        result = self.pipe(
            prompt=instruction,
            image=design,
            num_inference_steps=20,
            image_guidance_scale=1.5,
            guidance_scale=7.5,
        ).images[0]

        return result

5. カラーエディター

class ColorEditor:
    """Chỉnh màu design"""

    def change_color(
        self,
        design: Image.Image,
        source_color: str | None,
        target_color: str,
    ) -> Image.Image:
        """Đổi màu design"""
        import numpy as np
        from colorsys import rgb_to_hsv, hsv_to_rgb

        img_array = np.array(design.convert("RGBA"))
        rgb = img_array[:, :, :3].astype(float) / 255

        target_rgb = self._hex_to_rgb(target_color)
        target_hsv = rgb_to_hsv(*target_rgb)

        # Convert to HSV
        h, s, v = np.vectorize(rgb_to_hsv)(
            rgb[:, :, 0], rgb[:, :, 1], rgb[:, :, 2]
        )

        # Shift hue to target, keep saturation and value
        h_new = np.full_like(h, target_hsv[0])
        s_new = s * (target_hsv[1] / max(np.mean(s), 0.01))
        s_new = np.clip(s_new, 0, 1)

        # Convert back
        r, g, b = np.vectorize(hsv_to_rgb)(h_new, s_new, v)
        result = np.stack([r, g, b], axis=-1) * 255

        img_array[:, :, :3] = result.astype(np.uint8)
        return Image.fromarray(img_array)

    def adjust_brightness(
        self, design: Image.Image, factor: float
    ) -> Image.Image:
        from PIL import ImageEnhance
        enhancer = ImageEnhance.Brightness(design)
        return enhancer.enhance(factor)

    def adjust_vibrance(
        self, design: Image.Image, factor: float
    ) -> Image.Image:
        from PIL import ImageEnhance
        enhancer = ImageEnhance.Color(design)
        return enhancer.enhance(factor)

6. 統合編集パイプライン

class EditingAssistant:
    """Unified pipeline cho tất cả editing operations"""

    def __init__(self):
        self.router = EditIntentRouter()
        self.editors = {
            "LAYOUT": LayoutEditor(),
            "STYLE": StyleEditor(),
            "COLOR": ColorEditor(),
            "CONTENT": ContentEditor(),
        }

    async def edit(
        self,
        design: Image.Image,
        instruction: str,
    ) -> EditResult:
        # 1. Route intent
        intent = await self.router.route(instruction)

        # 2. Get appropriate editor
        editor = self.editors.get(intent.category)
        if not editor:
            return EditResult(
                success=False,
                message=f"Unsupported edit type: {intent.category}"
            )

        # 3. Apply edit
        edited = editor.apply(design, intent)

        # 4. Validate result
        quality = PrintQualityGate().check_all(edited)

        return EditResult(
            success=True,
            image=edited,
            intent=intent,
            quality_report=quality,
        )

概要

AI編集アシスタント:

  1. インテント ルーティング — LLM は編集コマンドを 4 つのカテゴリに分類します
  2. レイアウト エディタ — プログラムによる移動/サイズ変更/回転/中央揃え
  3. スタイル エディター — AI ベースのスタイル変更のための InstructPix2Pix
  4. カラーエディタ — 色相シフト、明るさ、鮮やかさの調整
  5. 品質検証 — 各編集後の自動チェック

次の記事: AI タイポグラフィ — T シャツのテキスト、フォント スタイル、自動配置を生成します。