跳转到主要内容

GPT Image 2.6 markup 标注改图怎么调用:按次中转线路实测不生效

markup 要单独传一张与原图同尺寸、带透明像素的 PNG,只作用于第一张图;2026 年 11 月 5 日在按次中转线路上实测没起作用,改用官方转发再核对圈外。

LaoZhang AI Team发布于20 分钟阅读
文章目录
GPT Image 2.6 markup 标注改图:原图、画着红圈的透明标注图和 prompt 一起发到 /v1/images/edits

GPT Image 2.6 的 markup(标注改图)在 API 里是一个单独的参数:你另做一张和原图宽高完全一致的透明 PNG,在上面圈出要改的位置,作为 markup 和原图一起发到 POST /v1/images/edits,要改成什么仍然写在 prompt 里。截至 2026 年 11 月 5 日,OpenAI 的图像生成指南「Guide an edit with markup」一节写明 gpt-image-2.6-flare 和 gpt-image-2.6-sunburst 都可以这样改图;标注图只作用于第一张输入图,不能和 mask、prompt_rewriter 同时传。

能不能生效,取决于请求经过哪条线路。2026 年 11 月 5 日在 LaoZhang 的两条按次计费线路 gpt-image-2.6-web 和 gpt-image-2.6-sunburst-vip 上测试:画面里有四把一样的白椅子,标注图圈住左前方那一把,结果四次请求(每条线路带、不带标注图各一次)都返回 200,变黄的始终是别的椅子,被圈住的那把一次都没变。经中转发 markup,应选请求体与 OpenAI 官方一致、按 token 计费的官方转发(OpenAI Official 分组下的 gpt-image-2.6-flare / gpt-image-2.6-sunburst);这条线路上的 markup 截至 11 月 5 日还没有测过,所以每次结果都要用文末的方法比对圈外。

如果要改的东西在画面里独一无二(只有一个花瓶),只写文字往往就够了,markup 真正有用的是"四把同样的椅子改其中一把"这类靠文字说不清位置的情况。下面依次是标注图的规则、生成与检查脚本、两种请求写法、线路实测,以及怎么确认圈外没被改动。

用 markup、蒙版还是只写文字:先看文字能不能说清位置

选哪种方式,先问一句:只用文字,模型能不能唯一地找到目标?能,就不必做标注图;不能,再看你走的是 Image API 还是 Responses API。markup 只在 Image API 的 /v1/images/edits 上可用,OpenAI 指南把 Responses API 里的局部编辑指向蒙版(mask)。标注图和蒙版是两样东西:标注图是一层画了圈或草图的透明 PNG,告诉模型"改这里";蒙版是一张带 alpha 通道的图,用来标出要编辑的区域,两者不能放在同一个请求里。

对比项只写文字markup 标注图mask 蒙版
位置靠什么指定prompt 里的描述透明 PNG 上的圈、草图等标注带 alpha 通道的蒙版图标出的区域
文件要求无PNG,与第一张输入图同宽高,必须含透明像素带 alpha 通道,与原图格式、尺寸相同,小于 50 MB
可用的接口/v1/images/edits、Responses API只有 /v1/images/edits/v1/images/edits、Responses API
精度目标唯一时够用,多个相似物体时容易改错标注只说明位置,圈外仍可能有少量变化官方说明完全靠提示词引导,不保证严格贴合蒙版形状
适合的场景画面里唯一的物体多个相同物体中的一个、难以描述的位置已有蒙版流程,或在 Responses API 里做局部编辑
不能同时传—mask、prompt_rewritermarkup

蒙版一列的说法来自 OpenAI 指南的「Edit an image using a mask」一节:模型把蒙版当作引导,可能不会完全按它的形状来改。所以三种方式都不保证"圈外一个像素都不动",区别只在于你用什么方式告诉模型位置。

标注图要满足的条件:同宽高、含透明像素、不超过 16,777,216 像素

标注图不合规时,按次线路不会提醒你。2026 年 11 月 5 日在 gpt-image-2.6-sunburst-vip 上发了一张 1000×750 的标注图(原图 1200×900)和一张压平成不透明的标注图,两次都返回 200,没有任何报错。返回 200 不代表标注图被读取,所以下面这些条件要在发请求之前自己检查。条件全部来自 OpenAI 图像生成指南和 images.edit 接口参考。

条件具体要求本地脚本怎么查
宽高一致按 EXIF 方向校正后,标注图和第一张输入图的宽、高完全相同先 ImageOps.exif_transpose 再比较尺寸
含透明像素单独的透明 PNG,不能把圈画在原图上再导出检查是 RGBA 且 alpha 最小值小于 255
像素上限第一张输入图和标注图各自不超过 16,777,216 像素(相当于 4096×4096)宽 × 高与上限比较
文件大小标注图文件不超过 50 MB读文件字节数
作用对象只作用于第一张输入图,其余输入图只作参考不查:调用时把原图放在第一位
不能组合不能和 mask、prompt_rewriter 同时传不查:请求里不写这两个参数

手机照片最容易在第一条出错。很多手机照片存储的像素方向和显示方向不同,靠 EXIF 方向标签让看图软件转正,而接口比较的是转正之后的宽高;如果你按文件原始尺寸做标注图,宽和高会正好对调。用 JSON 方式发送时还有一个隐含上限:参考文档里 image_url 字段最长 20,971,520 个字符,base64 会把文件放大到约 4/3,所以用 data URL 传的单个文件大约不能超过 20,971,520 × 3 ÷ 4 = 15,728,640 字节(约 15 MB),更大的原图改用 multipart 上传或 file_id。标注图本身通常只有几 KB,不受影响。

用 Python 画标注图并在本地检查

下面这个脚本做两件事:在一张与原图同尺寸的全透明画布上画一个红色椭圆,然后按上一节的四条可检查规则逐条验证。它只依赖 Pillow(pip install pillow),先按 EXIF 方向校正原图再取尺寸。

python
"""为 GPT Image 2.6 / 2.5 的 markup 改图生成并检查标注图。
在与原图(按 EXIF 方向校正后)同尺寸的全透明画布上画一个红色椭圆,
再按 OpenAI 写明的规则检查:与第一张输入图同宽高、含透明像素、
不超过 16,777,216 像素、不超过 50 MB。
用法:python3 make_markup_overlay.py photo.jpg x0 y0 x1 y1 [out.png]"""
import os, sys
from PIL import Image, ImageDraw, ImageOps

MAX_PIXELS = 16_777_216
MAX_BYTES = 50 * 1024 * 1024


def build(photo, box, out):
    img = ImageOps.exif_transpose(Image.open(photo))  # 接口按方向校正后的尺寸比较
    overlay = Image.new("RGBA", img.size, (0, 0, 0, 0))
    ImageDraw.Draw(overlay).ellipse(box, outline=(230, 20, 20, 255), width=max(4, img.width // 150))
    overlay.save(out)
    return img.size


def check(photo, out):
    img = ImageOps.exif_transpose(Image.open(photo))
    ov = Image.open(out)
    problems = []
    if ov.size != img.size:
        problems.append(f"size {ov.size} != photo {img.size}")
    if ov.mode != "RGBA" or ov.getchannel("A").getextrema()[0] == 255:
        problems.append("no transparent pixels (flattened overlay)")
    if ov.width * ov.height > MAX_PIXELS:
        problems.append("overlay over 16,777,216 pixels")
    if os.path.getsize(out) > MAX_BYTES:
        problems.append("overlay over 50 MB")
    return problems


if __name__ == "__main__":
    photo, *nums = sys.argv[1:6]
    out = sys.argv[6] if len(sys.argv) > 6 else "markup.png"
    size = build(photo, [int(n) for n in nums], out)
    issues = check(photo, out)
    print(f"photo {size[0]}x{size[1]} -> {out} ({os.path.getsize(out)} bytes)")
    print("OK" if not issues else "FAIL: " + "; ".join(issues))

照着做的顺序是:

  1. 在看图软件里找到目标的像素坐标,记下要圈的矩形范围:左上角 x0 y0、右下角 x1 y1。坐标按照片转正后的方向量。

  2. 运行 python3 make_markup_overlay.py kitchen.png 235 610 465 785 markup.png,最后一行是 OK 才算通过。

  3. 把标注图叠到原图上预览,确认圈住的是你要改的东西:

    python
    from PIL import Image, ImageOps
    photo = ImageOps.exif_transpose(Image.open("kitchen.png")).convert("RGBA")
    photo.alpha_composite(Image.open("markup.png"))
    photo.convert("RGB").save("preview.jpg")
  4. 输出 FAIL 时按提示处理:尺寸不符就用原图重新生成,不透明就换回透明画布,不要在修图软件里把圈直接画到照片上再导出。

2026 年 11 月 5 日用 OpenAI 指南里那张 1200×900 的厨房照片运行这个脚本,第 2 步输出 photo 1200x900 -> markup.png (5645 bytes) 和 OK。同一天用它的 check 函数检查另外三张图:1000×750 的标注图报 size (1000, 750) != photo (1200, 900),压平到白底上的标注图报 no transparent pixels (flattened overlay),OpenAI 示例自带的透明标注图通过。脚本检查的是 OpenAI 文档写明的规则,它通过只说明文件合规,不能代替看最终结果。

发送 markup:multipart 上传和 JSON 两种写法

发送时,原图放在第一张输入图的位置,标注图放进 markup,prompt 里用标注本身指代目标("inside the red circle"),写清要改成什么、哪些地方保持不变,并要求成品里去掉红圈。OpenAI 示例的提示词就是这个结构:Recolor the striped vase inside the red circle to solid cobalt blue ceramic. Keep its shape, the dried stems, and the rest of the kitchen unchanged. Remove the red circle from the finished photo. "只改 X、其余保留"这类改图提示词的细节,见 GPT Image 2.6 改图提示词写法。

参数上有四点要注意。第一,不传 mask、prompt_rewriter,也不传 input_fidelity(OpenAI 提示词指南写明改图时省略它)。第二,complexity 不传时两个模型都按 high 处理,而指南建议只改一处细节时从 low 开始,所以显式写 complexity="low"。第三,size 用 auto 或与原图同比例的尺寸,宽高都要是 16 的倍数(4:3 的照片可以写 1536x1152)。第四,模型二选一:Sunburst 在 quality 为 medium 或 high 时多次编辑之间的一致性更好(OpenAI 发布文章的说法),Flare 更快。

multipart 是 OpenAI 自己示例用的写法,经中转时先用它跑通。Python 用官方 openai 包,下面以 LaoZhang 官方转发为例,直连 OpenAI 时去掉 base_url、换成 OpenAI 的密钥即可。要注意,官方转发上的 markup 截至 2026 年 11 月 5 日还没有实测(下文的测试在按次线路上,标注图没有起作用),这段代码跑通只说明请求被接受,标注图有没有被读取,要用最后一节的对比方法确认:

python
import base64
from pathlib import Path
from openai import OpenAI

client = OpenAI(
    api_key="你的 OpenAI Official 分组令牌",
    base_url="https://api.laozhang.ai/v1",
)

with open("kitchen.png", "rb") as image, open("markup.png", "rb") as markup:
    result = client.images.edit(
        model="gpt-image-2.6-sunburst",
        image=("kitchen.png", image, "image/png"),       # 原图:第一张输入图
        markup=("markup.png", markup, "image/png"),      # 标注图
        prompt=(
            "Recolor the chair inside the red circle to bright mustard-yellow leather. "
            "Keep its shape. Keep the other chairs white and keep the rest of the kitchen unchanged. "
            "Remove the red circle from the finished photo."
        ),
        quality="medium",
        size="1536x1152",
        complexity="low",
    )

Path("edited.png").write_bytes(base64.b64decode(result.data[0].b64_json))

这段代码要求 openai-python 3.46.0 或更高版本:markup 从 3.42.0(2026 年 10 月 31 日发布)开始才有,complexity 到 3.46.0(2026 年 11 月 5 日发布)才加入,更早的版本会报 unexpected keyword argument。不方便升级时,把 complexity 去掉,改写成 extra_body={"complexity": "low"};版本低于 3.42.0 时 markup 也不能直接传,直接 pip install -U openai 最省事。用 curl 时把两个文件作为表单字段上传:

bash
curl --fail-with-body https://api.laozhang.ai/v1/images/edits \
  -H "Authorization: Bearer $LAOZHANG_API_KEY" \
  -F model=gpt-image-2.6-sunburst \
  -F quality=medium \
  -F size=1536x1152 \
  -F complexity=low \
  -F 'image=@kitchen.png;type=image/png' \
  -F 'markup=@markup.png;type=image/png' \
  -F 'prompt=Recolor the chair inside the red circle to bright mustard-yellow leather. Keep its shape. Keep the other chairs white and keep the rest of the kitchen unchanged. Remove the red circle from the finished photo.' \
  | jq -er '.data[0].b64_json' | base64 --decode > edited.png

JSON 写法的结构不同:原图放进 images 数组,markup 是一个对象,image_url(HTTPS 地址或 base64 data URL)和 file_id 二者只能填一个。原图较大时注意上一节说的 data URL 长度上限。

python
import base64, os, requests

def data_url(path):
    return "data:image/png;base64," + base64.b64encode(open(path, "rb").read()).decode()

body = {
    "model": "gpt-image-2.6-sunburst",
    "images": [{"image_url": data_url("kitchen.png")}],   # 第一张就是要改的图
    "markup": {"image_url": data_url("markup.png")},      # 或 {"file_id": "file-..."}
    "prompt": "Recolor the chair inside the red circle to bright mustard-yellow leather. "
              "Keep its shape. Keep the other chairs white and keep the rest of the kitchen unchanged. "
              "Remove the red circle from the finished photo.",
    "quality": "medium",
    "size": "1536x1152",
    "complexity": "low",
}
r = requests.post(
    "https://api.openai.com/v1/images/edits",
    headers={"Authorization": f"Bearer {os.environ['OPENAI_API_KEY']}"},
    json=body,
    timeout=300,
)
r.raise_for_status()
open("edited.png", "wb").write(base64.b64decode(r.json()["data"][0]["b64_json"]))

经中转调用 markup 该走哪条线路:官方转发,不是按次线路

经 LaoZhang 中转时,要试 markup 就用官方转发:令牌分组选 OpenAI Official(或加价 20% 的 OpenAI Official Enterprise),模型填 gpt-image-2.6-flare 或 gpt-image-2.6-sunburst,按 OpenAI 的 token 单价计费。依据是 LaoZhang 的 GPT Image 文档:官方转发的接口和请求写法与官方相同,只换 model。这份文档截至 2026 年 11 月 5 日没有提到 markup,官方转发是否原样透传这个字段也还没有测过,所以第一次调用后要用最后一节的方法看结果,确认被圈住的东西真的变了、圈外没被大改。

说明:laozhang.ai 是我们自己的服务,其价格是平台报价,不是独立比较的结论。

按次线路 gpt-image-2.6-web 和 gpt-image-2.6-*-vip 每次 $0.03,但在下一节的测试里没有读取标注图,不适合需要 markup 的任务。用其他中转服务时,同样的判断方法也适用:看它是否把请求体原样转给 OpenAI,再用"多个相同物体圈其中一个"的图实际测一次,只看返回 200 判断不了。

按次线路实测:圈住的椅子四次都没被改

2026 年 11 月 5 日晚,用 OpenAI 指南里的厨房照片(1200×900)在 LaoZhang 默认分组的两条按次线路上做了这组测试。照片里餐桌旁有四把一样的白椅子,标注图只圈住左前方那一把,提示词里也只说"红圈里的椅子",不提左右前后:Recolor the chair inside the red circle to bright mustard-yellow leather. Keep its shape. Keep the other chairs white and keep the rest of the kitchen unchanged. Remove the red circle from the finished photo. 这样,模型只有读了标注图才可能改对。每一格只跑了一次。

线路与参数标注图返回尺寸变成黄色的椅子被圈住的左前方椅子耗时
gpt-image-2.6-web带1448×1086右前方那把仍是白色约 24 秒
gpt-image-2.6-web不带1448×1086右侧几把仍是白色约 24 秒
gpt-image-2.6-sunburst-vip,size 1536x1152带1536×1152右前方那把仍是白色约 38 秒
gpt-image-2.6-sunburst-vip,size 1536x1152不带1536×1152右前方那把仍是白色约 38 秒

按次线路椅子测试:标注图圈住左前方的白椅子,两条线路带与不带标注图的四次结果都是别的椅子变黄,被圈的那把仍是白色

四张结果里红圈都被去掉了,但带不带标注图,改错的方式几乎一样,说明在这两条线路上标注图没有带来可见差别。gpt-image-2.6-flare-vip 没有单独测。这个结果只说明这两条按次线路,不代表 OpenAI 官方 API 或官方转发的表现。

做椅子测试之前,同一天先用 OpenAI 示例的花瓶跑过一轮:网页版带标注图返回 1448×1086,花瓶变成钴蓝色、干枝保留、红圈去掉,看起来完全成功;VIP 线路无论带标注图、不带标注图,还是只写一句 Make the vase blue.,花瓶都变蓝了。画面里只有一个花瓶,模型凭文字就能找到它,所以这类测试分辨不出标注图有没有被读取。自己验证线路时,要选"几个相同物体圈其中一个"的图。

改完变成方图:VIP 线路不传 size 会输出 2048×2048

改完的图被重新构图成正方形,原因是没有传 size。2026 年 11 月 5 日在 gpt-image-2.6-sunburst-vip 上改 1200×900 的厨房照片,只要请求里不带 size,返回的都是 2048×2048,4:3 的房间被重新排进方形画面,带不带标注图都一样;显式写 size: "1536x1152" 后输出保持 4:3。网页版和 OpenAI 自己的示例(size="auto")返回的是 1448×1086,比例没变。所以在按次线路上改图一定写明 size;在其他线路上,如果后续要和原图逐像素对比,也建议写一个与原图同比例的尺寸。

怎么确认圈外没被改:缩回原尺寸后分区对比

判断改图是否只动了圈内,要把结果缩回原图尺寸,分别计算圈内和圈外的平均变化,再看差异图里圈外有没有成块变亮的地方。OpenAI 在指南的花瓶示例后面也提醒,要把每张结果的其余部分和原图对比,检查有没有别的改动。下面的脚本需要 Pillow 和 NumPy,把标注笔画的外接椭圆当作"圈内":

python
"""对比改图结果与原图:圈内、圈外各变了多少,并输出一张差异图。
用法:python3 check_edit.py 原图 标注图.png 结果图 [diff.png]"""
import sys
import numpy as np
from PIL import Image, ImageDraw, ImageOps

photo, markup, result = sys.argv[1:4]
diff_out = sys.argv[4] if len(sys.argv) > 4 else "diff.png"

orig = ImageOps.exif_transpose(Image.open(photo)).convert("RGB")
alpha = np.array(Image.open(markup).convert("RGBA"))[:, :, 3]
ys, xs = np.nonzero(alpha > 0)                      # 标注笔画所在的像素
region = Image.new("L", orig.size, 0)               # 把圈的外接椭圆填满,当作"圈内"
ImageDraw.Draw(region).ellipse([xs.min(), ys.min(), xs.max(), ys.max()], fill=255)
inside = np.array(region) > 0

out = Image.open(result).convert("RGB")
print("结果尺寸", out.size, "原图尺寸", orig.size)
a = np.array(out.resize(orig.size, Image.LANCZOS)).astype(float)   # 缩回原图尺寸再比
d = np.abs(a - np.array(orig).astype(float)).mean(axis=2)
print(f"圈内平均变化 {d[inside].mean() / 2.55:.1f}%")
print(f"圈外平均变化 {d[~inside].mean() / 2.55:.1f}%")

heat = np.clip(d * 4, 0, 255).astype("uint8")       # 变化越大越亮
heat[inside] = heat[inside] // 4                    # 压暗圈内,突出圈外的改动
Image.fromarray(heat).save(diff_out)
print("差异图已保存到", diff_out)

拿到结果后按这个顺序看:

  1. 运行 python3 check_edit.py kitchen.png markup.png edited.png,先看"结果尺寸":比例和原图不同,说明画面被重新构图了,后面的数字没有意义,回到上一节加 size 重做。
  2. 看圈内变化是否明显高于圈外。圈内和圈外差不多,说明模型可能没改目标,或者整张图都变了。
  3. 打开 diff.png,找圈外成块发亮的区域:另一把椅子、另一件物体整体变亮,就是改错了位置,椅子测试里的失败正是这种情况。
  4. 同一张图换模型或换参数时,用圈外变化比较哪次更干净,不要拿某个绝对值当合格线。

确认圈外没被改的四步:先看结果尺寸,再比较圈内和圈外的平均变化,打开 diff.png 找圈外发亮的区域,最后换模型或参数横向比较

圈外变化不会是 0:模型会重新生成整张图,缩放本身也会带来细小差异。2026 年 11 月 5 日用这个脚本对比 OpenAI 公开的两张花瓶示例结果(输入 1200×900,输出 1448×1086),圈内平均变化 Sunburst 12.1%、Flare 11.2%,圈外 Sunburst 4.3%、Flare 8.4%。在这一个示例里,Flare 对圈外的改动约是 Sunburst 的两倍,这只是一组样本,可以作为你自己对比时的参照,不能当作两个模型的排名。

markup 要额外收费吗:按改图同样的 token 单价,没有附加费

不收额外费用。OpenAI 图像生成指南写的是标注改图与其他改图使用同样的 token 单价,没有附加费;OpenAI 价格页上 GPT Image 2.6 的图片输入每 1M tokens $8、图片输出每 1M tokens $30、文本输入每 1M tokens $5。作为参考,2026 年 11 月 5 日在 LaoZhang 官方转发上用 Sunburst、low 档改一张图,实际扣费 $0.03301,这是一次编辑的数字,尺寸和画质变了会不同。各档位的单张成本和要不要从 2.5 换过来,见 GPT Image 2.6 和 2.5 区别:low/medium 贵 3–4 倍,high 档起同价。

GPT Image 2.5 能用 markup 吗:指南和接口参考说法不一

截至 2026 年 11 月 5 日,OpenAI 的两份文档说法不一致。图像生成指南写的是 markup 适用于"支持的 GPT Image 2.5 和 2.6 模型",发布文章和两个 2.6 的模型页也把它列为 2.6 的能力;而 images.edit 接口参考里 markup 参数的说明只写了"Supports GPT Image 2.5",没有提 2.6。指南和发布文章是关于 2.6 的较新说明,所以 2.6 可以按指南使用;2.5 两份文档都提到了,但指南没有逐一列出是哪几个 2.5 型号。不管用哪个模型,第一次调用都用上一节的对比方法确认标注被读取。

GPT Image 2.6 markup 的其他问题

GPT Image 2.6 已经发布了吗?为什么有的页面说还没有模型 ID?

已经发布。OpenAI 在 2026 年 11 月 4 日发布 Images 2.6,API 模型 ID 是 gpt-image-2.6-flare 和 gpt-image-2.6-sunburst,发布文章原话是"Image markup, already available in ChatGPT, comes to the API"。"2.6 还没有模型 ID"的说法来自发布前的提前报道,当时只能看到 OpenAI 接口规范在 10 月底新增的 markup 字段,现在已经过时。

ChatGPT 里的圈选标注和 API 的 markup 是一回事吗?

不是同一个入口。ChatGPT App 图片编辑器里的标注工具是界面操作,按钮会重新生成整张图;API 的 markup 需要你自己做标注图并通过 /v1/images/edits 发送。在 App 里怎么只改一处,见 ChatGPT 图片编辑怎么用:按钮会重新生成整张图,只改一处这样做。

标注图上能画什么,红圈是必须的吗?

OpenAI 指南说标注图可以包含圈、草图或其他标注,没有规定颜色和形状;官方示例用的是红色圆圈,提示词里用"inside the red circle"指代目标,并要求成品去掉红圈。用别的颜色或形状时,提示词里按你画的样子去指代,并同样写明去掉标注,这样结果里才不会留下笔画。

用 markup 时 complexity 该选哪一档?

先用 low。OpenAI 发布文章建议大多数改图任务用 low 以加快速度,元素多、约束多的画面再试 medium 或 high;不传时两个 2.6 模型默认是 high。对比不同档位时保持 quality、size 和提示词不变,每次只改一个参数,再用圈外变化判断哪次更干净。

GIF 动图和 SVG 矢量图是 2.6 另外两项新输出,与改图无关;SVG 的调用方法见 GPT Image 2.6 导出 SVG 矢量图的 API 写法。

参考来源3

本文引用的外部页面,按正文出现顺序排列。最后更新于 2026年11月5日。

  1. 1.图像生成指南「Guide an edit with markup」一节developers.openai.com/api/docs/guides/image-generation
  2. 2.images.edit 接口参考developers.openai.com/api/reference/resources/images/methods/edit
  3. 3.OpenAI 价格页developers.openai.com/api/docs/pricing