多参考图编辑别再靠“感觉”写提示词:用一个 Python 小脚本整理 Qwen Image 2.1 Pro 的参考图角色

0 阅读5分钟

做人像换装、商品换场景这类图像编辑任务时,经常要同时上传好几张参考图:一张人物、一张外套、一张手袋,可能还有一张背景。图一多,提示词就很容易写乱——哪张图负责什么、要保留哪些细节、冲突时听谁的,全靠临时想。本文用 Qwen Image 2.1 Pro 的多参考图编辑为例,介绍一种把“参考图角色”结构化的写法,并附一个几十行的 Python 脚本,在提交前自动检查素材、拼出编号清晰的提示词。

01-page.jpg 链接页面要点:wan30.io/zh/qwen-image-2-1-pro(2026-10-30 读取)

先看官方给的约束

Qwen Image 2.1 Pro 页面上列出的和参考图相关的规则主要有这些:

  • 图像编辑最多支持 10 张参考图,格式为 JPG、PNG 或 WebP,每张不超过 30 MB;
  • 画幅可以用自动,或从 1:1、2:3、3:2、1:4、4:1、3:4、4:3、4:5、5:4、1:8、8:1、9:16、16:9、21:9 中选择;
  • 提示词上限 20,000 字符;
  • 上传顺序与提示词中的编号应对应,并说明冲突时优先保留什么。

页面还特别提醒:参考图越多并不一定越好,先使用足够清晰、彼此兼容的素材,避免多个不同人物、背景或色彩方案争夺同一个位置。编辑指令最好同时包含“修改什么”和“保留什么”。

这些规则正好可以写成代码里的校验项。

思路:把每张参考图写成一条结构化记录

与其直接写一大段自然语言,不如先把任务拆成一份 JSON:

  • goal:最终画面是什么(主体、构图、光线);
  • ratio:画幅;
  • refs:参考图列表,每张图有 file、role(负责什么)、keep(要保留什么);
  • change:要修改什么;
  • priority:冲突时的优先级。

脚本做两件事:先按上面的约束检查,再按上传顺序拼出“图1(人物):保留……”这样的编号提示词。

02-roles.png 自制图:每张参考图的角色与保留项

脚本

import json, os, sys

ALLOWED_EXT = {".jpg", ".jpeg", ".png", ".webp"}
MAX_REFS = 10
MAX_MB = 30
RATIOS = {"auto", "1:1", "2:3", "3:2", "1:4", "4:1", "3:4", "4:3",
          "4:5", "5:4", "1:8", "8:1", "9:16", "16:9", "21:9"}
MAX_PROMPT = 20000

def check(brief):
    errors = []
    refs = brief["refs"]
    if len(refs) > MAX_REFS:
        errors.append(f"参考图 {len(refs)} 张,超过 {MAX_REFS} 张")
    for i, r in enumerate(refs, 1):
        ext = os.path.splitext(r["file"])[1].lower()
        if ext not in ALLOWED_EXT:
            errors.append(f"图{i} {r['file']}: 格式 {ext} 不支持")
        elif os.path.getsize(r["file"]) > MAX_MB * 1024 * 1024:
            errors.append(f"图{i} {r['file']}: 超过 {MAX_MB} MB")
        if not r.get("keep"):
            errors.append(f"图{i} {r['file']}: 没写要保留什么")
    if brief["ratio"] not in RATIOS:
        errors.append(f"画幅 {brief['ratio']} 不在可选列表中")
    return errors

def build(brief):
    lines = [brief["goal"]]
    for i, r in enumerate(brief["refs"], 1):
        lines.append(f"图{i}({r['role']}):保留{r['keep']}。")
    if brief.get("change"):
        lines.append("修改:" + brief["change"])
    if brief.get("priority"):
        lines.append("冲突时优先保留:" + brief["priority"])
    return "\n".join(lines)

if __name__ == "__main__":
    brief = json.load(open(sys.argv[1], encoding="utf-8"))
    errs = check(brief)
    if errs:
        print("检查未通过:")
        for e in errs:
            print(" -", e)
        sys.exit(1)
    prompt = build(brief)
    assert len(prompt) <= MAX_PROMPT
    print(prompt)
    print(f"\n[参考图 {len(brief['refs'])} 张 | 画幅 {brief['ratio']} | 提示词 {len(prompt)} 字符]")

几个设计点:

  • 格式、大小、数量、画幅、提示词长度,都直接对应页面上的规则,规则变了只改顶部常量;
  • keep 为空会被当成错误——这是刻意的,逼自己为每张图写清保留项;
  • 输出的提示词按上传顺序编号,和页面“上传顺序与编号对应”的建议一致。

跑一下

用三张占位图片(纯色图,只为测试流程)和一份正常的任务描述:

{"goal": "竖版人像换装图:人物站在浅灰色影棚背景前,全身构图,柔和正面光。",
 "ratio": "2:3",
 "refs": [
  {"file": "model.jpg", "role": "人物", "keep": "脸型、发型和站姿"},
  {"file": "coat.png", "role": "外套", "keep": "藏青色、双排扣和长度"},
  {"file": "bag.webp", "role": "手袋", "keep": "棕色皮质和金属扣"}
 ],
 "change": "人物穿上图2的外套,左手拎图3的手袋。",
 "priority": "人物面部 > 外套颜色 > 手袋细节"}
$ python3 refbrief.py brief_ok.json
竖版人像换装图:人物站在浅灰色影棚背景前,全身构图,柔和正面光。
图1(人物):保留脸型、发型和站姿。
图2(外套):保留藏青色、双排扣和长度。
图3(手袋):保留棕色皮质和金属扣。
修改:人物穿上图2的外套,左手拎图3的手袋。
冲突时优先保留:人物面部 > 外套颜色 > 手袋细节

[参考图 3 张 | 画幅 2:3 | 提示词 141 字符]

再故意写一份有问题的:画幅写成不存在的 7:5,再塞一张 GIF,而且没写保留项。

$ python3 refbrief.py brief_bad.json
检查未通过:
 - 图2 shoes.gif: 格式 .gif 不支持
 - 图2 shoes.gif: 没写要保留什么
 - 画幅 7:5 不在可选列表中

三处问题都在提交前被拦下来了。这些错误如果到了工作台才发现,至少要多来回一次。

03-flow.png 自制图:JSON 任务描述 → 校验 → 编号提示词

生成之后:每轮只改一组内容

页面在“多轮细化”部分建议:把已认可的结果保存为下一轮参考,每次只修改一组内容,这样更容易追踪变化,也能及时发现面部、Logo、标签文字或产品结构偏移。

配合脚本,可以把每一轮都保存成一份 JSON(比如 round1.json、round2.json),只改 change 字段,其余不动。用 diff 比较两份文件,就能清楚地看到这一轮到底改了什么。出图后对照原图逐项检查:人物面部、外套颜色、手袋细节,按 priority 的顺序看。

另外,页面建议先用 1K 探索构图、配色和主体关系,确定方向后再提高输出清晰度。也就是说,前几轮验证参考图组合时不必一开始就选最高档,等组合确定了再提高。

一些注意事项

  • 脚本只检查“能不能提交”,不保证效果。参考图本身是否清晰、彼此是否兼容,还是要人眼判断;
  • 页面也说明,参考图与保留指令能帮助维持可识别特征,但不同任务的还原程度可能不同,商业素材要逐项核查;
  • 品牌 Logo、人物肖像这类素材,提交前确认自己有使用权。

04-check.png 自制图:多参考图编辑提交前检查清单

小结

多参考图编辑最容易出问题的地方不是模型,而是提示词里“谁负责什么”没写清。把参考图角色写成结构化数据,用脚本做一次提交前检查,再按上传顺序生成编号提示词,能省掉不少来回试错。脚本很短,可以按自己的任务类型继续扩展,比如加上背景图、加上必须出现的文字。