示例
Qwen Image Edit 的实用示例和用例
示例
探索 Qwen Image Edit 的实用示例和真实世界用例。每个示例都包含完整的代码片段和说明。
文本编辑示例
添加水印
为图片添加版权水印以保护您的图像:
import { QwenImageEdit } from '@qwen-image-edit/sdk';
const client = new QwenImageEdit({ apiKey: 'your-api-key' });
// 添加简单的文本水印
const result = await client.textEdit({
image: './original-photo.jpg',
instruction: '在右下角添加水印 "© 2024 您的公司"',
style: {
fontSize: 16,
color: '#FFFFFF',
opacity: 0.7,
fontFamily: 'Arial Bold'
},
position: { x: -50, y: -30 } // 负值表示右下角定位
});
console.log('添加水印的图片:', result.editedImage);
多语言文本替换
替换不同语言的文本:
// 英文转中文
const englishToChinese = await client.textEdit({
image: './menu-english.jpg',
instruction: '将 "Welcome" 替换为 "欢迎"',
preserveStyle: true
});
// 西班牙文转英文
const spanishToEnglish = await client.textEdit({
image: './sign-spanish.jpg',
instruction: '将 "Salida" 改为 "Exit"',
style: {
fontSize: 'auto', // 自动调整字体大小
color: 'preserve' // 保持原始颜色
}
});
动态文本生成
生成带有动态文本的个性化图片:
const generatePersonalizedCard = async (userName: string, achievement: string) => {
return await client.textEdit({
image: './certificate-template.jpg',
instruction: `将占位符文本替换为姓名 "${userName}" 和成就 "${achievement}"`,
style: {
fontSize: 24,
color: '#2C3E50',
fontFamily: 'Times New Roman'
}
});
};
// 使用方法
const certificate = await generatePersonalizedCard('张三', 'AI 领域卓越表现');
语义编辑示例
风格转换
将图片转换为不同的艺术风格:
// 将照片转换为油画
const oilPainting = await client.semanticEdit({
image: './portrait.jpg',
prompt: '转换为古典油画风格,具有丰富的纹理和温暖的色彩',
strength: 0.8
});
// 创建动漫风格艺术作品
const animeStyle = await client.semanticEdit({
image: './character-photo.jpg',
prompt: '转换为动漫艺术风格,具有鲜艳的色彩和清晰的线条',
strength: 0.9,
preserveAreas: [
{ x: 100, y: 50, width: 200, height: 300 } // 保留面部区域
]
});
物体操作
在图片中添加、移除或修改物体:
// 向场景添加物体
const addObject = await client.semanticEdit({
image: './empty-room.jpg',
prompt: '在中央添加一个现代沙发,前面放一个咖啡桌',
strength: 0.7
});
// 移除不需要的物体
const removeObject = await client.semanticEdit({
image: './crowded-scene.jpg',
prompt: '从背景中移除穿红衣服的人',
strength: 0.6
});
// 改变物体属性
const changeColor = await client.semanticEdit({
image: './red-car.jpg',
prompt: '将汽车颜色从红色改为蓝色,保持其他所有内容不变',
strength: 0.5
});
背景替换
替换或修改图片背景:
// 专业头像背景
const professionalBg = await client.semanticEdit({
image: './casual-photo.jpg',
prompt: '将背景替换为专业办公环境,保持人物不变',
strength: 0.8,
preserveAreas: [
{ x: 150, y: 100, width: 300, height: 400 } // 保留人物
]
});
// 季节转换
const seasonalChange = await client.semanticEdit({
image: './summer-landscape.jpg',
prompt: '转换为冬季场景,有雪和光秃的树木',
strength: 0.9
});
批量处理示例
电商产品图片
使用一致的样式处理多个产品图片:
const processProductImages = async (productImages: string[]) => {
const operations = [
{
type: 'semantic-edit',
prompt: '放置在干净的白色背景上,专业照明',
strength: 0.6
},
{
type: 'text-edit',
instruction: '在右上角添加 "NEW" 标签',
style: {
fontSize: 20,
color: '#FF4444',
fontFamily: 'Arial Bold'
}
}
];
return await client.batchEdit({
images: productImages,
operations,
parallel: true
});
};
// 处理所有产品图片
const productUrls = [
'./product1.jpg',
'./product2.jpg',
'./product3.jpg'
];
const processedProducts = await processProductImages(productUrls);
社交媒体内容
在社交媒体帖子中创建一致的品牌形象:
const createSocialMediaPosts = async (images: string[], brandColors: string[]) => {
const socialOperations = [
{
type: 'text-edit',
instruction: '在左下角添加 "@您的品牌" 水印',
style: {
fontSize: 14,
color: brandColors[0],
opacity: 0.8
}
},
{
type: 'semantic-edit',
prompt: `应用品牌配色方案,使用 ${brandColors.join(', ')} 作为强调色`,
strength: 0.4
}
];
return await client.batchEdit({
images,
operations: socialOperations,
parallel: true
});
};
高级用例
实时图片编辑器
构建实时图片编辑界面:
class RealTimeEditor {
private client: QwenImageEdit;
private currentImage: string;
private editHistory: string[] = [];
constructor(apiKey: string) {
this.client = new QwenImageEdit({ apiKey });
}
async loadImage(imageUrl: string) {
this.currentImage = imageUrl;
this.editHistory = [imageUrl];
}
async applyEdit(instruction: string, options?: any) {
const result = await this.client.textEdit({
image: this.currentImage,
instruction,
...options
});
this.currentImage = result.editedImage;
this.editHistory.push(result.editedImage);
return result;
}
async undo() {
if (this.editHistory.length > 1) {
this.editHistory.pop();
this.currentImage = this.editHistory[this.editHistory.length - 1];
}
return this.currentImage;
}
getCurrentImage() {
return this.currentImage;
}
}
// 使用方法
const editor = new RealTimeEditor('your-api-key');
await editor.loadImage('./base-image.jpg');
// 应用多个编辑
await editor.applyEdit('添加标题 "我的艺术作品"');
await editor.applyEdit('将背景改为渐变蓝色');
await editor.applyEdit('在右下角添加签名');
// 如需要可以撤销最后一次编辑
await editor.undo();
自动化内容生成
基于模板自动生成内容:
const generateMarketingMaterials = async (campaign: {
productName: string;
price: string;
features: string[];
targetAudience: string;
}) => {
const templates = [
'./template-banner.jpg',
'./template-square.jpg',
'./template-story.jpg'
];
const results = await Promise.all(
templates.map(async (template) => {
// 添加产品信息
let result = await client.textEdit({
image: template,
instruction: `将产品名称替换为 "${campaign.productName}",价格替换为 "${campaign.price}"`,
style: { fontSize: 'auto', color: '#2C3E50' }
});
// 添加功能特性
result = await client.textEdit({
image: result.editedImage,
instruction: `添加功能列表:${campaign.features.join(', ')}`,
style: { fontSize: 14, color: '#7F8C8D' }
});
// 为目标受众定制
result = await client.semanticEdit({
image: result.editedImage,
prompt: `调整视觉风格以吸引${campaign.targetAudience}`,
strength: 0.3
});
return result;
})
);
return results;
};
// 生成营销材料
const campaign = {
productName: '智能手表 Pro',
price: '¥1999',
features: ['心率监测', 'GPS 追踪', '7天续航'],
targetAudience: '健身爱好者'
};
const marketingMaterials = await generateMarketingMaterials(campaign);
错误处理和最佳实践
健壮的错误处理
const safeImageEdit = async (image: string, instruction: string, retries = 3) => {
for (let attempt = 1; attempt <= retries; attempt++) {
try {
const result = await client.textEdit({ image, instruction });
return result;
} catch (error) {
console.log(`第 ${attempt} 次尝试失败:`, error.message);
if (attempt === retries) {
throw new Error(`${retries} 次尝试后失败: ${error.message}`);
}
// 指数退避
await new Promise(resolve => setTimeout(resolve, Math.pow(2, attempt) * 1000));
}
}
};
性能优化
// 缓存常用结果
const cache = new Map<string, any>();
const cachedEdit = async (image: string, instruction: string) => {
const cacheKey = `${image}-${instruction}`;
if (cache.has(cacheKey)) {
return cache.get(cacheKey);
}
const result = await client.textEdit({ image, instruction });
cache.set(cacheKey, result);
return result;
};
// 处理前优化图片大小
const optimizeAndEdit = async (image: string, instruction: string) => {
// 调整大图片尺寸以加快处理速度
const optimizedImage = await resizeImage(image, { maxWidth: 1024, maxHeight: 1024 });
return await client.textEdit({
image: optimizedImage,
instruction
});
};
集成示例
Next.js API 路由
// pages/api/edit-image.ts
import { NextApiRequest, NextApiResponse } from 'next';
import { QwenImageEdit } from '@qwen-image-edit/sdk';
const client = new QwenImageEdit({ apiKey: process.env.QWEN_API_KEY });
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method !== 'POST') {
return res.status(405).json({ error: '方法不允许' });
}
try {
const { image, instruction, type = 'text-edit' } = req.body;
let result;
if (type === 'text-edit') {
result = await client.textEdit({ image, instruction });
} else if (type === 'semantic-edit') {
result = await client.semanticEdit({ image, prompt: instruction });
}
res.status(200).json(result);
} catch (error) {
res.status(500).json({ error: error.message });
}
}
React 组件
// components/ImageEditor.tsx
import React, { useState } from 'react';
const ImageEditor: React.FC = () => {
const [image, setImage] = useState<string>('');
const [instruction, setInstruction] = useState<string>('');
const [result, setResult] = useState<string>('');
const [loading, setLoading] = useState<boolean>(false);
const handleEdit = async () => {
setLoading(true);
try {
const response = await fetch('/api/edit-image', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ image, instruction })
});
const data = await response.json();
setResult(data.editedImage);
} catch (error) {
console.error('编辑失败:', error);
} finally {
setLoading(false);
}
};
return (
<div className="image-editor">
<input
type="text"
placeholder="图片 URL"
value={image}
onChange={(e) => setImage(e.target.value)}
/>
<input
type="text"
placeholder="编辑指令"
value={instruction}
onChange={(e) => setInstruction(e.target.value)}
/>
<button onClick={handleEdit} disabled={loading}>
{loading ? '处理中...' : '编辑图片'}
</button>
{result && <img src={result} alt="编辑结果" />}
</div>
);
};
export default ImageEditor;
这些示例展示了 Qwen Image Edit 在不同用例和集成场景中的多样性和强大功能。从简单的文本编辑开始,随着您对 API 的熟悉逐渐探索更高级的功能。