图像和视觉
概览
在本指南中,你将了解如何使用 OpenAI API 构建与图像相关的应用。
如果你已经明确知道自己要构建什么,可以直接根据下方对应的使用场景开始。如果你还不确定从哪里入手,可以继续阅读本页概览。
图像相关使用场景一览
最新的语言模型已经能够处理图像输入并对其进行分析,这项能力通常称为 视觉(vision)。GPT Image 模型则可以结合文本和图像输入,生成新图像,或对已有图像进行编辑。
OpenAI API 提供了多个端点,既可以将图像作为输入处理,也可以将图像作为输出生成,从而支持你构建强大的多模态应用。
| API | 支持的使用场景 |
|---|---|
| Responses API | 分析图像,将图像作为输入,并且/或者将图像作为输出生成 |
| Images API | 生成图像输出,并可选择将图像作为输入 |
| Chat Completions API | 分析图像,并将图像作为输入生成文本或音频 |
如需进一步了解各模型支持的输入与输出模态,请参考我们的模型页面。
生成或编辑图像
你可以使用 Image API 或 Responses API 生成或编辑图像。
当前最先进的图像生成模型 gpt-image-2,能够理解文本和图像,并结合广泛的世界知识生成高质量图像,具备较强的指令遵循能力与上下文理解能力。
使用 Responses API 生成图像:
javascript
import OpenAI from "openai";
const openai = new OpenAI();
const response = await openai.responses.create({
model: "gpt-5.4-mini",
input: "Generate an image of gray tabby cat hugging an otter with an orange scarf",
tools: [{type: "image_generation"}],
});
// Save the image to a file
const imageData = response.output
.filter((output) => output.type === "image_generation_call")
.map((output) => output.result);
if (imageData.length > 0) {
const imageBase64 = imageData[0];
const fs = await import("fs");
fs.writeFileSync("cat_and_otter.png", Buffer.from(imageBase64, "base64"));
}python
from openai import OpenAI
import base64
client = OpenAI()
response = client.responses.create(
model="gpt-5.4-mini",
input="Generate an image of gray tabby cat hugging an otter with an orange scarf",
tools=[{"type": "image_generation"}],
)
# Save the image to a file
image_data = [
output.result
for output in response.output
if output.type == "image_generation_call"
]
if image_data:
image_base64 = image_data[0]
with open("cat_and_otter.png", "wb") as f:
f.write(base64.b64decode(image_base64))bash
openai responses create \
--model gpt-5.5 \
--raw-output \
--transform 'output.#(type=="image_generation_call").result' <<'YAML' | base64 --decode > cat_and_otter.png
tools:
- type: image_generation
input: Generate an image of a gray tabby cat hugging an otter with an orange scarf.
YAML你可以在我们的图像生成指南中了解更多内容。
利用世界知识进行图像生成
GPT Image 模型能够利用对现实世界的视觉理解,在没有参考图的情况下生成带有真实细节、更加逼真的图像。
例如,如果你要求 GPT Image 生成一个陈列最受欢迎半宝石的玻璃柜,模型会知道应该选择紫水晶、粉晶、玉石等宝石,并以较为真实的方式表现出来。
图像分析
视觉(Vision) 指的是模型“看见”并理解图像的能力。如果图像中包含文字,模型通常也可以理解这些文字。
它能够理解大多数视觉元素,包括物体、形状、颜色和纹理,当然也仍然存在一些局限性。
将图像作为模型输入
你可以通过多种方式把图像作为输入传给生成请求:
- 提供图像文件的完整 URL
- 提供 Base64 编码后的 data URL
- 提供文件 ID(通过 Files API 创建)
你也可以在一次请求中,通过在 content 数组里放入多个图像,实现多图输入。不过要注意,图像也会计入 token,并按此计费。
通过 URL 传入图像
分析图像内容:
javascript
import OpenAI from "openai";
const openai = new OpenAI();
const response = await openai.responses.create({
model: "gpt-5.4-mini",
input: [{
role: "user",
content: [
{ type: "input_text", text: "what's in this image?" },
{
type: "input_image",
image_url: "https://api.nga.gov/iiif/a2e6da57-3cd1-4235-b20e-95dcaefed6c8/full/!800,800/0/default.jpg",
},
],
}],
});
console.log(response.output_text);python
from openai import OpenAI
client = OpenAI()
response = client.responses.create(
model="gpt-5.4-mini",
input=[{
"role": "user",
"content": [
{"type": "input_text", "text": "what's in this image?"},
{
"type": "input_image",
"image_url": "https://api.nga.gov/iiif/a2e6da57-3cd1-4235-b20e-95dcaefed6c8/full/!800,800/0/default.jpg",
},
],
}],
)
print(response.output_text)csharp
using OpenAI.Responses;
string key = Environment.GetEnvironmentVariable("XIKAPI_API_KEY")!;
OpenAIResponseClient client = new(model: "gpt-5", apiKey: key);
Uri imageUrl = new("https://api.nga.gov/iiif/a2e6da57-3cd1-4235-b20e-95dcaefed6c8/full/!800,800/0/default.jpg");
OpenAIResponse response = (OpenAIResponse)client.CreateResponse([
ResponseItem.CreateUserMessageItem([
ResponseContentPart.CreateInputTextPart("What is in this image?"),
ResponseContentPart.CreateInputImagePart(imageUrl)
])
]);
Console.WriteLine(response.GetOutputText());bash
curl https://xikapi.com/v1/responses \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $XIKAPI_API_KEY" \
-d '{
"model": "gpt-5.4-mini",
"input": [
{
"role": "user",
"content": [
{"type": "input_text", "text": "what is in this image?"},
{
"type": "input_image",
"image_url": "https://api.nga.gov/iiif/a2e6da57-3cd1-4235-b20e-95dcaefed6c8/full/!800,800/0/default.jpg"
}
]
}
]
}'bash
openai responses create \
--model gpt-5.5 \
--raw-output \
--transform 'output.#(type=="message").content.0.text' <<'YAML'
input:
- role: user
content:
- type: input_text
text: What is in this image?
- type: input_image
image_url: https://api.nga.gov/iiif/a2e6da57-3cd1-4235-b20e-95dcaefed6c8/full/!800,800/0/default.jpg
YAML通过 Base64 编码传入图像
分析图像内容:
javascript
import fs from "fs";
import OpenAI from "openai";
const openai = new OpenAI();
const imagePath = "path_to_your_image.jpg";
const base64Image = fs.readFileSync(imagePath, "base64");
const response = await openai.responses.create({
model: "gpt-5.4-mini",
input: [
{
role: "user",
content: [
{ type: "input_text", text: "what's in this image?" },
{
type: "input_image",
image_url: `data:image/jpeg;base64,${base64Image}`,
},
],
},
],
});
console.log(response.output_text);python
import base64
from openai import OpenAI
client = OpenAI()
# Function to encode the image
def encode_image(image_path):
with open(image_path, "rb") as image_file:
return base64.b64encode(image_file.read()).decode("utf-8")
# Path to your image
image_path = "path_to_your_image.jpg"
# Getting the Base64 string
base64_image = encode_image(image_path)
response = client.responses.create(
model="gpt-5.4",
input=[
{
"role": "user",
"content": [
{ "type": "input_text", "text": "what's in this image?" },
{
"type": "input_image",
"image_url": f"data:image/jpeg;base64,{base64_image}",
},
],
}
],
)
print(response.output_text)csharp
using OpenAI.Responses;
string key = Environment.GetEnvironmentVariable("XIKAPI_API_KEY")!;
OpenAIResponseClient client = new(model: "gpt-5", apiKey: key);
Uri imageUrl = new("https://openai-documentation.vercel.app/images/cat_and_otter.png");
using HttpClient http = new();
// Download an image as stream
using var stream = await http.GetStreamAsync(imageUrl);
OpenAIResponse response1 = (OpenAIResponse)client.CreateResponse([
ResponseItem.CreateUserMessageItem([
ResponseContentPart.CreateInputTextPart("What is in this image?"),
ResponseContentPart.CreateInputImagePart(BinaryData.FromStream(stream), "image/png")
])
]);
Console.WriteLine($"From image stream: {response1.GetOutputText()}");
// Download an image as byte array
byte[] bytes = await http.GetByteArrayAsync(imageUrl);
OpenAIResponse response2 = (OpenAIResponse)client.CreateResponse([
ResponseItem.CreateUserMessageItem([
ResponseContentPart.CreateInputTextPart("What is in this image?"),
ResponseContentPart.CreateInputImagePart(BinaryData.FromBytes(bytes), "image/png")
])
]);
Console.WriteLine($"From byte array: {response2.GetOutputText()}");通过文件 ID 传入图像
分析图像内容:
javascript
import OpenAI from "openai";
import fs from "fs";
const openai = new OpenAI();
// Function to create a file with the Files API
async function createFile(filePath) {
const fileContent = fs.createReadStream(filePath);
const result = await openai.files.create({
file: fileContent,
purpose: "vision",
});
return result.id;
}
// Getting the file ID
const fileId = await createFile("path_to_your_image.jpg");
const response = await openai.responses.create({
model: "gpt-5.4-mini",
input: [
{
role: "user",
content: [
{ type: "input_text", text: "what's in this image?" },
{
type: "input_image",
file_id: fileId,
},
],
},
],
});
console.log(response.output_text);python
from openai import OpenAI
client = OpenAI()
# Function to create a file with the Files API
def create_file(file_path):
with open(file_path, "rb") as file_content:
result = client.files.create(
file=file_content,
purpose="vision",
)
return result.id
# Getting the file ID
file_id = create_file("path_to_your_image.jpg")
response = client.responses.create(
model="gpt-5.4-mini",
input=[{
"role": "user",
"content": [
{"type": "input_text", "text": "what's in this image?"},
{
"type": "input_image",
"file_id": file_id,
},
],
}],
)
print(response.output_text)csharp
using OpenAI.Files;
using OpenAI.Responses;
string key = Environment.GetEnvironmentVariable("XIKAPI_API_KEY")!;
OpenAIResponseClient client = new(model: "gpt-5", apiKey: key);
string filename = "cat_and_otter.png";
Uri imageUrl = new($"https://openai-documentation.vercel.app/images/{filename}");
using var http = new HttpClient();
// Download an image as stream
using var stream = await http.GetStreamAsync(imageUrl);
OpenAIFileClient files = new(key);
OpenAIFile file = await files.UploadFileAsync(BinaryData.FromStream(stream), filename, FileUploadPurpose.Vision);
OpenAIResponse response = (OpenAIResponse)client.CreateResponse([
ResponseItem.CreateUserMessageItem([
ResponseContentPart.CreateInputTextPart("what's in this image?"),
ResponseContentPart.CreateInputImagePart(file.Id)
])
]);
Console.WriteLine(response.GetOutputText());图像输入要求
输入图像需要满足以下要求,才能在 API 中正常使用。
| 支持的文件类型 | - PNG (`.png`) - JPEG (`.jpeg` 和 `.jpg`) - WEBP (`.webp`) - 非动态图 GIF (`.gif`) |
| 大小限制 | - 单次请求总载荷最多 512 MB - 单次请求最多 1500 张单独图像输入 |
| 其他要求 | - 不包含水印或 Logo - 不包含 NSFW 内容 - 清晰到足以让人类理解 |
选择图像细节级别
detail 参数用于告诉模型在处理和理解图像时使用什么精度级别(low、high、original 或 auto)。如果你省略该参数,模型会使用 auto。在 Responses API 和 Chat Completions API 中,这一行为是一致的。在 gpt-5.5 上,auto 和默认省略参数的行为等价于 original。
选择细节级别时可参考下表:
| 细节级别 | 最适合的场景 |
|---|---|
low | 当不需要精细视觉细节时,用于快速、低成本地理解图像。模型接收的是 512px x 512px 的低分辨率版本。 |
high | 标准高保真图像理解。 |
original | 适合大尺寸、信息密集、空间敏感,或计算机使用(computer-use)类图像。适用于 gpt-5.4 及未来模型。 |
auto | 自动选择细节级别。在 gpt-5.5 上,auto 与默认省略时都等价于 original。 |
对于 gpt-5.4 及未来模型上的计算机使用、定位与点击精度场景,我们建议使用 "detail": "original"。详见计算机使用指南。
关于模型如何缩放图像,可继续阅读下方的模型尺寸行为;关于 token 成本,可阅读后面的成本计算。
模型尺寸行为
不同模型在图像 token 化前,使用的缩放规则并不相同:
| 模型家族 | 支持的细节级别 | Patch 与缩放行为 |
|---|---|---|
gpt-5.5 | low, high, original, auto | high 最多允许 2,500 个 patch,或最大边长 2048 像素。 original 最多允许 10,000 个 patch,或最大边长 6000 像素。 如果超出任一限制,我们会在保留宽高比的前提下,对图像进行缩放,使其满足所选细节级别下两个约束中更严格的那个。auto 与省略 detail 时,使用与 original 相同的缩放行为。 |
gpt-5.4 | low, high, original, auto | high 最多允许 2,500 个 patch,或最大边长 2048 像素。 original 最多允许 10,000 个 patch,或最大边长 6000 像素。 如果超出任一限制,我们会在保留宽高比的前提下,对图像进行缩放,使其满足所选细节级别下两个约束中更严格的那个。auto 与省略 detail 时,使用与 high 相同的缩放行为。 |
gpt-5.4-mini、gpt-5.4-nano、gpt-5-mini、gpt-5-nano、 gpt-5.2、gpt-5.3-codex、gpt-5-codex-mini、 gpt-5.1-codex-mini、gpt-5.2-codex、gpt-5.2-chat-latest、 o4-mini,以及 2025-04-14 快照版本的 gpt-4.1-mini 与 gpt-4.1-nano | low, high, auto | high 最多允许 1,536 个 patch,或最大边长 2048 像素。 如果超出任一限制,我们会在保留宽高比的前提下,对图像进行缩放,使其满足两个约束中更严格的那个。 |
GPT-4o、GPT-5.4、GPT-4o-mini、 computer-use-preview,以及除 o4-mini 外的 o 系列模型 | low, high, auto | 使用基于 tile 的缩放行为。详见后文对应说明。 |
成本计算
图像输入与文本输入类似,也是按照 token 单位计量和计费。图像如何转换为文本 token 输入,取决于具体模型。你可以在价格页面的 FAQ 中找到视觉定价计算器。
基于 patch 的图像 token 化
某些模型会通过 32px x 32px 的 patch 覆盖整张图像来完成 token 化。每个模型都有一个最大的 patch 预算。图像的 token 成本按以下方式确定:
A. 计算覆盖原始图像所需的 32px x 32px patch 数量。patch 可以超出图像边界。
text
original_patch_count = ceil(width/32)×ceil(height/32)B. 如果原始图像会超出模型的 patch 预算,则按比例缩小图像直到满足预算。然后再调整缩放比例,以确保在转换为整数像素维度并重新计算 patch 覆盖数之后,最终尺寸仍在预算内。
text
shrink_factor = sqrt((32^2 * patch_budget) / (width * height))
adjusted_shrink_factor = shrink_factor * min(
floor(width * shrink_factor / 32) / (width * shrink_factor / 32),
floor(height * shrink_factor / 32) / (height * shrink_factor / 32)
)C. 将调整后的缩放比例转换为整数像素尺寸,然后计算覆盖缩放后图像所需的 patch 数量。这个缩放后的 patch 数,就是应用模型倍率前的图像 token 数,并且不会超过模型的 patch 预算。
text
resized_patch_count = ceil(resized_width/32)×ceil(resized_height/32)D. 按模型对应倍率计算最终 token 总数:
| 模型 | 倍率 |
|---|---|
gpt-5.4-mini | 1.62 |
gpt-5.4-nano | 2.46 |
gpt-5-mini | 1.62 |
gpt-5-nano | 2.46 |
gpt-4.1-mini* | 1.62 |
gpt-4.1-nano* | 2.46 |
o4-mini | 1.72 |
* 对于 gpt-4.1-mini 和 gpt-4.1-nano,这里指的是 2025-04-14 快照版本。
对于 patch 预算为 1,536 的模型,成本计算示例:
一张 1024 x 1024 图像,缩放后 patch 数为 1024
- A.
original_patch_count = ceil(1024 / 32) * ceil(1024 / 32) = 32 * 32 = 1024 - B.
1024低于1,536的 patch 预算,因此无需缩放 - C.
resized_patch_count = 1024 - 应用模型倍率前的 patch 数:
1024 - 之后再乘以模型 token 倍率,即可得到最终计费 token
- A.
一张 1800 x 2400 图像,缩放后 patch 数为 1452
- A.
original_patch_count = ceil(1800 / 32) * ceil(2400 / 32) = 57 * 75 = 4275 - B.
4275超出了1,536的 patch 预算,因此先计算shrink_factor = sqrt((32^2 * 1536) / (1800 * 2400)) = 0.603 - 然后进一步调整缩放比例,确保最终整数像素尺寸在 patch 计算后仍不超预算:
adjusted_shrink_factor = 0.603 * min(floor(1800 * 0.603 / 32) / (1800 * 0.603 / 32), floor(2400 * 0.603 / 32) / (2400 * 0.603 / 32)) = 0.586 - 缩放后的整数像素尺寸:
1056 x 1408 - C.
resized_patch_count = ceil(1056 / 32) * ceil(1408 / 32) = 33 * 44 = 1452 - 应用模型倍率前的 patch 数:
1452 - 最终再乘以模型倍率,得到计费 token
- A.
基于 tile 的图像 token 化
GPT-4o、GPT-5.4、GPT-4o-mini、CUA 和 o 系列(不含 o4-mini)
图像的 token 成本由两个因素决定:尺寸与细节级别。
任何设置为 "detail": "low" 的图像,都会消耗一个固定的基础 token 数,该数值因模型而异。
如果图像设置为 "detail": "high",其成本计算方式如下:
- 按原始宽高比缩放,使图像落在 2048px x 2048px 的边界框内
- 再继续缩放,使图像短边为 768px
- 统计图像中包含多少个 512px 的方块,每个方块都会消耗固定数量 token
- 最后再加上基础 token
| 模型 | 基础 tokens | Tile tokens |
|---|---|---|
| gpt-5, gpt-5-chat-latest | 70 | 140 |
| 4o, 4.1, 4.5 | 85 | 170 |
| 4o-mini | 2833 | 5667 |
| o1, o1-pro, o3 | 75 | 150 |
| computer-use-preview | 65 | 129 |
GPT Image 1
对于 GPT Image 1,图像输入成本的计算方式与上面类似,不同之处在于会把图像缩放到短边 512px,而不是 768px。
实际价格取决于图像尺寸以及input fidelity。
当 input fidelity 设置为 low 时,基础成本是 65 个图像 token,每个 tile 成本是 129 个图像 token。
当使用 high input fidelity 时,除了上述图像 token 外,还会根据图像长宽比增加额外 token:
- 如果图像是正方形,额外增加 4160 个输入图像 token
- 如果更接近竖图或横图,额外增加 6240 个 token
图像输入 token 的具体价格,请参考我们的价格页面。
局限性
虽然具备视觉能力的模型已经非常强大,并且可以用于许多场景,但你仍然需要了解这些模型的限制。以下是一些已知局限:
- 医学图像:模型不适合解释 CT 等专业医学图像,也不应被用于医疗建议
- 非英语文字:当图像中包含日语、韩语等非拉丁字母文本时,模型表现可能不够理想
- 小文字:建议放大图像中的文字以提升可读性;如果可用,使用
"detail": "original"也有助于提升效果 - 旋转问题:模型可能会误解旋转或倒置的文字与图像
- 视觉元素:当图表或文本依赖颜色、线型(如实线、虚线、点线)变化表达信息时,模型可能难以准确理解
- 空间推理:模型不擅长需要精确空间定位的任务,例如识别国际象棋棋盘位置
- 准确性:在某些场景中,模型可能会生成不正确的描述或标题
- 图像形状:模型对全景图和鱼眼图的处理能力较弱
- 元数据与缩放:模型不会处理原始文件名或元数据;并且会根据图像大小与
detail级别,在分析前对图像进行缩放,因此原始尺寸可能发生变化 - 计数:模型对图像中的物体数量通常只能给出近似值
- 验证码(CAPTCHA):出于安全原因,我们的系统会阻止 CAPTCHA 的提交
我们会在 token 层面处理图像,因此每张处理过的图像都会计入你的每分钟 token 限额(TPM)。
如需获取最准确、最新的图像处理成本估算,请使用我们的图像定价计算器。