欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 能源 > AI图片生成器

AI图片生成器

2025/4/16 14:34:16 来源:https://blog.csdn.net/cnds123/article/details/147192298  浏览:    关键词:AI图片生成器

AI图片生成器

这里介绍AI图片生成器程序依赖 Pollinations.ai 的后端服务(官网 Pollinations.AI )。

先看一个效果图:

这里提供两种方法实现:一是HTML+CSS+JavaScript实现,二是python+ requests+pillow实现。

可以选用的模型:

Flux

Stable Diffusion v2

它们都依赖依赖pollinations.ai的后端服务。

模型区别

  • 选 Flux
    • 需要快速生成简单图像(如图标、基础场景)。
    • 对生成速度敏感,或提示词较为直接。
  • 选 Stable Diffusion v2
    • 需要高质量、复杂细节的图像(如艺术创作、写实场景)。
    • 需精细控制参数(如采样步骤、负面提示词)。

提示词长度限制(500字符)

提示词建议使用英文提示词(可用翻译工具辅助),如:

A beautiful modern and simple Chinese modern girl, smiling

A sunset over mountains, digital art

即使相同提示词,不同种子也会产生差异。

特别提示,目前,提示词用中文生成的图像符合度较低。

界面中,各参数的详细说明和设置建议:

 基础参数

参数名称

取值范围

默认值

功能说明

设置建议

宽度(Width)

256-2048

1024

生成图像的横向像素数

推荐使用1024x576或1280x720等标准比例,大尺寸(>1600)会增加显存消耗和生成时间

高度(Height)

256-2048

576

生成图像的纵向像素数

需与宽度保持合理比例(如16:9),避免设置极端尺寸(如2048x256)

核心控制参数

参数名称

取值范围

默认值

功能说明

设置建议

采样步骤(Steps)

50-150

80

生成过程中的迭代次数,直接影响图像质量

- 高质量:100-120
- 平衡模式:80-100
- 快速测试:50-70

CFG Scale

7-15

10

控制生成结果与提示词的贴合度(Classifier-Free Guidance)

- 严格遵循提示:12-15
- 平衡模式:9-12
- 创意发散:7-9

随机种子(Seed)

0-999999

100

控制生成随机性的数字,相同种子+相同参数会产生相似结果

- 随机探索:每次+1
- 复现结果:固定种子值
- 微调变化:种子值微调(如100→101)

提示词

参数类型

功能说明

使用技巧

正向提示词

描述你希望生成的图像内容

- 使用英文更准确
- 关键词组合:"masterpiece, 4K, cinematic lighting"
- 避免矛盾描述

负面提示词

描述需要排除的元素

- 常用:"low quality, blurry, extra fingers"
- 针对性过滤:"text, watermark, deformed"

模型选择

参数名称

可选值

默认值

功能说明

设置建议

模型(Model)

flux
stable-diffusion-v2

flux

选择不同的生成模型

flux:通用场景,细节丰富
stable-diffusion-v2:适合艺术创作,风格更强烈

参数组合示例

场景1:高质量角色设计

宽度(Width): 1280

高度(Height): 720 

采样步骤(Steps): 110

cfg: 12

model: flux

正向提示词: "cyborg warrior, intricate armor design, neon lighting, futuristic city background, cinematic composition, 8k"

负面提示词: "deformed, low resolution, watermark"

场景2:艺术风格探索

宽度(Width): 1600

高度(Height): 900

采样步骤(Steps): 90

cfg: 11

model: stable-diffusion-v2 

正向提示词: "surreal landscape, Salvador Dali style, melting clocks, vibrant colors"

负面提示词: "photorealistic, modern architecture"

场景3:快速概念草图

宽度(Width): 1024

高度(Height): 576

采样步骤(Steps): 60 

cfg: 9

model: stable-diffusion-v2

正向提示词: "medieval castle concept art, rough sketch, pencil shading"

负面提示词: "detailed, color, realistic"

一、HTML+CSS+JavaScript实现

先看效果图:

生成的图片,可右击另存为保存。

源码如下:

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><title>增强版AI文生图工具</title><style>body {max-width: 800px;margin: 20px auto;padding: 40px 30px;font-family: system-ui, -apple-system, sans-serif;background: linear-gradient(135deg, #e6f7ff 0%, #f0ebff 100%);border-radius: 24px;box-shadow: 0 12px 40px rgba(24,144,255,0.15);}.control-group {margin-bottom: 20px;}.param-group {display: grid;grid-template-columns: repeat(2, 1fr);gap: 15px;margin-bottom: 20px;}label {display: block;margin-bottom: 5px;font-weight: bold;}input, textarea, select {width: 100%;padding: 12px;border: 2px solid #69c0ff;border-radius: 12px;background: rgba(255,255,255,0.95);box-shadow: 0 4px 16px rgba(24,144,255,0.15);transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);}button {background: linear-gradient(135deg, #1890ff, #096dd9);color: white;padding: 12px 24px;border: none;border-radius: 25px;cursor: pointer;font-size: 16px;box-shadow: 0 4px 12px rgba(24,144,255,0.3);transition: all 0.2s;width: 100%;margin-top: 15px;}button:hover {transform: translateY(-2px);box-shadow: 0 6px 16px rgba(24,144,255,0.4);}#preview {margin-top: 20px;text-align: center;}#imageContainer {border: 2px solid #bae7ff;padding: 20px;border-radius: 16px;background: rgba(255,255,255,0.95);min-height: 300px;display: flex;align-items: center;justify-content: center;}.loader {border: 4px solid #f3f3f3;border-top: 4px solid #1890ff;border-radius: 50%;width: 30px;height: 30px;animation: spin 1s linear infinite;display: none;}@keyframes spin {0% { transform: rotate(0deg); }100% { transform: rotate(360deg); }}#errorMsg {color: red;display: none;margin-top: 10px;}.status-text {font-weight: bold;color: #1890ff;margin-bottom: 10px;}</style>
</head>
<body><h2>AI图片生成器(稳定版)</h2><div class="control-group"><label for="prompt">正向提示词【优先使用英文提示词(可用翻译工具辅助)】:</label><textarea id="prompt" rows="4" placeholder="示例:A cute puppy playing in the garden, 4k resolution, soft lighting"></textarea></div><div class="control-group"><label for="negativePrompt">负面提示词:</label><textarea id="negativePrompt" rows="2" placeholder="示例:blurry, deformed, low quality"></textarea></div><div class="param-group"><div><label for="width">宽度 (256-2048)</label><input type="number" id="width" value="1024" min="256" max="2048"></div><div><label for="height">高度 (256-2048)</label><input type="number" id="height" value="576" min="256" max="2048"></div><div><label for="model">模型选择</label><select id="model"><option value="flux">Flux</option><option value="stable-diffusion-v2">Stable Diffusion v2</option></select></div><div><label for="steps">采样步骤 (50-150)</label><input type="number" id="steps" value="80" min="50" max="150"></div><div><label for="cfg">CFG Scale (7-15)</label><input type="number" id="cfg" value="10" min="7" max="15"></div><div><label for="seed">随机种子</label><input type="number" id="seed" value="100" min="0"></div></div><button onclick="generateImage()">生成图片</button><div class="loader" id="loader"></div><div id="preview"><div class="status-text">状态:<span id="statusText">准备就绪</span></div><div id="imageContainer"><img id="generatedImage" style="max-width: 100%; display: none;"><div id="errorMsg"></div></div></div><script>const bannedKeywords = ['nude', 'blood', 'violence', 'nsfw'];let retryCount = 0;function validateInput(params) {const ranges = {width: [256, 2048],height: [256, 2048],steps: [50, 150],cfg: [7, 15]};// 参数范围验证Object.entries(ranges).forEach(([key, [min, max]]) => {const value = parseInt(params[key]);if (value < min || value > max) {throw new Error(`${key}需在${min}-${max}之间`);}});// 违禁词检查const promptText = params.prompt.toLowerCase();if (bannedKeywords.some(word => promptText.includes(word))) {throw new Error('提示词包含受限内容');}if (params.prompt.length > 500) {throw new Error('提示词过长(最多500字符)');}}async function generateImage() {const loader = document.getElementById('loader');const errorMsg = document.getElementById('errorMsg');const statusText = document.getElementById('statusText');const imageElement = document.getElementById('generatedImage');try {// 重置状态errorMsg.style.display = 'none';loader.style.display = 'block';statusText.textContent = '生成中...';imageElement.style.display = 'none';// 获取参数const params = {prompt: document.getElementById('prompt').value.trim(),negativePrompt: document.getElementById('negativePrompt').value.trim(),width: document.getElementById('width').value,height: document.getElementById('height').value,model: document.getElementById('model').value,steps: document.getElementById('steps').value,seed: document.getElementById('seed').value,cfg: document.getElementById('cfg').value};// 输入验证validateInput(params);// 自动修复常见问题if (retryCount > 2) {params.width = 512;params.height = 512;params.prompt += ", high quality, sharp focus";retryCount = 0;}// 构造请求URLconst baseURL = 'https://image.pollinations.ai/prompt';const queryParams = new URLSearchParams({...params,nologo: true,negativePrompt: params.negativePrompt});const finalPrompt = encodeURIComponent(`${params.prompt}, masterpiece, best quality`);const imageUrl = `${baseURL}/${finalPrompt}?${queryParams}`;// 带超时的请求const controller = new AbortController();setTimeout(() => controller.abort(), 10000);const response = await fetch(imageUrl, {signal: controller.signal});if (!response.ok) throw new Error(`API错误: ${response.status}`);// 验证内容类型const contentType = response.headers.get('content-type');if (!contentType?.includes('image')) {throw new Error('无效的图片响应');}// Blob方式加载const blob = await response.blob();if (blob.size < 1024) {throw new Error('图片数据异常');}imageElement.src = URL.createObjectURL(blob);imageElement.style.display = 'block';document.getElementById('seed').value = parseInt(params.seed) + 1;statusText.textContent = '生成成功';retryCount = 0;} catch (error) {retryCount++;errorMsg.textContent = error.message;errorMsg.style.display = 'block';statusText.textContent = '生成失败';// 特定错误处理if (error.name === 'AbortError') {errorMsg.textContent = '请求超时,请重试';}console.error('生成错误:', error);} finally {loader.style.display = 'none';}}</script>
</body>
</html>

二、python+ requests+pillow实现

先看效果图:

程序需要导入的模块:tkinter、requests、PIL(通过 Image 和 ImageTk 引入)、io、webbrowser、threading。

requests 是一个第三方库, 是一个非常流行的 HTTP 客户端库,不是 Python 自带的,所以需要安装。

PIL 是 Python Imaging Library 的缩写,现在通常使用的是它的分支 Pillow。实际上安装的是 pillow 包即可。

其他库( tkinter、io、webbrowser、threading)是 Python 的标准库,不需要额外安装。

源码如下:

import tkinter as tk
from tkinter import ttk, messagebox, filedialog
import requests
from PIL import Image, ImageTk
from io import BytesIO
import webbrowser
import threadingclass ImageGeneratorApp:def __init__(self, root):# 显式设置初始尺寸root.geometry("1000x800")self.root = rootself.root.title("AI图像生成器 - V1.3")        # 初始化默认参数self.default_params = {"width": 1024,"height": 576,"steps": 80,"cfg": 10,"seed": 100,"model": "flux"}self.original_image = Noneself.preview_size = (800, 600)  # 固定预览区域尺寸self.setup_ui()self.retry_count = 0self.is_generating = Falsedef setup_ui(self):"""界面布局"""main_frame = ttk.Frame(self.root, padding=20)main_frame.pack(fill=tk.BOTH, expand=True)# 输入区域input_frame = ttk.LabelFrame(main_frame, text="生成参数")input_frame.pack(fill=tk.X, pady=5)# 正向提示词ttk.Label(input_frame, text="正向提示词【优先使用英文提示词】:").grid(row=0, column=0, sticky=tk.W)self.prompt_entry = tk.Text(input_frame, height=4, width=50)self.prompt_entry.grid(row=1, column=0, columnspan=2, pady=5)# 负面提示词ttk.Label(input_frame, text="负面提示词:").grid(row=2, column=0, sticky=tk.W)self.negative_prompt_entry = tk.Text(input_frame, height=2, width=50)self.negative_prompt_entry.grid(row=3, column=0, columnspan=2, pady=5)# 参数控件params_frame = ttk.Frame(input_frame)params_frame.grid(row=4, column=0, columnspan=2, sticky="ew", pady=10)params_frame.columnconfigure(1, weight=1)params_frame.columnconfigure(3, weight=1)params = [("宽度", "width", 256, 2048),("高度", "height", 256, 2048),("采样步骤", "steps", 50, 150),("CFG Scale", "cfg", 7, 15),("随机种子", "seed", 0, 999999)]self.param_vars = {}for i, (label, name, min_val, max_val) in enumerate(params):row = i // 2col = (i % 2) * 2ttk.Label(params_frame, text=label).grid(row=row, column=col, sticky="w", padx=(0 if col == 0 else 20, 5), pady=5)default_val = self.default_params.get(name, min_val)var = tk.IntVar(value=default_val)spin = ttk.Spinbox(params_frame, from_=min_val, to=max_val, textvariable=var, width=15)spin.grid(row=row, column=col+1, sticky="ew", padx=(0, 20 if col == 0 else 0), pady=5)self.param_vars[name] = var# 模型选择ttk.Label(params_frame, text="模型选择:").grid(row=2, column=2, sticky="w", padx=(20, 5), pady=5)self.model_var = tk.StringVar(value="flux")ttk.Combobox(params_frame, textvariable=self.model_var, values=["flux", "stable-diffusion-v2"], state="readonly", width=13).grid(row=2, column=3, sticky="ew", pady=5)# 控制按钮btn_frame = ttk.Frame(main_frame)btn_frame.pack(pady=10)self.generate_btn = ttk.Button(btn_frame, text="生成图片", command=self.start_generation)self.generate_btn.pack(side=tk.LEFT, padx=5)self.save_btn = ttk.Button(btn_frame, text="保存图片", command=self.save_image, state=tk.DISABLED)self.save_btn.pack(side=tk.LEFT, padx=5)ttk.Button(btn_frame, text="API文档", command=lambda: webbrowser.open("https://pollinations.ai/api")).pack(side=tk.RIGHT)# 进度条self.progress = ttk.Progressbar(main_frame, mode='indeterminate', length=400)self.progress.pack(pady=5)# 图片显示区域self.image_frame = ttk.LabelFrame(main_frame, text="图片预览【800x600,保持原生成图像的宽高比】")self.image_frame.pack(fill=tk.BOTH, expand=True)# 创建Canvas实现自适应缩放self.canvas = tk.Canvas(self.image_frame, bg='#f0f0f0', width=self.preview_size[0], height=self.preview_size[1])self.canvas.pack(fill=tk.BOTH, expand=True)self.status_label = ttk.Label(self.image_frame, text="状态: 准备就绪", font=('Arial', 10))self.status_label.pack(pady=5)# 初始化占位符self.show_placeholder()def on_frame_resize(self, event):"""窗口调整大小时自动缩放图片"""if self.original_image:# 计算可用区域(减去状态栏高度)available_width = event.width - 20available_height = event.height - 50if available_width > 10 and available_height > 10:img = self.original_image.copy()img.thumbnail((available_width, available_height), Image.Resampling.LANCZOS)self.current_image = ImageTk.PhotoImage(img)self.image_label.config(image=self.current_image)def update_status(self, message, color="black"):self.root.after(0, lambda: [self.status_label.config(text=f"状态: {message}", foreground=color),self.root.update()])def start_generation(self):if not self.is_generating:self.is_generating = Trueself.generate_btn.config(state=tk.DISABLED)self.save_btn.config(state=tk.DISABLED)self.progress.start(10)threading.Thread(target=self.generate_image, daemon=True).start()def get_parameters(self):return {"prompt": self.prompt_entry.get("1.0", tk.END).strip(),"negativePrompt": self.negative_prompt_entry.get("1.0", tk.END).strip(),"width": self.param_vars["width"].get(),"height": self.param_vars["height"].get(),"steps": self.param_vars["steps"].get(),"cfg": self.param_vars["cfg"].get(),"seed": self.param_vars["seed"].get(),"model": self.model_var.get(),"nologo": "true"}def handle_error(self, error):self.retry_count += 1error_msg = f"错误: {str(error)}"self.update_status(error_msg, "red")messagebox.showerror("生成错误", error_msg)self.root.after(0, self.show_placeholder)def validate_inputs(self):banned_keywords = ["nude", "blood", "violence", "nsfw"]prompt = self.prompt_entry.get("1.0", tk.END).strip().lower()if not prompt:raise ValueError("请输入正向提示词")if len(prompt) > 500:raise ValueError("提示词过长(最多500字符)")if any(kw in prompt for kw in banned_keywords):raise ValueError("提示词包含受限内容")ranges = {"width": (256, 2048),"height": (256, 2048),"steps": (50, 150),"cfg": (7, 15),"seed": (0, 999999)}for name, var in self.param_vars.items():value = var.get()min_val, max_val = ranges.get(name, (0, 999999))if not (min_val <= value <= max_val):raise ValueError(f"{name}参数超出范围 ({min_val}-{max_val})")def build_request_url(self, params):base_url = "https://image.pollinations.ai/prompt"encoded_prompt = requests.utils.quote(f'{params["prompt"]}, masterpiece, best quality')query = "&".join(f"{k}={v}" for k, v in params.items() if k not in ["prompt"])return f"{base_url}/{encoded_prompt}?{query}"def validate_response(self, response):if response.status_code != 200:raise ValueError(f"API错误: {response.status_code}")if "image" not in response.headers.get("Content-Type", ""):raise ValueError("无效的图片响应")if len(response.content) < 1024:raise ValueError("图片数据异常")def display_image(self, image_data):         """显示图片(自动缩放至预览区域)"""try:# 清除旧内容self.canvas.delete("all")# 加载并处理图片img = Image.open(BytesIO(image_data))self.original_image = img.copy()# 计算缩放比例img_width, img_height = img.sizecanvas_width = self.canvas.winfo_width()canvas_height = self.canvas.winfo_height()# 保持宽高比缩放ratio = min(canvas_width/img_width, canvas_height/img_height)new_size = (int(img_width*ratio), int(img_height*ratio))img = img.resize(new_size, Image.Resampling.LANCZOS)# 居中显示self.tk_image = ImageTk.PhotoImage(img)x = (canvas_width - new_size[0]) // 2y = (canvas_height - new_size[1]) // 2self.canvas.create_image(x, y, anchor=tk.NW, image=self.tk_image)except Exception as e:self.handle_error(e)def show_placeholder(self):"""显示占位符(居中显示)"""self.canvas.delete("all")placeholder = Image.new("RGB", self.preview_size, (240, 240, 240))self.tk_placeholder = ImageTk.PhotoImage(placeholder)x = (self.preview_size[0] - placeholder.width) // 2y = (self.preview_size[1] - placeholder.height) // 2self.canvas.create_image(x, y, anchor=tk.NW, image=self.tk_placeholder)def generate_image(self):try:self.update_status("正在验证输入参数...", "blue")self.validate_inputs()params = self.get_parameters()self.update_status("正在连接API服务器...", "blue")image_url = self.build_request_url(params)self.update_status("正在生成图像...", "blue")response = requests.get(image_url, timeout=15)self.update_status("正在验证响应数据...", "blue")self.validate_response(response)self.root.after(0, lambda: self.display_image(response.content))self.update_status("生成成功!", "green")self.param_vars["seed"].set(params["seed"] + 1)self.retry_count = 0self.save_btn.config(state=tk.NORMAL)except Exception as e:self.handle_error(e)finally:self.progress.stop()self.is_generating = Falseself.root.after(0, lambda: self.generate_btn.config(state=tk.NORMAL))def save_image(self):if not self.original_image:messagebox.showwarning("警告", "没有可保存的图片")returnfile_path = filedialog.asksaveasfilename(defaultextension=".png",filetypes=[("PNG文件", "*.png"), ("所有文件", "*.*")])if file_path:try:self.original_image.save(file_path)messagebox.showinfo("成功", "图片保存成功")except Exception as e:messagebox.showerror("错误", f"保存失败: {str(e)}")if __name__ == "__main__":root = tk.Tk()app = ImageGeneratorApp(root)root.mainloop()

三、python+ requests+pillow实现 改进版

添加了

在线翻译

帮助

运行界面:

源码如下:

import tkinter as tk
from tkinter import ttk, messagebox, filedialog
import requests
from PIL import Image, ImageTk
from io import BytesIO
import webbrowser
import threading
import osclass ImageGeneratorApp:def __init__(self, root):# 显式设置初始尺寸root.geometry("1000x800")self.root = rootself.root.title("AI图像生成器 - V1.3")        # 初始化默认参数self.default_params = {"width": 1024,"height": 576,"steps": 80,"cfg": 10,"seed": 100,"model": "flux"}self.original_image = Noneself.preview_size = (800, 600)  # 固定预览区域尺寸self.setup_ui()self.load_urls()  # 新增网址加载self.retry_count = 0self.is_generating = Falsedef setup_ui(self):"""界面布局"""main_frame = ttk.Frame(self.root, padding=20)main_frame.pack(fill=tk.BOTH, expand=True)# 输入区域input_frame = ttk.LabelFrame(main_frame, text="生成参数")input_frame.pack(fill=tk.X, pady=5)# 正向提示词ttk.Label(input_frame, text="正向提示词【优先使用英文提示词】:").grid(row=0, column=0, sticky=tk.W)self.prompt_entry = tk.Text(input_frame, height=4, width=50)self.prompt_entry.grid(row=1, column=0, columnspan=2, pady=5)# 新增翻译网址组件(右边区域)url_frame = ttk.Frame(input_frame)url_frame.grid(row=0, column=2, rowspan=2, padx=10, sticky="e")# 网址下拉框self.url_combo = ttk.Combobox(url_frame, width=32, state="readonly")self.url_combo.pack(side=tk.LEFT, padx=2)# 打开翻译按钮self.trans_btn = ttk.Button(url_frame,text="打开翻译",width=8,command=self.open_selected_url)self.trans_btn.pack(side=tk.LEFT)# 负面提示词ttk.Label(input_frame, text="负面提示词:").grid(row=2, column=0, sticky=tk.W)self.negative_prompt_entry = tk.Text(input_frame, height=2, width=50)self.negative_prompt_entry.grid(row=3, column=0, columnspan=2, pady=5)# 参数控件params_frame = ttk.Frame(input_frame)params_frame.grid(row=4, column=0, columnspan=2, sticky="ew", pady=10)params_frame.columnconfigure(1, weight=1)params_frame.columnconfigure(3, weight=1)params = [("宽度", "width", 256, 2048),("高度", "height", 256, 2048),("采样步骤", "steps", 50, 150),("CFG Scale", "cfg", 7, 15),("随机种子", "seed", 0, 999999)]self.param_vars = {}for i, (label, name, min_val, max_val) in enumerate(params):row = i // 2col = (i % 2) * 2ttk.Label(params_frame, text=label).grid(row=row, column=col, sticky="w", padx=(0 if col == 0 else 20, 5), pady=5)default_val = self.default_params.get(name, min_val)var = tk.IntVar(value=default_val)spin = ttk.Spinbox(params_frame, from_=min_val, to=max_val, textvariable=var, width=15)spin.grid(row=row, column=col+1, sticky="ew", padx=(0, 20 if col == 0 else 0), pady=5)self.param_vars[name] = var# 模型选择ttk.Label(params_frame, text="模型选择:").grid(row=2, column=2, sticky="w", padx=(20, 5), pady=5)self.model_var = tk.StringVar(value="flux")ttk.Combobox(params_frame, textvariable=self.model_var, values=["flux", "stable-diffusion-v2"], state="readonly", width=13).grid(row=2, column=3, sticky="ew", pady=5)# 控制按钮# 在控制按钮区域修改btn_frame = ttk.Frame(main_frame)btn_frame.pack(pady=10)# 原有按钮保持不变,新增帮助按钮self.generate_btn = ttk.Button(btn_frame, text="生成图片", command=self.start_generation)self.generate_btn.pack(side=tk.LEFT, padx=5)self.save_btn = ttk.Button(btn_frame, text="保存图片", command=self.save_image, state=tk.DISABLED)self.save_btn.pack(side=tk.LEFT, padx=5)# 右侧按钮组right_btn_frame = ttk.Frame(btn_frame)right_btn_frame.pack(side=tk.RIGHT)ttk.Button(right_btn_frame, text="API文档", command=lambda: webbrowser.open("https://pollinations.ai/api")).pack(side=tk.LEFT, padx=5)ttk.Button(right_btn_frame, text="帮助", command=self.show_help).pack(side=tk.LEFT)  # 新增帮助按钮# 进度条self.progress = ttk.Progressbar(main_frame, mode='indeterminate', length=400)self.progress.pack(pady=5)# 图片显示区域self.image_frame = ttk.LabelFrame(main_frame, text="图片预览【800x600,保持原生成图像的宽高比】")self.image_frame.pack(fill=tk.BOTH, expand=True)# 创建Canvas实现自适应缩放self.canvas = tk.Canvas(self.image_frame, bg='#f0f0f0', width=self.preview_size[0], height=self.preview_size[1])self.canvas.pack(fill=tk.BOTH, expand=True)self.status_label = ttk.Label(self.image_frame, text="状态: 准备就绪", font=('Arial', 10))self.status_label.pack(pady=5)# 初始化占位符self.show_placeholder()# 新增网址相关方法def load_urls(self):"""加载翻译网址列表"""self.urls = []try:with open("翻译网址.txt", "r", encoding="utf-8") as f:for line in f:line = line.strip()if line and line.startswith("http"):self.urls.append(line)except FileNotFoundError:self.urls = ["请创建翻译网址.txt"]self.url_combo["values"] = self.urlsif self.urls:self.url_combo.current(0)def open_selected_url(self):"""打开选择的翻译网址"""url = self.url_combo.get()if url.startswith("http"):webbrowser.open(url)# 新增帮助功能def show_help(self):"""显示帮助窗口"""help_window = tk.Toplevel(self.root)help_window.title("使用帮助")help_window.geometry("600x500")# 创建带滚动条的文本框main_frame = ttk.Frame(help_window)main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)text_scroll = ttk.Scrollbar(main_frame)text_scroll.pack(side=tk.RIGHT, fill=tk.Y)help_text = tk.Text(main_frame, wrap=tk.WORD, yscrollcommand=text_scroll.set,font=("宋体", 10),padx=10,pady=10)help_text.pack(fill=tk.BOTH, expand=True)text_scroll.config(command=help_text.yview)# 格式化帮助内容help_content = """
【参数说明】◼ 基础参数▹ 宽度/高度:建议1024x576起,最大2048x2048▹ 模型选择:- flux:通用模型,细节丰富- stable-diffusion-v2:艺术风格更强◼ 核心控制▹ 采样步骤(Steps):- 50-70:快速测试- 80-100:平衡模式- 100+:高质量输出▹ CFG Scale:- 7-9:创意发散- 10-12:平衡模式- 12+:严格遵循提示▹ 随机种子:- 固定种子可复现结果- 微调值(+1)产生变体◼ 提示词技巧✓ 正向提示词:- 使用英文更准确- 示例:"4k, masterpiece, detailed eyes"✓ 负面提示词:- 过滤不需要的内容- 示例:"blurry, low quality, extra fingers"◼ 快捷键• 生成图片:Ctrl+Enter• 保存图片:Ctrl+S【常见问题】
Q:生成时间太长?
A:降低采样步骤(Steps)值/缩小尺寸Q:图像有缺陷?
A:添加负面提示词如"deformed"Q:如何保持风格一致?
A:固定随机种子(Seed)值+相似提示词【参数组合示例】
场景1:高质量角色设计
宽度(Width): 1280
高度(Height): 720  
采样步骤(Steps): 110
cfg: 12
model: flux
正向提示词: "cyborg warrior, intricate armor design, neon lighting, futuristic city background, cinematic composition, 8k"
负面提示词: "deformed, low resolution, watermark"场景2:艺术风格探索
宽度(Width): 1600
高度(Height): 900
采样步骤(Steps): 90
cfg: 11
model: stable-diffusion-v2  
正向提示词: "surreal landscape, Salvador Dali style, melting clocks, vibrant colors"
负面提示词: "photorealistic, modern architecture"场景3:快速概念草图
宽度(Width): 1024
高度(Height): 576
采样步骤(Steps): 60  
cfg: 9
model: stable-diffusion-v2
正向提示词: "medieval castle concept art, rough sketch, pencil shading"
负面提示词: "detailed, color, realistic""""# 插入带格式的文本help_text.insert(tk.END, help_content)# 设置标签格式help_text.tag_configure("title", font=("黑体", 12, "bold"), foreground="#2c3e50")help_text.tag_configure("header", font=("微软雅黑", 11, "bold"), foreground="#3498db")help_text.tag_configure("highlight", foreground="#e74c3c")# 应用格式标记format_rules = [("【参数说明】", "title"),("◼ 基础参数", "header"),("◼ 核心控制", "header"), ("◼ 提示词技巧", "header"),("【常见问题】", "title"),("Q:", "highlight"),("A:", "highlight"),("【参数组合示例】", "title"),("场景1:", "highlight"),("场景2:", "highlight"),("场景3:", "highlight")]for text, tag in format_rules:start = "1.0"while True:pos = help_text.search(text, start, tk.END)if not pos:breakend = f"{pos}+{len(text)}c"help_text.tag_add(tag, pos, end)start = endhelp_text.config(state=tk.DISABLED)def on_frame_resize(self, event):"""窗口调整大小时自动缩放图片"""if self.original_image:# 计算可用区域(减去状态栏高度)available_width = event.width - 20available_height = event.height - 50if available_width > 10 and available_height > 10:img = self.original_image.copy()img.thumbnail((available_width, available_height), Image.Resampling.LANCZOS)self.current_image = ImageTk.PhotoImage(img)self.image_label.config(image=self.current_image)def update_status(self, message, color="black"):self.root.after(0, lambda: [self.status_label.config(text=f"状态: {message}", foreground=color),self.root.update()])def start_generation(self):if not self.is_generating:self.is_generating = Trueself.generate_btn.config(state=tk.DISABLED)self.save_btn.config(state=tk.DISABLED)self.progress.start(10)threading.Thread(target=self.generate_image, daemon=True).start()def get_parameters(self):return {"prompt": self.prompt_entry.get("1.0", tk.END).strip(),"negativePrompt": self.negative_prompt_entry.get("1.0", tk.END).strip(),"width": self.param_vars["width"].get(),"height": self.param_vars["height"].get(),"steps": self.param_vars["steps"].get(),"cfg": self.param_vars["cfg"].get(),"seed": self.param_vars["seed"].get(),"model": self.model_var.get(),"nologo": "true"}def handle_error(self, error):self.retry_count += 1error_msg = f"错误: {str(error)}"self.update_status(error_msg, "red")messagebox.showerror("生成错误", error_msg)self.root.after(0, self.show_placeholder)def validate_inputs(self):banned_keywords = ["nude", "blood", "violence", "nsfw"]prompt = self.prompt_entry.get("1.0", tk.END).strip().lower()if not prompt:raise ValueError("请输入正向提示词")if len(prompt) > 500:raise ValueError("提示词过长(最多500字符)")if any(kw in prompt for kw in banned_keywords):raise ValueError("提示词包含受限内容")ranges = {"width": (256, 2048),"height": (256, 2048),"steps": (50, 150),"cfg": (7, 15),"seed": (0, 999999)}for name, var in self.param_vars.items():value = var.get()min_val, max_val = ranges.get(name, (0, 999999))if not (min_val <= value <= max_val):raise ValueError(f"{name}参数超出范围 ({min_val}-{max_val})")def build_request_url(self, params):base_url = "https://image.pollinations.ai/prompt"encoded_prompt = requests.utils.quote(f'{params["prompt"]}, masterpiece, best quality')query = "&".join(f"{k}={v}" for k, v in params.items() if k not in ["prompt"])return f"{base_url}/{encoded_prompt}?{query}"def validate_response(self, response):if response.status_code != 200:raise ValueError(f"API错误: {response.status_code}")if "image" not in response.headers.get("Content-Type", ""):raise ValueError("无效的图片响应")if len(response.content) < 1024:raise ValueError("图片数据异常")def display_image(self, image_data):         """显示图片(自动缩放至预览区域)"""try:# 清除旧内容self.canvas.delete("all")# 加载并处理图片img = Image.open(BytesIO(image_data))self.original_image = img.copy()# 计算缩放比例img_width, img_height = img.sizecanvas_width = self.canvas.winfo_width()canvas_height = self.canvas.winfo_height()# 保持宽高比缩放ratio = min(canvas_width/img_width, canvas_height/img_height)new_size = (int(img_width*ratio), int(img_height*ratio))img = img.resize(new_size, Image.Resampling.LANCZOS)# 居中显示self.tk_image = ImageTk.PhotoImage(img)x = (canvas_width - new_size[0]) // 2y = (canvas_height - new_size[1]) // 2self.canvas.create_image(x, y, anchor=tk.NW, image=self.tk_image)except Exception as e:self.handle_error(e)def show_placeholder(self):"""显示占位符(居中显示)"""self.canvas.delete("all")placeholder = Image.new("RGB", self.preview_size, (240, 240, 240))self.tk_placeholder = ImageTk.PhotoImage(placeholder)x = (self.preview_size[0] - placeholder.width) // 2y = (self.preview_size[1] - placeholder.height) // 2self.canvas.create_image(x, y, anchor=tk.NW, image=self.tk_placeholder)def generate_image(self):try:self.update_status("正在验证输入参数...", "blue")self.validate_inputs()params = self.get_parameters()self.update_status("正在连接API服务器...", "blue")image_url = self.build_request_url(params)self.update_status("正在生成图像...", "blue")response = requests.get(image_url, timeout=15)self.update_status("正在验证响应数据...", "blue")self.validate_response(response)self.root.after(0, lambda: self.display_image(response.content))self.update_status("生成成功!", "green")self.param_vars["seed"].set(params["seed"] + 1)self.retry_count = 0self.save_btn.config(state=tk.NORMAL)except Exception as e:self.handle_error(e)finally:self.progress.stop()self.is_generating = Falseself.root.after(0, lambda: self.generate_btn.config(state=tk.NORMAL))def save_image(self):if not self.original_image:messagebox.showwarning("警告", "没有可保存的图片")returnfile_path = filedialog.asksaveasfilename(defaultextension=".png",filetypes=[("PNG文件", "*.png"), ("所有文件", "*.*")])if file_path:try:self.original_image.save(file_path)messagebox.showinfo("成功", "图片保存成功")except Exception as e:messagebox.showerror("错误", f"保存失败: {str(e)}")if __name__ == "__main__":root = tk.Tk()app = ImageGeneratorApp(root)root.mainloop()

OK!

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词