修正image-tools技能并新增NAS U盘主图素材
- 清理万相相关内容(SKILL.md、wan_image_edit.py),仅保留豆包Seedream - 修正豆包万相误称,明确为火山引擎豆包Seedream - 新增文字渲染技巧章节(双引号包裹、逐字拼写、清晰度约束) - 更新doubao-api-reference.md模型ID和参数说明 - 新增产品/NAS U盘目录(实拍图、主图、产品名称) - 清理旧的nascab目录冗余图片和脚本
@@ -1,7 +1,6 @@
|
||||
|
||||
---
|
||||
|
||||
## 引擎1:豆包万相(Doubao Seedream)
|
||||
## 豆包 Seedream(字节跳动/火山引擎)
|
||||
|
||||
使用火山引擎 Ark API 的 Doubao Seedream 模型,支持文生图、图生图、多图融合、图片编辑。
|
||||
|
||||
@@ -16,12 +15,20 @@
|
||||
| 模式 | `image`参数 | 用途 |
|
||||
|---|---|---|
|
||||
| 文生图 | 省略或`[]` | 从文字描述生成图片 |
|
||||
| 图生图 | `["url1"]` | 风格转换、精修、变换 |
|
||||
| 多图融合 | `["url1","url2",...]` | 最多14张参考图融合 |
|
||||
| 图生图 | `["url1"]` | 基于参考图生成新图,可通过prompt控制保留原图产品外观 |
|
||||
| 多图融合 | `["url1","url2",...]` | 最多10张参考图融合,prompt中用"图1/图2"指代 |
|
||||
| 图片编辑 | `["url1"]` + 编辑提示词 | 移除/替换元素、换背景等 |
|
||||
|
||||
默认模型: `doubao-seedream-5-0-260128`
|
||||
|
||||
### 图生图说明
|
||||
|
||||
Seedream 的 `image` 参数传入的是**参考图**,模型会根据 prompt 重新生成图片,**不能100%像素级保留原图**。但通过精确的 prompt 可在一定程度上保持产品形态:
|
||||
- 好的做法:`"保留图1中U盘产品的外观和形态不变,仅更换背景为白色,添加科技光效"`
|
||||
- 不好的做法:`"U盘插在电脑上"`(描述太笼统,产品外观会偏离原图)
|
||||
|
||||
|
||||
|
||||
### 文生图(Windows PowerShell)
|
||||
|
||||
```powershell
|
||||
@@ -51,12 +58,18 @@ $imgBytes = [System.IO.File]::ReadAllBytes((Resolve-Path "path\to\input.png"))
|
||||
$imgBase64 = [System.Convert]::ToBase64String($imgBytes)
|
||||
|
||||
$tmpFile = "$env:TEMP\request.json"
|
||||
$prompt = "YOUR_EDIT_INSTRUCTIONS_HERE"
|
||||
$json = @"
|
||||
{"model":"doubao-seedream-5-0-260128","prompt":"$prompt","image":["data:image/png;base64,$imgBase64"],"size":"2k","sequential_image_generation":"disabled","response_format":"url","stream":false,"watermark":false}
|
||||
"@
|
||||
$sw = [System.IO.StreamWriter]::new($tmpFile, $false, (New-Object System.Text.UTF8Encoding $false))
|
||||
$sw.Write($json); $sw.Close()
|
||||
$sw.WriteLine('{')
|
||||
$sw.WriteLine(' "model": "doubao-seedream-5-0-260128",')
|
||||
$sw.WriteLine(' "prompt": "保留图1中产品的外观和形态不变,更换背景为白色",')
|
||||
$sw.WriteLine(' "image": ["data:image/png;base64,' + $imgBase64 + '"],')
|
||||
$sw.WriteLine(' "size": "2048x2048",')
|
||||
$sw.WriteLine(' "sequential_image_generation": "disabled",')
|
||||
$sw.WriteLine(' "response_format": "url",')
|
||||
$sw.WriteLine(' "stream": false,')
|
||||
$sw.WriteLine(' "watermark": false')
|
||||
$sw.WriteLine('}')
|
||||
$sw.Close()
|
||||
|
||||
$response = curl.exe -s -X POST https://ark.cn-beijing.volces.com/api/v3/images/generations `
|
||||
-H "Content-Type: application/json" `
|
||||
@@ -69,6 +82,8 @@ curl.exe -s -o $outputPath $imageUrl
|
||||
Write-Output $outputPath
|
||||
```
|
||||
|
||||
> **注意**:当 prompt 中包含中文引号等特殊字符时,不要用 PowerShell 的 `@"..."@` here-string 拼接 JSON,应改用 `StreamWriter.WriteLine()` 逐行写入,避免解析错误。
|
||||
|
||||
### 多图融合
|
||||
|
||||
```json
|
||||
@@ -99,71 +114,70 @@ Write-Output $outputPath
|
||||
}
|
||||
```
|
||||
|
||||
### 豆包参数参考
|
||||
### Seedream 参数参考
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
|---|---|---|---|
|
||||
| `model` | string | 是 | `doubao-seedream-5-0-260128`(默认)或 `doubao-seededit-3-0-i2i`(精确编辑) |
|
||||
| `model` | string | 是 | `doubao-seedream-5-0-260128`(默认,5.0)、`doubao-seedream-4-5-251128`(4.5)、`doubao-seedream-4-0-250828`(4.0) |
|
||||
| `prompt` | string | 是 | 文本提示词,最多~300中文字或~600英文词 |
|
||||
| `image` | string[] | 否 | 参考图片URL或Base64(`data:image/png;base64,...`),最多14张 |
|
||||
| `size` | string | 否 | `2k`(默认)、`3k`、`4k` 或 `WIDTHxHEIGHT`(如`2048x1024`),必须小写 |
|
||||
| `image` | string[] | 否 | 参考图片URL或Base64(`data:image/jpeg;base64,...`),最多10张;prompt中用"图1/图2"指代顺序 |
|
||||
| `size` | string | 否 | `2k`(默认)、`3k`(仅5.0)、`4k`(4.5/4.0) 或 `WIDTHxHEIGHT`(如`2048x2048`) |
|
||||
| `response_format` | string | 否 | `url`(下载链接,24h有效)或 `b64_json` |
|
||||
| `output_format` | string | 否 | `jpeg`(默认)或 `png`(仅5.0支持) |
|
||||
| `sequential_image_generation` | string | 否 | `disabled`(默认,单图)或 `auto`(模型决定批量数) |
|
||||
| `sequential_image_generation_options` | object | 否 | `{ "max_images": N }` N为1-15,仅auto模式 |
|
||||
| `stream` | boolean | 否 | `false`(等待全部)或 `true`(逐张返回) |
|
||||
| `watermark` | boolean | 否 | 添加"AI Generated"水印,默认`false` |
|
||||
| `guidance_scale` | float | 否 | 文本遵循度(CFG),范围[1,10],仅seededit-3-0-i2i |
|
||||
| `seed` | int32 | 否 | 可复现种子,仅seededit-3-0-i2i |
|
||||
| `watermark` | boolean | 否 | 添加"AI Generated"水印,默认`true`(建议设`false`) |
|
||||
| `tools` | array | 否 | `[{ "type": "web_search" }]` 联网搜索(仅5.0) |
|
||||
|
||||
### 豆包尺寸指南
|
||||
### Seedream 尺寸指南
|
||||
|
||||
| 别名 | 近似分辨率 | 适用场景 |
|
||||
|---|---|---|
|
||||
| `2k` | ~2048px | **默认** — 质量与速度平衡 |
|
||||
| `3k` | ~3072px | 高质量,产品图 |
|
||||
| `4k` | ~4096px | 最终生产质量 |
|
||||
| `WIDTHxHEIGHT` | 自定义 | 如`2048x1024`宽幅横幅 |
|
||||
| `3k` | ~3072px | 高质量,产品图(仅5.0) |
|
||||
| `4k` | ~4096px | 最终生产质量(4.5/4.0) |
|
||||
| `WIDTHxHEIGHT` | 自定义 | 如`2048x2048`、`2048x1024` |
|
||||
|
||||
像素约束:两个维度必须在[1280, 4096],最大3:1宽高比。
|
||||
**像素约束**:
|
||||
- 方式1(别名):用`2k`/`3k`等,prompt中描述宽高比
|
||||
- 方式2(精确像素):总像素范围 [3686400, 16777216],宽高比 [1/16, 16],每个维度 [1280, 4096]
|
||||
- 两种方式不可混用
|
||||
|
||||
### 豆包提示词技巧
|
||||
### Seedream 提示词技巧
|
||||
|
||||
- **描述场景**: 主体、动作、环境、氛围
|
||||
- **指定风格**: "电影大片感"、"水彩画风"、"赛博朋克"、"oc渲染"、"超现实主义"
|
||||
- **质量关键词**: "光线追踪"、"景深"、"极致的光影"、"动态模糊"
|
||||
- **编辑指令**: "把背景换成海滩"、"移除画面中的人物"、"将风格改为水彩画"
|
||||
- **编辑指令**: "保留图1中产品外观不变,把背景换成海滩"、"移除画面中的人物"
|
||||
- **多图指代**: 多图输入时用"图1""图2"明确指代,如"保留图1的U盘,放到图2的笔记本上"
|
||||
- **中文提示词原生支持** — 无需翻译为英文
|
||||
|
||||
### 文字渲染技巧(重要)
|
||||
|
||||
Seedream 对文字渲染有特殊优化,但需要正确的提示词写法:
|
||||
|
||||
- **必须用双引号包裹文字内容**:Seedream 对双引号内的文字有特殊渲染优先级,准确率远高于不加引号
|
||||
- ✅ 正确:`标题文字"NAS U盘"`,`标签显示"自动内网穿透"`
|
||||
- ❌ 错误:`标题文字NAS U盘`,`标签显示自动内网穿透`
|
||||
- **强制清晰度约束**:加"笔画清晰醒目、无乱码无模糊"等约束条件
|
||||
- **指定字体样式**:明确"黑色加粗印刷体"、"白色大号粗体"等,避免模糊描述
|
||||
- **避免过多小字**:小字号文字像素占比太低,极易模糊出错;尽量只生成少量大号标题文字
|
||||
- **商用场景建议**:对文字精度要求高时,采用"AI生成无文字底图 + 手动/程序叠加文字"的工作流
|
||||
|
||||
### Windows注意事项
|
||||
|
||||
| 问题 | 解决方案 |
|
||||
|---|---|
|
||||
| PowerShell 5.1给JSON加UTF-8 BOM | **不要**用`Set-Content`或`[System.Text.Encoding]::UTF8`,用`[System.IO.StreamWriter]::new($path, $false, (New-Object System.Text.UTF8Encoding $false))` |
|
||||
| PowerShell破坏curl中的`"` | **始终**写JSON到临时文件,用`-d "@$tmpFile"` |
|
||||
| prompt含中文引号/特殊字符 | 用`StreamWriter.WriteLine()`逐行写JSON,不要用`@"..."@` here-string |
|
||||
| curl别名冲突 | 用`curl.exe`而非`curl` |
|
||||
| 续行符 | 用反引号`` ` `` |
|
||||
|
||||
### 豆包错误处理
|
||||
### Seedream 错误处理
|
||||
|
||||
- **401**: API Key无效 — 检查Authorization头
|
||||
- **400**: 请求错误 — 检查提示词长度、图片格式、尺寸值
|
||||
- **400**: 请求错误 — 检查提示词长度、图片格式、尺寸值(像素不低于3686400)
|
||||
- **429**: 限流 — 等待后重试
|
||||
- **500**: 服务器错误 — 稍后重试
|
||||
|
||||
### 精确编辑模型
|
||||
|
||||
需要精细编辑时,`doubao-seededit-3-0-i2i`提供额外控制:
|
||||
|
||||
```json
|
||||
{
|
||||
"model": "doubao-seededit-3-0-i2i",
|
||||
"prompt": "Change the dress color to red",
|
||||
"image": ["data:image/png;base64,..."],
|
||||
"guidance_scale": 5.5,
|
||||
"seed": 42,
|
||||
"size": "adaptive",
|
||||
"response_format": "url",
|
||||
"watermark": false
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -1,18 +1,21 @@
|
||||
# Volcengine Ark Image API Reference
|
||||
# 火山引擎 Ark 图像生成 API 参考
|
||||
|
||||
## Endpoint
|
||||
> 本文档描述字节跳动/火山引擎的豆包 Seedream 模型 API。
|
||||
> 阿里云万相(Wan)是不同厂商的产品,参见万相相关文档。
|
||||
|
||||
## 端点
|
||||
|
||||
`POST https://ark.cn-beijing.volces.com/api/v3/images/generations`
|
||||
|
||||
## Authentication
|
||||
## 认证
|
||||
|
||||
```
|
||||
Authorization: Bearer ark-119a37ed-f123-42fc-aea6-b38d47d47fc0-f7ddf
|
||||
```
|
||||
|
||||
## Response Format
|
||||
## 响应格式
|
||||
|
||||
### Success Response (response_format: "url")
|
||||
### 成功响应 (response_format: "url")
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -26,7 +29,7 @@ Authorization: Bearer ark-119a37ed-f123-42fc-aea6-b38d47d47fc0-f7ddf
|
||||
}
|
||||
```
|
||||
|
||||
### Success Response (response_format: "b64_json")
|
||||
### 成功响应 (response_format: "b64_json")
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -40,7 +43,7 @@ Authorization: Bearer ark-119a37ed-f123-42fc-aea6-b38d47d47fc0-f7ddf
|
||||
}
|
||||
```
|
||||
|
||||
### Error Response
|
||||
### 错误响应
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -51,26 +54,46 @@ Authorization: Bearer ark-119a37ed-f123-42fc-aea6-b38d47d47fc0-f7ddf
|
||||
}
|
||||
```
|
||||
|
||||
## Available Models
|
||||
## 可用模型
|
||||
|
||||
| Model ID | Capabilities | Max Size |
|
||||
|---|---|---|
|
||||
| `doubao-seedream-5-0-260128` | Text-to-image, image-to-image, multi-image fusion, editing, batch | 2K |
|
||||
| `doubao-seedream-4-5-t2i` | Text-to-image, image-to-image, multi-image fusion | 4K |
|
||||
| `doubao-seedream-4-0-t2i` | Text-to-image, image-to-image, multi-image fusion | 4K |
|
||||
| `doubao-seedream-5-0-lite-t2i` | Text-to-image, batch, web search | 3K |
|
||||
| `doubao-seedream-3-0-t2i` | Text-to-image (with seed/guidance_scale) | 2K |
|
||||
| `doubao-seededit-3-0-i2i` | Dedicated image editing (with seed/guidance_scale) | adaptive |
|
||||
| Model ID | 能力 | 最大尺寸 | 备注 |
|
||||
|---|---|---|---|
|
||||
| `doubao-seedream-5-0-260128` | 文生图、图生图、多图融合、编辑、批量、联网搜索 | 3K | **默认推荐** |
|
||||
| `doubao-seedream-5-0-lite-260128` | 文生图、批量、联网搜索 | 3K | 轻量版,速度更快 |
|
||||
| `doubao-seedream-4-5-251128` | 文生图、图生图、多图融合 | 4K | 高质量 |
|
||||
| `doubao-seedream-4-0-250828` | 文生图、图生图、多图融合 | 4K | 稳定版 |
|
||||
| `doubao-seededit-3-0-i2i` | 精确图片编辑 (seed/guidance_scale) | adaptive | **当前API Key无权限** |
|
||||
|
||||
## Image Input Formats
|
||||
> ⚠️ `doubao-seededit-3-0-i2i` 精确编辑模型在当前 API Key 下返回 404,暂不可用。
|
||||
|
||||
- **URL**: Publicly accessible HTTP/HTTPS URL
|
||||
## 图片输入格式
|
||||
|
||||
- **URL**: 公网可访问的 HTTP/HTTPS URL
|
||||
- **Base64**: `data:image/<format>;base64,<encoded_data>`
|
||||
- Format must be lowercase: `data:image/png;base64,...` (not `PNG`)
|
||||
- Supported formats: png, jpeg, webp
|
||||
- 格式必须小写: `data:image/png;base64,...`(不是 `PNG`)
|
||||
- 支持格式: png, jpeg, jpg, webp, bmp, tiff, gif
|
||||
- 文件大小: 不超过 10MB
|
||||
- 总像素: ≤ 6000×6000
|
||||
- 宽高比: [1/16, 16]
|
||||
|
||||
## Size Constraints
|
||||
## 尺寸约束
|
||||
|
||||
- Pixel range: `[1280, 4096]` for both width and height
|
||||
- Max aspect ratio: 3:1 (long edge to short edge)
|
||||
- Custom size format: `"WIDTHxHEIGHT"` (e.g., `"2048x1024"`)
|
||||
### 方式1:分辨率别名
|
||||
- `2K`(默认)、`3K`(仅5.0)、`4K`(4.5/4.0)
|
||||
- 需在 prompt 中描述宽高比/形状/用途,由模型判断具体像素
|
||||
|
||||
### 方式2:精确像素
|
||||
- 格式: `"WIDTHxHEIGHT"`(如 `"2048x2048"`)
|
||||
- 总像素范围: [3686400, 16777216](即最小约 2560×1440)
|
||||
- 宽高比范围: [1/16, 16]
|
||||
- 每个维度: [1280, 4096]
|
||||
|
||||
> ⚠️ 两种方式不可混用
|
||||
|
||||
## image 参数说明
|
||||
|
||||
- 类型: `string[]`(URL或Base64数组)
|
||||
- 最多 **10** 张参考图
|
||||
- 输入图 + 输出图总数 ≤ 15
|
||||
- prompt 中用"图1""图2"等指代图片顺序
|
||||
- **重要**: image 传入的是参考图,模型会根据 prompt 重新生成,不能100%像素级保留原图产品外观
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
import os
|
||||
import sys
|
||||
import base64
|
||||
import mimetypes
|
||||
import requests
|
||||
from urllib.request import urlretrieve
|
||||
|
||||
API_KEY = os.getenv("DASHSCOPE_API_KEY", "")
|
||||
DEFAULT_API_KEY = "sk-ef591b52e48840c6a63899c8901a9428"
|
||||
if not API_KEY:
|
||||
API_KEY = DEFAULT_API_KEY
|
||||
print(f"使用默认API Key (前8位): {DEFAULT_API_KEY[:8]}...")
|
||||
|
||||
def encode_image(file_path):
|
||||
mime_type, _ = mimetypes.guess_type(file_path)
|
||||
if not mime_type:
|
||||
mime_type = "image/png"
|
||||
with open(file_path, "rb") as f:
|
||||
return f"data:{mime_type};base64,{base64.b64encode(f.read()).decode('utf-8')}"
|
||||
|
||||
def wan_image_edit(
|
||||
prompt,
|
||||
image_path,
|
||||
output_path="wan_output.png",
|
||||
size="2K",
|
||||
negative_prompt="",
|
||||
n=1,
|
||||
prompt_extend=True
|
||||
):
|
||||
"""
|
||||
万相2.7图生图 - 基于输入图片和提示词生成新图
|
||||
|
||||
参数:
|
||||
prompt: 提示词,描述想要的效果
|
||||
image_path: 输入图片路径
|
||||
output_path: 输出图片路径
|
||||
size: 输出尺寸 ("2K" 或 "1K")
|
||||
negative_prompt: 反向提示词
|
||||
n: 生成数量 (1-4)
|
||||
prompt_extend: 是否启用提示词扩展
|
||||
|
||||
示例:
|
||||
python wan_image_edit.py "keep the product, white background" "product.png" "output.png"
|
||||
"""
|
||||
print(f"提示词: {prompt}")
|
||||
print(f"输入图片: {image_path}")
|
||||
print(f"输出路径: {output_path}")
|
||||
print(f"尺寸: {size}")
|
||||
|
||||
url = "https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation"
|
||||
headers = {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": f"Bearer {API_KEY}"
|
||||
}
|
||||
|
||||
content = [{"text": prompt}]
|
||||
if image_path:
|
||||
content.append({"image": encode_image(image_path)})
|
||||
|
||||
payload = {
|
||||
"model": "wan2.7-image-pro",
|
||||
"input": {
|
||||
"messages": [{
|
||||
"role": "user",
|
||||
"content": content
|
||||
}]
|
||||
},
|
||||
"parameters": {
|
||||
"size": size,
|
||||
"n": n,
|
||||
"prompt_extend": prompt_extend,
|
||||
"watermark": False
|
||||
}
|
||||
}
|
||||
|
||||
if negative_prompt:
|
||||
payload["parameters"]["negative_prompt"] = negative_prompt
|
||||
|
||||
try:
|
||||
resp = requests.post(url, headers=headers, json=payload, timeout=120)
|
||||
result = resp.json()
|
||||
|
||||
if resp.status_code == 200 and "output" in result:
|
||||
choices = result["output"].get("choices", [])
|
||||
if choices:
|
||||
for idx, choice in enumerate(choices):
|
||||
content_list = choice.get("message", {}).get("content", [])
|
||||
for item in content_list:
|
||||
if item.get("type") == "image":
|
||||
image_url = item["image"]
|
||||
out_path = output_path if n == 1 else output_path.replace(".png", f"_{idx}.png").replace(".jpg", f"_{idx}.jpg")
|
||||
urlretrieve(image_url, out_path)
|
||||
print(f"成功: {out_path}")
|
||||
return True
|
||||
else:
|
||||
msg = result.get("message", str(result))
|
||||
print(f"失败: {msg}")
|
||||
return False
|
||||
|
||||
except requests.exceptions.Timeout:
|
||||
print("请求超时,请重试")
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"错误: {e}")
|
||||
return False
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 3:
|
||||
print("用法: python wan_image_edit.py <提示词> <输入图片> [输出路径] [尺寸]")
|
||||
print("")
|
||||
print("示例:")
|
||||
print(' python wan_image_edit.py "keep the product, white background" "product.png" "output.png"')
|
||||
print(' python wan_image_edit.py "cyberpunk style" "product.png" "output.png" "2K"')
|
||||
print("")
|
||||
print("尺寸选项: 1K (1024x1024), 2K (2048x2048)")
|
||||
sys.exit(1)
|
||||
|
||||
prompt = sys.argv[1]
|
||||
image_path = sys.argv[2]
|
||||
output_path = sys.argv[3] if len(sys.argv) > 3 else "wan_output.png"
|
||||
size = sys.argv[4] if len(sys.argv) > 4 else "2K"
|
||||
|
||||
wan_image_edit(prompt, image_path, output_path, size)
|
||||
BIN
产品/NAS U盘/image/实拍图.png
Normal file
|
After Width: | Height: | Size: 301 KiB |
BIN
产品/NAS U盘/详情/NAS U盘主图.png
Normal file
|
After Width: | Height: | Size: 365 KiB |
|
Before Width: | Height: | Size: 3.2 MiB |
|
Before Width: | Height: | Size: 3.8 MiB |
|
Before Width: | Height: | Size: 160 KiB |
|
Before Width: | Height: | Size: 368 KiB |
|
Before Width: | Height: | Size: 364 KiB |
|
Before Width: | Height: | Size: 376 KiB |
|
Before Width: | Height: | Size: 2.7 MiB |
|
Before Width: | Height: | Size: 269 KiB |
|
Before Width: | Height: | Size: 314 KiB |
|
Before Width: | Height: | Size: 355 KiB |
|
Before Width: | Height: | Size: 369 KiB |
@@ -1,70 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""在图片上叠加文字标签:标题 + 副标题,带半透明背景条"""
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
import sys
|
||||
import os
|
||||
|
||||
def add_text_overlay(image_path, title, subtitle, output_path):
|
||||
img = Image.open(image_path).convert("RGBA")
|
||||
w, h = img.size
|
||||
|
||||
# 创建文字图层
|
||||
txt_layer = Image.new("RGBA", (w, h), (0, 0, 0, 0))
|
||||
draw = ImageDraw.Draw(txt_layer)
|
||||
|
||||
# 字体大小根据图片宽度自适应
|
||||
title_size = max(48, w // 18)
|
||||
sub_size = max(28, w // 30)
|
||||
|
||||
# 尝试加载中文字体
|
||||
font_paths = [
|
||||
r"C:\Windows\Fonts\msyhbd.ttc", # 微软雅黑粗体
|
||||
r"C:\Windows\Fonts\msyh.ttc", # 微软雅黑
|
||||
r"C:\Windows\Fonts\simhei.ttf", # 黑体
|
||||
]
|
||||
title_font = None
|
||||
sub_font = None
|
||||
for fp in font_paths:
|
||||
if os.path.exists(fp):
|
||||
title_font = ImageFont.truetype(fp, title_size)
|
||||
sub_font = ImageFont.truetype(fp, sub_size)
|
||||
break
|
||||
|
||||
if title_font is None:
|
||||
title_font = ImageFont.load_default()
|
||||
sub_font = ImageFont.load_default()
|
||||
|
||||
# 文字位置:左上角,带边距
|
||||
margin_x = w // 15
|
||||
margin_y = h // 10
|
||||
|
||||
# 绘制半透明背景条
|
||||
title_bbox = draw.textbbox((margin_x, margin_y), title, font=title_font)
|
||||
sub_bbox = draw.textbbox((margin_x, title_bbox[3] + 12), subtitle, font=sub_font)
|
||||
|
||||
bar_top = margin_y - 16
|
||||
bar_bottom = sub_bbox[3] + 16
|
||||
bar_right = max(title_bbox[2], sub_bbox[2]) + 30
|
||||
|
||||
draw.rectangle(
|
||||
[(margin_x - 16, bar_top), (bar_right, bar_bottom)],
|
||||
fill=(0, 0, 0, 140)
|
||||
)
|
||||
|
||||
# 绘制标题(白色粗体)
|
||||
draw.text((margin_x, margin_y), title, font=title_font, fill=(255, 255, 255, 255))
|
||||
|
||||
# 绘制副标题(浅白色)
|
||||
draw.text((margin_x, title_bbox[3] + 12), subtitle, font=sub_font, fill=(220, 230, 255, 230))
|
||||
|
||||
# 合成
|
||||
result = Image.alpha_composite(img, txt_layer).convert("RGB")
|
||||
result.save(output_path, "PNG")
|
||||
print(f"Saved: {output_path}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 5:
|
||||
print("Usage: python add_text.py <image_path> <title> <subtitle> <output_path>")
|
||||
sys.exit(1)
|
||||
add_text_overlay(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4])
|
||||
@@ -1,70 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""豆包万相 (Doubao Seedream) 图片生成工具 - 支持文生图/图生图"""
|
||||
import sys
|
||||
import os
|
||||
import json
|
||||
import base64
|
||||
import urllib.request
|
||||
import urllib.error
|
||||
|
||||
API_URL = "https://ark.cn-beijing.volces.com/api/v3/images/generations"
|
||||
API_KEY = "ark-119a37ed-f123-42fc-aea6-b38d47d47fc0-f7ddf"
|
||||
MODEL = "doubao-seedream-5-0-260128"
|
||||
|
||||
|
||||
def generate(prompt, input_image=None, output_path="output.png", size="2k"):
|
||||
"""生成图片。input_image 为本地路径时走图生图,否则文生图。"""
|
||||
body = {
|
||||
"model": MODEL,
|
||||
"prompt": prompt,
|
||||
"size": size,
|
||||
"sequential_image_generation": "disabled",
|
||||
"response_format": "url",
|
||||
"stream": False,
|
||||
"watermark": False,
|
||||
}
|
||||
|
||||
if input_image and os.path.exists(input_image):
|
||||
with open(input_image, "rb") as f:
|
||||
img_b64 = base64.b64encode(f.read()).decode("ascii")
|
||||
ext = os.path.splitext(input_image)[1].lower().lstrip(".")
|
||||
mime = "jpeg" if ext in ("jpg", "jpeg") else ("png" if ext == "png" else "octet-stream")
|
||||
body["image"] = [f"data:image/{mime};base64,{img_b64}"]
|
||||
|
||||
data = json.dumps(body).encode("utf-8")
|
||||
req = urllib.request.Request(
|
||||
API_URL,
|
||||
data=data,
|
||||
headers={
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": f"Bearer {API_KEY}",
|
||||
},
|
||||
method="POST",
|
||||
)
|
||||
|
||||
try:
|
||||
with urllib.request.urlopen(req, timeout=180) as resp:
|
||||
result = json.loads(resp.read().decode("utf-8"))
|
||||
except urllib.error.HTTPError as e:
|
||||
err_body = e.read().decode("utf-8", errors="replace")
|
||||
print(f"HTTP {e.code}: {err_body}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
image_url = result["data"][0]["url"]
|
||||
print(f"Generated URL: {image_url}")
|
||||
|
||||
# 下载图片
|
||||
urllib.request.urlretrieve(image_url, output_path)
|
||||
print(f"Saved to: {output_path}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# 用法: python doubao_image.py <prompt> <output_path> [input_image] [size]
|
||||
if len(sys.argv) < 3:
|
||||
print("Usage: python doubao_image.py <prompt> <output_path> [input_image] [size]")
|
||||
sys.exit(1)
|
||||
prompt = sys.argv[1]
|
||||
output_path = sys.argv[2]
|
||||
input_image = sys.argv[3] if len(sys.argv) > 3 else None
|
||||
size = sys.argv[4] if len(sys.argv) > 4 else "2k"
|
||||
generate(prompt, input_image, output_path, size)
|
||||
@@ -1,74 +0,0 @@
|
||||
# NasCabOS 商品详情页文案
|
||||
|
||||
> 产品全称:智能存储NAS相册备份无线传输共享视频影视播放手机电脑互联
|
||||
> 软件名称:NasCabOS
|
||||
> 官网:https://nas.cab/
|
||||
|
||||
---
|
||||
|
||||
## 屏1|产品主图
|
||||
|
||||

|
||||
|
||||
**NasCabOS 智能私有云**
|
||||
手机电脑互联 · 相册备份 · 影视播放 · 无需专用硬件
|
||||
|
||||
---
|
||||
|
||||
## 屏2|相册备份
|
||||
|
||||

|
||||
|
||||
**手机照片自动备份 永不丢失**
|
||||
- 插上U盘,手机照片自动无线备份到私有云
|
||||
- 时间线/地图视图,智能相册自动分类
|
||||
- 人脸识别 · AI分类,一键整理海量照片
|
||||
- 不改变原有文件夹结构,只读取和组织
|
||||
|
||||
---
|
||||
|
||||
## 屏3|影视播放
|
||||
|
||||

|
||||
|
||||
**私人影院 随时随地看**
|
||||
- 手机/iPad/电视多端播放,实时转码
|
||||
- 几乎支持所有视频格式,蓝光原盘也能播
|
||||
- 自动匹配海报,影视库式管理
|
||||
- 出门在外也能远程看家里的电影
|
||||
|
||||
---
|
||||
|
||||
## 屏4|多设备互联
|
||||
|
||||

|
||||
|
||||
**手机 电脑 平板 一盘全通**
|
||||
- Windows / macOS / Android / iOS / TV / Web 全平台
|
||||
- 局域网内所有设备同时访问,互不干扰
|
||||
- 无需专用硬件,电脑装上就能用
|
||||
- 插上U盘,旧电脑秒变NAS服务器
|
||||
|
||||
---
|
||||
|
||||
## 屏5|文件共享
|
||||
|
||||

|
||||
|
||||
**全家共享 一人管文件全家都能用**
|
||||
- FTP / SFTP / WebDAV 三协议共享
|
||||
- 每个成员独立账号,独立权限
|
||||
- 在线上传下载,远程也能访问
|
||||
- 挂载云盘,聚合多个网盘到一个入口
|
||||
|
||||
---
|
||||
|
||||
## 屏6|加密安全
|
||||
|
||||

|
||||
|
||||
**AES256加密 隐私绝不泄露**
|
||||
- 加密空间,隐藏敏感文件
|
||||
- 2FA双因素认证,Google/Microsoft验证器
|
||||
- IP黑白名单,控制谁能访问
|
||||
- WebRTC加密传输,数据不走第三方服务器
|
||||