GPT Image 2.6 markup: редактирование по разметке и проверка слоя
Markup в GPT Image 2.6 — прозрачный PNG размером с фото: он показывает, где править, prompt — что. 200 в ответе не значит, что маршрут прочитал слой.
Содержание

Параметр markup в GPT Image 2.6 — это отдельный прозрачный PNG того же размера, что и фото, на котором вы обводите или зарисовываете место правки. Слой разметки отвечает на вопрос «где», а что именно поменять, вы по-прежнему пишете в prompt. Отправляется он в POST /v1/images/edits с моделью gpt-image-2.6-flare или gpt-image-2.6-sunburst: в multipart-запросе — файлом в поле markup, в JSON — объектом "markup": {"image_url": ...} или {"file_id": ...} рядом с массивом images. Это не маска: вместе с mask и prompt_rewriter слой передавать нельзя, и действует он только на первое входное изображение. OpenAI добавила разметку в API вместе с Images 2.6 4 ноября 2026 года, отдельной платы за неё нет.
Перед платным вызовом проверьте слой локально: после учёта EXIF-ориентации у него должны быть те же ширина и высота, что у фото, в нём должны быть настоящие прозрачные пиксели, не больше 16 777 216 пикселей и не больше 50 МБ. Скрипт на Python ниже собирает такой слой по координатам и проверяет все четыре правила. После ответа сравните с оригиналом всё, что лежит за пределами круга, иначе вы не узнаете, перерисовала ли модель заодно остальную картинку.
Главное условие — маршрут, через который идёт запрос. Ответ 200 не означает, что разметку прочитали: 5 ноября 2026 года поштучные маршруты LaoZhang API gpt-image-2.6-web и gpt-image-2.6-sunburst-vip приняли слой без ошибки, но обведённый стул ни разу не перекрасили, и с разметкой результат был таким же, как без неё. Поэтому markup отправляйте напрямую в OpenAI или через маршрут, который передаёт тело запроса OpenAI без изменений.
Примечание: laozhang.ai — наш собственный сервис; его цены — наши тарифы, а не независимое сравнение.
Слой разметки, маска или только текст: что выбрать для точечной правки
Слой разметки нужен, когда цель трудно назвать словами: в кадре несколько одинаковых предметов, и фраза «второй стул слева» уже не раз приводила к правке не того объекта. Если объект в кадре один и легко называется, хватит текста. Маска (mask) — другой параметр со своими правилами, и в Responses API для правки отдельной области руководство OpenAI предлагает именно её, потому что markup есть только в Image API.
| Что сравниваем | Слой разметки (markup) | Маска (mask) | Только текст |
|---|---|---|---|
| Как задаётся место | Круги, наброски и другие пометки на прозрачном PNG | PNG с альфа-каналом, отмечающим область правки | Описание объекта в prompt |
| Где работает | Только Image API, /v1/images/edits | Image API и Responses API | Везде |
| Насколько точно соблюдается область | Модель видит, куда указали, но перерисовывает картинку целиком; в примере OpenAI за кругом изменилось 4,3–8,4 % | По руководству OpenAI, маска — ориентир для модели, и её форма может соблюдаться неточно | Модель угадывает цель; 5 ноября 2026 года без пометки жёлтым стал не тот из четырёх стульев |
| Ограничения | Нельзя вместе с mask и prompt_rewriter; действует на первое изображение | Тот же формат и размер, что у фото, меньше 50 МБ; действует на первое изображение | Нет |
| Когда брать | Несколько похожих объектов, нужно указать один | Правка через Responses API или область уже есть в виде маски | Объект уникален в кадре |
Если вы правите картинку не через API, а в приложении ChatGPT, там есть собственная кнопка разметки, и она перерисовывает изображение заново — об этом в статье Редактор фото ChatGPT: каждая кнопка заново рисует картинку.
Требования к слою markup: размер после EXIF, прозрачность, 16 777 216 пикселей
Требования к слою разметки по руководству OpenAI по генерации изображений, раздел Guide an edit with markup, по состоянию на 5 ноября 2026 года: отдельный прозрачный PNG с той же шириной и высотой, что у первого входного изображения после учёта ориентации, с прозрачными пикселями и не наложенный на оригинал. Первое изображение и слой могут содержать не больше 16 777 216 пикселей каждый (например, 4096×4096), файл слоя — не больше 50 МБ. Чаще всего ломаются первые два правила, и оба легко поймать до отправки.
| Правило | Типичная причина нарушения | Как проверяет скрипт ниже |
|---|---|---|
| Ширина и высота как у первого изображения после учёта ориентации | Фото с телефона хранится повёрнутым и поворачивается по EXIF, а слой нарисован по другому виду; слой экспортирован в другом масштабе | Поворачивает фото по EXIF и сравнивает размеры |
| Есть прозрачные пиксели, слой не сведён с фото | Экспорт с «объединить слои», сохранение в JPEG, отправка фото с уже нарисованным кругом | Требует RGBA и хотя бы один пиксель с альфой меньше 255 |
| Лимит пикселей для фото и для слоя | Снимок с камеры на 24 Мп | Перемножает ширину и высоту |
| Лимит размера файла слоя | Несжатый PNG очень большого разрешения | Смотрит размер файла |
| Слой относится к первому изображению; остальные — референсы | Исходное фото стоит в images не первым | Не проверяет: это порядок в запросе |
Без mask и prompt_rewriter | Параметры остались от старой функции правки | Не проверяет: это поля запроса |
В JSON-запросе есть ещё одно ограничение. По справочнику OpenAI по методу images.edit строка image_url не длиннее 20 971 520 символов, а base64 раздувает файл на треть, поэтому в data URL помещается примерно 15 МБ PNG (20 971 520 × 3/4 = 15 728 640 байт). Слой больше этого отправляйте через multipart или по file_id.

Как собрать слой разметки и проверить его до платного вызова
Слой проще нарисовать кодом, чем в редакторе: так он гарантированно совпадёт с фото по размеру и останется прозрачным. Скрипт ниже (Python, Pillow) поворачивает фото по EXIF, рисует красный эллипс на полностью прозрачном холсте того же размера и проверяет четыре правила из предыдущего раздела. Координаты x0 y0 x1 y1 — прямоугольник, в который вписан эллипс, в пикселях фото в том виде, в каком оно отображается после поворота.
"""Собирает и проверяет слой разметки для правок GPT Image 2.6 / 2.5.
Рисует красный эллипс на полностью прозрачном холсте размером с фото (после учёта EXIF-ориентации)
и проверяет правила OpenAI: та же ширина и высота, что у первого входного изображения, есть прозрачные
пиксели, не больше 16 777 216 пикселей, файл не больше 50 МБ.
Запуск: 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)) # API сравнивает размеры после учёта ориентации
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))5 ноября 2026 года скрипт прогнали на кухонном фото 1200×900 из примера OpenAI, обведя передний левый стул: команда python3 make_markup_overlay.py kitchen.png 235 610 465 785 markup.png вывела photo 1200x900 -> markup.png (5645 bytes) и OK. Готовый слой из другого источника проверяется той же функцией: python3 -c "from make_markup_overlay import check; print(check('kitchen.png', 'overlay.png'))". Слой 1000×750 к тому же фото она отклонила с сообщением size (1000, 750) != photo (1200, 900), слой, сведённый на белый фон, — с no transparent pixels (flattened overlay), а слой из примера OpenAI прошёл с пустым списком замечаний. Скрипт строгий: палитровый PNG с прозрачностью он тоже отклонит, так что сохраняйте слой в RGBA.
Проверка повторяет правила из документации OpenAI, а не ответ сервера. Она нужна потому, что некоторые маршруты не возвращают ошибку на неверный слой, и без локальной проверки вы заплатите за правку, в которой разметка ничего не значила.
Как отправить markup в /v1/images/edits: multipart и JSON
Запрос с разметкой — это обычная правка, в которую добавлено одно поле. Порядок такой:
- Поставьте исходное фото первым: в multipart это поле
image, в JSON — первый элемент массиваimages. Дополнительные изображения после него модель использует как референсы, разметка к ним не относится. - Передайте слой в поле
markup: в multipart — файлом, в JSON — объектом ровно с одним из ключейimage_url(HTTPS-адрес или base64 data URL) илиfile_id. - В
promptназовите объект через пометку («the chair inside the red circle»), опишите изменение, перечислите, что сохранить, и попросите убрать красный круг из готового фото — так сделано в примере OpenAI. Как формулировать такие правки по схеме «измени только X, сохрани Y», разобрано в руководстве по промптам GPT Image 2.6. - Задайте
sizeявно (размеры кратны 16, соотношение сторон от 1:3 до 3:1, для фото 4:3 подходит1536x1152) илиauto. Для точечной правки OpenAI советует начинать сcomplexity: "low", аqualityвыбирать по задаче. - Не передавайте
mask,prompt_rewriterиinput_fidelity: первые два несовместимы с разметкой, третий OpenAI просит не указывать при правках. - Сохраните результат из
data[0].b64_jsonи сравните его с оригиналом (процедура в разделе о проверке ниже).
Multipart через официальный Python SDK повторяет пример из руководства OpenAI:
import base64
from pathlib import Path
from openai import OpenAI
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.")
client = OpenAI() # ключ из OPENAI_API_KEY
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=PROMPT,
quality="medium",
size="1536x1152",
)
Path("edited.png").write_bytes(base64.b64decode(result.data[0].b64_json))В JSON входные изображения передаются массивом images, а слой — объектом. Если версия SDK у вас старая и не знает поля markup, этот вариант через requests от неё не зависит:
import base64, os
from pathlib import Path
import requests
def data_url(path):
return "data:image/png;base64," + base64.b64encode(Path(path).read_bytes()).decode()
body = {
"model": "gpt-image-2.6-sunburst",
"images": [{"image_url": data_url("kitchen.png")}], # первое изображение — то, которое правим
"markup": {"image_url": data_url("markup.png")}, # ровно один ключ: image_url или file_id
"prompt": PROMPT, # тот же текст, что в примере выше
"quality": "medium",
"complexity": "low",
"size": "1536x1152",
}
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()
Path("edited.png").write_bytes(base64.b64decode(r.json()["data"][0]["b64_json"]))Где markup действительно читается: тест маршрутов 5 ноября 2026 года
Напрямую в OpenAI разметка работает по документации и по опубликованному примеру. На поштучных маршрутах LaoZhang API gpt-image-2.6-web и gpt-image-2.6-sunburst-vip 5 ноября 2026 года она видимой разницы не дала. Тест был устроен так, чтобы текст сам по себе не подсказывал цель: на кухонном фото 1200×900 четыре одинаковых белых стула, слой разметки обводит передний левый, а промпт называет только «стул внутри красного круга» и просит перекрасить его в горчично-жёлтый, оставив остальные белыми. Каждую ячейку запускали по одному разу.
Примечание: laozhang.ai — наш собственный сервис; его цены — наши тарифы, а не независимое сравнение.
| Маршрут | Слой разметки | Размер ответа | Какой стул стал жёлтым | Время |
|---|---|---|---|---|
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 с |
Обведённый стул во всех четырёх случаях остался белым, красного круга ни в одном ответе не было. Первый раунд с вазой из примера OpenAI этого не показал бы: вазу на столе модель перекрашивала и без разметки, и с расплывчатым «Make the vase blue.», потому что её легко найти по одному тексту. В том же раунде VIP-маршрут принял слой неверного размера (1000×750) и непрозрачный слой с ответом 200 и без единой ошибки. Отсюда практическое правило: чтобы проверить, читает ли маршрут разметку, обведите один из нескольких одинаковых предметов и сравните ответ с разметкой и без неё.

Квадратный результат вместо исходного кадра — отдельная ловушка VIP-маршрута. Без параметра size он возвращал 2048×2048 и перекомпоновывал кухню 4:3 в квадрат, а с явным size: "1536x1152" сохранил 4:3. Маршрут gpt-image-2.6-web с разметкой отдал 1448×1086, тот же размер, что и опубликованные результаты OpenAI для этого фото с size="auto".
Для разметки через LaoZhang нужен официальный проброс: модели gpt-image-2.6-flare и gpt-image-2.6-sunburst в группе OpenAI Official (или OpenAI Official Enterprise с наценкой 20 %), оплата по токенным ценам OpenAI. По документации LaoZhang API по GPT Image тело запроса там такое же, как у официального API, меняется только model; в Python это OpenAI(base_url="https://api.laozhang.ai/v1", api_key=...) с ключом из этой группы. О markup документация не пишет, и отдельного прогона разметки через официальный проброс 5 ноября 2026 года не было, поэтому перед рабочей нагрузкой проверьте его тестом с одинаковыми предметами. Поштучные маршруты стоят $0,03 за вызов, правки включены, но для разметки они, судя по тесту выше, не годятся.
Сама разметка ничего не добавляет к цене. По руководству OpenAI правки с разметкой считаются по тем же токенным тарифам, что и остальные правки; у GPT Image 2.6 это $8 за 1 млн входных токенов изображения, $30 за 1 млн выходных и $5 за 1 млн входных текстовых. Для ориентира: одна обычная правка без разметки на Sunburst с quality: "low" через официальный проброс LaoZhang в замере команды документации LaoZhang обошлась в $0,03301.
Как проверить, что правка осталась внутри круга
Модель не вклеивает изменение в старые пиксели, а перерисовывает изображение целиком, поэтому разница с оригиналом за пределами пометки никогда не равна нулю. Вопрос в том, насколько она велика. OpenAI в примере с вазой сама советует сравнить остальную часть каждого изображения с оригиналом, и это можно сделать числом:
- Возьмите исходное фото и тот же слой разметки, что отправляли.
- Запустите скрипт ниже: он уменьшает результат до размера оригинала, закрашивает эллипс по границам пометки и выводит среднюю разницу пикселей внутри и снаружи в процентах от полной шкалы.
- Сравните два числа: внутри круга разница должна быть заметно больше, чем снаружи.
- Посмотрите глазами на то, что важно за кругом (лица, надписи, края мебели), и убедитесь, что красного круга в результате нет.
- Если снаружи изменилось много, повторите с
complexity: "low"и явным «keep the rest unchanged» в промпте или попробуйтеgpt-image-2.6-sunburstнаmediumилиhigh.
"""Сравнивает результат правки с оригиналом внутри и снаружи пометки.
Использование: python3 check_edit_area.py photo.png markup.png result.png"""
import sys
import numpy as np
from PIL import Image, ImageDraw, ImageOps
photo_path, markup_path, result_path = sys.argv[1:4]
orig = ImageOps.exif_transpose(Image.open(photo_path)).convert("RGB")
alpha = np.array(Image.open(markup_path).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 # закрашенный круг пометки
result = Image.open(result_path).convert("RGB")
print("размер результата:", result.size, "оригинал:", orig.size)
a = np.array(orig).astype(float)
b = np.array(result.resize(orig.size, Image.LANCZOS)).astype(float)
diff = np.abs(b - a).mean(axis=2) / 255 * 100 # средняя разница, % от полной шкалы
print(f"внутри пометки: {diff[inside].mean():.1f} %")
print(f"снаружи: {diff[~inside].mean():.1f} %")Скрипт рассчитан на одну пометку: при нескольких кругах или свободном наброске он берёт эллипс, вписанный в общий прямоугольник всех пометок, и тогда «внутри» окажется больше, чем вы обвели.
Ориентиры дают опубликованные OpenAI результаты примера с вазой, разобранные этим способом 5 ноября 2026 года. Оба ответа пришли размером 1448×1086 при входе 1200×900. Внутри круга изменилось 12,1 % у Sunburst и 11,2 % у Flare, снаружи — 4,3 % у Sunburst и 8,4 % у Flare, то есть в этом примере Flare изменил остальную кухню примерно вдвое сильнее. Собственный контрольный расчёт блога 5 ноября 2026 года показывает, сколько из этого шум масштабирования: если исходное фото 1200×900 увеличить до 1448×1086 и вернуть обратно фильтром LANCZOS, тот же скрипт даёт около 0,3 % снаружи, так что почти вся разница — работа модели. Это один пример, а не рейтинг моделей; OpenAI отдельно пишет, что Sunburst стабильнее от правки к правке на medium и high.
Markup и GPT Image 2.5: что пишут руководство и справочник OpenAI
Документы OpenAI по состоянию на 5 ноября 2026 года расходятся в том, каким моделям доступна разметка. Руководство по генерации изображений говорит о правках с разметкой для «supported GPT Image 2.5 and 2.6 models», а справочник по методу images.edit в описании поля markup пишет только «Supports GPT Image 2.5». Анонс Images 2.6, где разметка «comes to the API», и пример в руководстве с gpt-image-2.6-flare говорят в пользу 2.6, поэтому на 2.6 разметку можно отправлять. GPT Image 2.5 называют оба документа, хотя руководство пишет о «поддерживаемых» моделях 2.5 и списка не даёт.
Многие страницы, где разметку называют функцией GPT Image 2.5, написаны до 4 ноября 2026 года, когда у 2.6 ещё не было ID модели в API; теперь они есть — gpt-image-2.6-flare и gpt-image-2.6-sunburst. Стоит ли переводить на 2.6 остальные задачи и сколько это стоит по уровням качества, разобрано в статье GPT Image 2.6: отличия от 2.5 — GIF, SVG и low в 4 раза дороже.
Источники2
Внешние страницы, на которые ссылается это руководство, в порядке упоминания. Последнее обновление: 5 нояб. 2026 г..
Источники2
Внешние страницы, на которые ссылается это руководство, в порядке упоминания. Последнее обновление: 5 нояб. 2026 г..





