目录
- 什么是文生图
- 应用场景
- 环境搭建与依赖安装
- 阿里云百炼平台配置
- 完整代码实现
- 代码逐行解析
- 运行测试
- 常见问题
- 总结
一、什么是文生图
文生图(Text-to-Image)是一种根据文字描述自动生成图片的人工智能技术。
核心原理:用户输入一段描述文字(称为"提示词"),AI模型理解文字含义后,从零开始生成一张符合描述的图片。
输入 输出
"一只穿着宇航服的橘猫,漂浮在星云中" 🖼️ 一张对应的图片
通俗理解:就像有一个永远不会累的画家,你告诉他画什么,他就能立刻画出来。
二、应用场景
场景 说明 示例提示词
营销素材 快速生成海报、广告背景 "电商促销海报,红色背景,金色字体"
游戏开发 生成角色、场景概念图 "科幻风格的机器人战士,机甲设计"
电商设计 商品展示图、主图设计 "白色运动鞋,简约风格,纯白背景"
个人创作 头像、壁纸、插画 "二次元少女,樱花飘落,日系风格"
教育培训 教学插图、课件配图 "太阳系八大行星,科普风格"
三、环境搭建与依赖安装
3.1 依赖库清单
text
python-dotenv>=1.0.0
requests>=2.31.0
Pillow>=10.0.0
库名 用途
python-dotenv 从 .env 文件读取 API Key
requests 发送 HTTP 请求调用 API
Pillow 处理和显示图片信息
3.2 一键安装
bash
pip install python-dotenv requests Pillow -i https://pypi.tuna.tsinghua.edu.cn/simple
3.3 创建项目目录
bash
mkdir ai_text_to_image
cd ai_text_to_image
3.4 项目文件结构
ai_text_to_image/
├── .env # API Key 配置文件
├── text_to_image.py # 文生图主程序
├── output_images/ # 生成的图片保存目录(自动创建)
└── README.md # 说明文档
四、阿里云百炼平台配置
4.1 获取 API Key
- 访问 阿里云百炼控制台
- 使用手机号或支付宝扫码登录
- 选择地域:华北2(北京)
- 左侧菜单找到 "API Key" → 点击 "创建API Key"
- 复制并保存生成的 API Key(以 sk- 开头)
4.2 配置环境变量
在项目根目录创建 .env 文件:
bash
DASHSCOPE_API_KEY="sk-你的API Key"
⚠️ 安全提示:不要将 .env 文件提交到 GitHub,建议添加到 .gitignore
4.3 免费额度说明
新用户开通阿里云百炼后,自动获得免费额度:
· 文生图:前50张免费
· 有效期:90天
· 可在控制台开启"免费额度用完即停"避免意外扣费
五、完整代码实现
python
"""
文生图(Text-to-Image)完整实现
使用阿里云百炼原生 API(异步调用模式)
功能:根据文字描述生成图片
"""
import os
import time
import requests
from datetime import datetime
from dotenv import load_dotenv
from PIL import Image
# ========== 初始化配置 ==========
# 加载 .env 文件中的环境变量
load_dotenv()
# 获取 API Key(从 .env 文件读取)
API_KEY = os.getenv("DASHSCOPE_API_KEY")
# 阿里云百炼 API 地址(北京地域)
BASE_URL = "https://dashscope.aliyuncs.com"
# 创建输出目录(用于保存生成的图片)
OUTPUT_DIR = "output_images"
os.makedirs(OUTPUT_DIR, exist_ok=True)
print("=" * 60)
print("🎨 文生图(Text-to-Image)实战")
print("=" * 60)
def text_to_image(prompt: str, size: str = "1024*1024"):
"""
文生图核心函数(异步调用模式)
参数:
prompt: 图片描述文字,如 "一只可爱的橘猫"
size: 图片尺寸,可选 "1024*1024", "768*1024", "1024*768"
返回:
生成的图片本地路径,失败返回 None
"""
print(f"\n📝 提示词: {prompt}")
print(f"📐 尺寸: {size}")
try:
# ========== 步骤1:创建异步任务 ==========
# 文生图 API 端点
create_url = f"{BASE_URL}/api/v1/services/aigc/image-generation/generation"
# 请求头设置
headers = {
"X-DashScope-Async": "enable", # 启用异步模式
"Authorization": f"Bearer {API_KEY}", # API 认证
"Content-Type": "application/json" # 请求体格式
}
# 请求体参数
payload = {
"model": "wan2.5-t2i-preview", # 使用通义万相 2.5 模型
"input": {
"prompt": prompt # 用户输入的提示词
},
"parameters": {
"size": size, # 图片尺寸
"n": 1 # 生成图片数量
}
}
print("📤 提交任务...")
create_response = requests.post(create_url, headers=headers, json=payload)
# 检查创建任务是否成功
if create_response.status_code != 200:
print(f"❌ 创建任务失败: {create_response.text}")
return None
# 获取任务 ID(用于后续查询结果)
task_id = create_response.json().get("output", {}).get("task_id")
if not task_id:
print(f"❌ 未获取到 task_id: {create_response.json()}")
return None
print(f"✅ 任务已创建,task_id: {task_id}")
# ========== 步骤2:轮询查询结果 ==========
query_url = f"{BASE_URL}/api/v1/tasks/{task_id}"
print("⏳ 等待生成...")
max_attempts = 30 # 最多尝试30次
attempt = 0
while attempt < max_attempts:
time.sleep(2) # 每2秒查询一次,避免频繁请求
# 查询任务状态
query_response = requests.get(query_url, headers={
"Authorization": f"Bearer {API_KEY}"
})
if query_response.status_code != 200:
print(f"⚠️ 查询失败: {query_response.text}")
attempt += 1
continue
result = query_response.json()
task_status = result.get("output", {}).get("task_status")
# 任务成功完成
if task_status == "SUCCEEDED":
# 获取图片 URL
image_urls = result.get("output", {}).get("results", [])
if image_urls:
image_url = image_urls[0].get("url")
print(f"✅ 图片生成成功")
# 下载图片到本地
img_response = requests.get(image_url)
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"{OUTPUT_DIR}/text2img_{timestamp}.png"
with open(filename, "wb") as f:
f.write(img_response.content)
print(f"💾 图片已保存: {filename}")
return filename
else:
print("❌ 未获取到图片 URL")
return None
# 任务失败
elif task_status == "FAILED":
error_msg = result.get("output", {}).get("message", "未知错误")
print(f"❌ 任务失败: {error_msg}")
return None
# 任务处理中(PENDING、RUNNING等状态)
else:
print(f"⏳ 处理中... 状态: {task_status}")
attempt += 1
print("❌ 超时:任务未在预期时间内完成")
return None
except Exception as e:
print(f"❌ 生成失败: {str(e)}")
return None
def display_image_info(image_path: str):
"""
显示图片信息(尺寸、格式等)
参数:
image_path: 图片文件路径
"""
if image_path and os.path.exists(image_path):
img = Image.open(image_path)
print(f"📷 图片信息: {img.size[0]}x{img.size[1]}, {img.format}")
return img
return None
# ========== 测试示例 ==========
if __name__ == "__main__":
# 示例1:科幻写实风格
print("\n" + "-" * 40)
print("示例1:科幻写实风格")
print("-" * 40)
img1 = text_to_image(
prompt="写实风格,4K高清,一只穿着宇航服的橘猫,漂浮在星云中",
size="1024*1024"
)
# 示例2:赛博朋克风格
print("\n" + "-" * 40)
print("示例2:赛博朋克风格")
print("-" * 40)
img2 = text_to_image(
prompt="赛博朋克风格,霓虹灯,雨天,玻璃反射,高清细节,未来的赛博朋克城市",
size="1024*1024"
)
# 示例3:可爱插画风格
print("\n" + "-" * 40)
print("示例3:可爱插画风格")
print("-" * 40)
img3 = text_to_image(
prompt="可爱插画风格,色彩鲜艳,一只柴犬穿着西装打领带,商务风格",
size="1024*1024"
)
print("\n" + "=" * 60)
print(f"🎉 所有图片已保存到 {OUTPUT_DIR}/ 目录")
print("=" * 60)
六、代码逐行解析
6.1 核心概念:异步调用模式
阿里云百炼的文生图 API 采用异步调用模式,分为两步:
步骤 说明 API 端点
步骤1 提交任务,获取 task_id /api/v1/services/aigc/image-generation/generation
步骤2 用 task_id 轮询查询结果 /api/v1/tasks/{task_id}
6.2 为什么用异步模式?
同步模式 异步模式
请求一直等待直到完成 立即返回任务ID
可能超时(处理时间长) 可随时查询进度
不适合图像生成 标准做法
6.3 关键代码解析
- 环境变量加载
python
load_dotenv() # 加载 .env 文件
API_KEY = os.getenv("DASHSCOPE_API_KEY") # 读取 API Key
- 异步任务创建
python
headers = {
"X-DashScope-Async": "enable", # 关键:启用异步模式
"Authorization": f"Bearer {API_KEY}", # 认证
"Content-Type": "application/json"
}
payload = {
"model": "wan2.5-t2i-preview", # 模型名称
"input": {"prompt": prompt}, # 提示词
"parameters": {"size": size, "n": 1} # 参数:尺寸、数量
}
- 轮询结果
python
while attempt < max_attempts:
time.sleep(2) # 每2秒查询一次
result = requests.get(query_url, headers={...})
status = result["output"]["task_status"]
if status == "SUCCEEDED":
# 成功,获取图片
image_url = result["output"]["results"][0]["url"]
break
elif status == "FAILED":
# 失败,退出
break
# else: 继续等待
- 保存图片
python
# 下载图片二进制数据
img_response = requests.get(image_url)
# 保存为本地文件
with open(filename, "wb") as f:
f.write(img_response.content)
七、运行测试
7.1 执行脚本
bash
python text_to_image.py
7.2 预期输出
============================================================
🎨 文生图(Text-to-Image)实战
============================================================
----------------------------------------
示例1:科幻写实风格
----------------------------------------
📝 提示词: 写实风格,4K高清,一只穿着宇航服的橘猫,漂浮在星云中
📐 尺寸: 1024*1024
📤 提交任务...
✅ 任务已创建,task_id: 8f3b6a1c-9d4e-4f2a-8c1e-3b5f7a9d2c1e
⏳ 等待生成...
⏳ 处理中... 状态: PENDING
⏳ 处理中... 状态: RUNNING
✅ 图片生成成功
💾 图片已保存: output_images/text2img_20260115_143025.png
----------------------------------------
示例2:赛博朋克风格
----------------------------------------
...
============================================================
🎉 所有图片已保存到 output_images/ 目录
============================================================
7.3 查看生成的图片
bash
ls output_images/
# 输出: text2img_20260115_143025.png text2img_20260115_143045.png ...
八、常见问题
Q1:提示 No module named 'dotenv'
bash
pip install python-dotenv
Q2:提示 API Key 无效
检查 .env 文件中的 API Key 是否正确,注意不要有多余空格或引号。
Q3:生成失败,提示 404
检查 API 地址是否正确,北京地域使用 https://dashscope.aliyuncs.com
Q4:生成速度慢?
每次生成需要 5-15 秒,属于正常现象。异步模式本身就需要等待。
Q5:如何提高图片质量?
在提示词中加入质量关键词,如:
· 4K高清
· 高细节
· 写实风格
· 8K分辨率
Q6:免费额度用完了怎么办?
· 可以继续充值使用(按量付费)
· 或使用其他模型如 flux-chinese-optimized(有新用户免费额度)
九、提示词编写技巧
9.1 好的提示词结构
[风格] + [主体] + [环境] + [细节] + [质量词]
9.2 示例对比
提示词类型 示例
简单 "一只猫"
中等 "一只橘猫,坐在窗台上"
详细 "写实风格,一只橘猫坐在窗台上看日落,温暖色调,4K高清"
9.3 风格关键词参考
风格 关键词
写实 写实风格、真实照片质感、4K高清
插画 插画风格、可爱卡通、色彩鲜艳
科幻 赛博朋克、未来感、霓虹灯
水墨 中国水墨画风格、意境优美
十、总结
本文实现了文生图的核心功能:
步骤 功能 代码实现
1 提交任务 requests.post() + 异步头
2 获取任务ID response.json()["output"]["task_id"]
3 轮询结果 while 循环 + time.sleep()
4 下载图片 requests.get(image_url)
5 保存本地 open(filename, "wb")
核心流程图:
用户输入提示词
│
▼
┌─────────────┐
│ 提交任务 │ → 获得 task_id
└─────────────┘
│
▼
┌─────────────┐
│ 轮询查询 │ ← 每2秒一次
└─────────────┘
│
├── 成功 ──→ 下载图片 ──→ 保存本地
│
└── 失败 ──→ 打印错误信息
核心代码模板(精简版):
python
# 提交任务
response = requests.post(api_url, headers=headers, json=payload)
task_id = response.json()["output"]["task_id"]
# 轮询结果
while True:
time.sleep(2)
result = requests.get(f"{base_url}/api/v1/tasks/{task_id}", headers=headers)
if result.json()["output"]["task_status"] == "SUCCEEDED":
image_url = result.json()["output"]["results"][0]["url"]
break