首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >QClaw 5天搞定24张文创插画!AI管线封神

QClaw 5天搞定24张文创插画!AI管线封神

原创
作者头像
用户12431396
修改2026-04-23 11:03:39
修改2026-04-23 11:03:39
1000
举报

AI工具链在文创项目中的完整协作推广推文

电子科技大学成都学院 开放原子开源社团 yy

文创周边赶工期?24张插画、4套规格、5天交付,纯人工扛不住,纯AI不稳定?教你用AI工具链编排管线,高效落地项目,新手也能上手!

结构化正文

一、项目核心需求

为独立游戏社团设计年度周边,含4类SKU,明确印刷规格。

核心矛盾:24张风格统一插画+4套规格,5天交付,人工与纯AI均不适用。

解决方案:AI批量生成+脚本自动化后处理+人工精修。

二、工作流总览

需求文档→Prompt工程→AI批量生图→脚本后处理→人工审核→印刷出稿

对应工具:Notion→ChatGPT/Claude→即梦API→Python脚本→Canva/PS→PDF+标记色

三、工具选型核心

对比4类AI生图工具,最终选定即梦AI。

核心优势:支持REST API,可批量提交任务、轮询结果,适配自动化管线。

后处理工具栈:抠图、尺寸适配、色彩转换等均有对应高效工具。

四、核心实现拆解

1. Prompt模板系统:用风格锚点+主题模板,锁定统一画风。

2. 即梦API批量调用:通过代码实现批量生成、自动保存。

3. 后处理管线:抠图→缩放→色彩转换,适配印刷需求。

4. 裁切标记:自动绘制,满足印刷厂要求。

五、真实踩坑实录

坑1:AI生图透明底幻觉,解决方案:生成后用rembg抠图。

坑2:RGB转CMYK色彩失真,两种解决方案可精准规避。

专属代码块

1. Prompt模板系统(完整代码)

代码语言:javascript
复制
# prompt_template.py

# 基础风格锚点(所有图共享)
STYLE_ANCHOR = (
    "pixel art illustration, retro game style, "
    "limited color palette, clean outlines, "
    "vibrant but not saturated colors, "
    "white background, no text, no watermark"
)

# 主题模板库
THEMES = {
    "sticker": "a cute {subject} holding a {prop}, chibi style, "
               "centered composition, simple background elements",
    "postcard": "a scenic {scene} with {detail}, "
                "wider composition, atmospheric perspective, "
                "small character silhouette in foreground",
    "badge": "a circular emblem featuring {symbol} with {frame_style} border, "
             "symmetrical composition, bold lines",
}

def build_prompt(theme: str, **kwargs) -> str:
    """
    构建最终 Prompt。
    
    参数:
        theme:  主题类型,对应 THEMES 中的 key
        kwargs: 替换模板中的占位符(如 subject="cat", prop="game controller")
    
    返回:
        完整的 Prompt 字符串
    """
    template = THEMES.get(theme, THEMES["sticker"])
    subject_prompt = template.format(** kwargs)
    return f"{subject_prompt}, {STYLE_ANCHOR}"

使用说明:替换kwargs中的占位符(如subject、prop),可批量生成对应主题的Prompt,风格锚点锁定统一画风。

2. 即梦API批量调用(完整代码)

代码语言:javascript
复制
# gen_batch.py
import requests
import time
import json
from pathlib import Path

API_BASE = "https://jimeng.jianying.com/openservice/api"
# 从环境变量读取,不硬编码
API_KEY = Path(".env").read_text().strip()

HEADERS = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json"
}

def submit_task(prompt: str, aspect_ratio: str = "1:1") -> str:
    """
    提交单次生成任务。
    
    参数:
        prompt:        文生图 Prompt
        aspect_ratio:  宽高比,可选 "1:1" / "3:4" / "16:9"
    
    返回:
        task_id:       用于轮询的任务 ID
    """
    payload = {
        "model": "jimeng_v2",
        "request": {
            "prompt": prompt,
            "aspect_ratio": aspect_ratio,
            # n: 每次生成数量,1~4
            "n": 1,
            # quality: "standard" 更快,"hd" 更精细
            "quality": "hd",
            # seed: 固定种子用于可复现(调试用)
            "seed": 42,
        }
    }
    resp = requests.post(
        f"{API_BASE}/generate",
        headers=HEADERS,
        json=payload,
        timeout=30
    )
    resp.raise_for_status()
    return resp.json()["task_id"]

def poll_result(task_id: str, interval: int = 10, timeout: int = 120) -> str:
    """
    轮询任务状态,返回图片 URL。
    
    参数:
        task_id:  submit_task 返回的任务 ID
        interval: 轮询间隔秒数
        timeout:  超时秒数
    """
    elapsed = 0
    while elapsed < timeout:
        resp = requests.get(
            f"{API_BASE}/task/{task_id}",
            headers=HEADERS
        )
        data = resp.json()
        
        if data["status"] == "succeeded":
            return data["result"]["images"][0]["url"]
        elif data["status"] == "failed":
            raise RuntimeError(f"Task {task_id} failed: {data.get('error')}")
        
        time.sleep(interval)
        elapsed += interval
    
    raise TimeoutError(f"Task {task_id} timed out after {timeout}s")

def batch_generate(prompts: list, output_dir: str = "output/raw"):
    """
    批量生成,自动保存。
    
    参数:
        prompts:    Prompt 列表
        output_dir: 原始图片保存目录
    """
    Path(output_dir).mkdir(parents=True, exist_ok=True)
    
    for i, prompt in enumerate(prompts):
        print(f"[{i+1}/{len(prompts)}] Submitting...")
        task_id = submit_task(prompt)
        url = poll_result(task_id)
        
        # 下载图片
        img_resp = requests.get(url, timeout=30)
        img_path = Path(output_dir) / f"raw_{i:03d}.png"
        img_path.write_bytes(img_resp.content)
        print(f"  → Saved: {img_path}")
        
        # 礼貌延迟,避免触发限流
        time.sleep(3)

使用说明:替换API_KEY,准备好Prompt列表,运行代码即可批量生成图片,生产环境需删除seed参数避免构图相似。

3. 后处理管线代码(完整代码)

代码语言:javascript
复制
# postprocess.py
from PIL import Image, ImageCms
from rembg import remove
from pathlib import Path

# 印刷规格配置
SKU_SPECS = {
    "sticker": {
        "target_size": (1500, 1500),   # 5cm @ 300dpi
        "dpi": 300,
        "color_mode": "RGBA",           # 贴纸需要透明底
        "format": "PNG",
        "bleed_mm": 0,
    },
    "postcard": {
        "target_size": (1740, 1170),    # 148×100mm + 双侧 3mm 出血 @ 300dpi
        "dpi": 300,
        "color_mode": "CMYK",
        "format": "TIFF",
        "bleed_mm": 3,
    },
    "badge": {
        "target_size": (1740, 1740),    # 58mm 直径 + 裁切余量 @ 300dpi
        "dpi": 300,
        "color_mode": "RGB",            # 徽章印刷用 RGB 即可
        "format": "PNG",
        "bleed_mm": 2,
    },
}

def remove_background(input_path: Path) -> Image.Image:
    """用 rembg 去除背景。"""
    img = Image.open(input_path)
    # model="u2net" 速度快;model="isnet-general-use" 边缘更精细
    return remove(img, model="u2net")

def resize_for_sku(img: Image.Image, sku: str) -> Image.Image:
    """
    按 SKU 规格缩放图片。
    
    参数:
        img:  PIL Image 对象(已去背景)
        sku:  SKU 类型,对应 SKU_SPECS
    """
    spec = SKU_SPECS[sku]
    # LANCZOS:高质量缩放算法
    return img.resize(spec["target_size"], Image.LANCZOS)

def to_cmyk(img: Image.Image, profile_path: str = "profiles/CoatedFOGRA27.icc") -> Image.Image:
    """
    RGB → CMYK 转换。
    
    参数:
        img:           RGB 模式的 PIL Image
        profile_path:  目标 ICC Profile 路径
                      (CoatedFOGRA27 是国内铜版纸最常用的标准)
    
    返回:
        CMYK 模式的 PIL Image
    """
    if img.mode != "RGB":
        img = img.convert("RGB")
    
    # 加载 CMYK 目标 Profile
    cmyk_profile = ImageCms.ImageCmsProfile(profile_path)
    
    # 创建转换意图:RELATIVE_COLORIMETRIC 保留色相,PERCEPTUAL 整体最自然
    transform = ImageCms.ImageCmsTransform(
        img,
        cmyk_profile,
        renderingIntent=ImageCms.Intent.RELATIVE_COLORIMETRIC
    )
    return transform(img)

def process_one(input_path: Path, sku: str, output_dir: Path) -> Path:
    """
    完整后处理:去背景 → 缩放 → 色彩转换 → 保存。
    
    参数:
        input_path:  原始生成图片路径
        sku:         SKU 类型
        output_dir:  输出目录
    
    返回:
        输出文件路径
    """
    spec = SKU_SPECS[sku]
    
    # Step 1: 去背景
    img_no_bg = remove_background(input_path)
    
    # Step 2: 缩放
    img_resized = resize_for_sku(img_no_bg, sku)
    
    # Step 3: 色彩转换
    if spec["color_mode"] == "CMYK":
        img_final = to_cmyk(img_resized)
    else:
        img_final = img_resized
    
    # Step 4: 保存
    output_dir.mkdir(parents=True, exist_ok=True)
    output_path = output_dir / f"{sku}_{input_path.stem}.{spec['format'].lower()}"
    
    save_kwargs = {"dpi": (spec["dpi"], spec["dpi"])}
    if spec["format"] == "PNG":
        save_kwargs["compression_level"] = 6  # 0-9,6 是速度/体积平衡点
    
    img_final.save(output_path, **save_kwargs)
    return output_path

使用说明:配置SKU规格,运行代码可自动完成去背景、缩放、色彩转换,适配不同周边印刷需求。

价值总结

本文拆解真实文创项目全流程,打破“AI仅能单张出图”的认知,教你将AI作为管线节点编排,结合Prompt工程、Python脚本与即梦API,5天高效交付24张风格统一的插画及4套印刷规格产品。规避AI生图、色彩转换等常见坑,提供可直接复用的代码,无论是社团文创、个人周边还是小型商业项目,都能快速落地,提升效率、降低成本。

行动号召(CTA)

收藏本文,复制代码直接复用,跟着流程实操落地你的文创项目!关注我们,获取更多AI工具实操技巧、文创项目拆解,评论区留言“文创AI”,领取完整代码包及印刷规格模板~

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 结构化正文
  • 专属代码块
  • 价值总结
  • 行动号召(CTA)
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档