Qwen-Image-2512-Pixel-Art-LoRA 批量处理脚本编写:自动化生成海量像素素材库
Qwen-Image-2512-Pixel-Art-LoRA 批量处理脚本编写:自动化生成海量像素素材库
你是不是也遇到过这样的烦恼?想用Qwen-Image-2512-Pixel-Art-LoRA这个模型做一套像素游戏的角色素材,结果发现要一个个手动输入提示词、等待生成、保存图片,光是生成几十张图就花了大半天,效率低得让人抓狂。
我之前给一个独立游戏工作室做素材支持,他们需要上千张不同职业、不同动作的像素角色图。如果靠人工一张张来,估计项目还没开始,美术就先崩溃了。后来我花时间写了个Python脚本,把整个流程自动化了,原本需要一周的工作量,现在一个下午就能跑完。
今天我就把这个方法分享给你,教你如何编写一个高效的批量处理脚本,让你也能轻松搭建自己的海量像素素材库。整个过程并不复杂,就算你Python刚入门,跟着步骤走也能搞定。
1. 脚本能帮你做什么?
在动手写代码之前,我们先看看这个脚本能帮你解决哪些具体问题。了解目标,写起来才更有方向。
核心痛点与解决方案:
- 痛点一:手动操作效率极低→ 脚本自动从文件读取成百上千个提示词,无需手动输入。
- 痛点二:生成过程不可控→ 脚本支持并发调用,可以同时生成多张图片,并处理失败重试。
- 痛点三:素材管理混乱→ 脚本自动按你设定的规则(如角色职业、场景类型)分类保存图片,并给图片加上元数据水印,方便后续查找和使用。
简单来说,你只需要准备一个写好了所有提示词的文本文件(比如CSV或JSON),然后运行脚本,它就会自动帮你完成“读取提示词 -> 调用模型生成 -> 处理异常 -> 保存并归类图片”的全过程。
2. 环境准备与核心思路
工欲善其事,必先利其器。我们先来把跑通脚本所需的环境搭好。
2.1 你需要准备什么?
- Python环境:确保你的电脑上安装了Python 3.8或更高版本。打开终端或命令行,输入
python --version检查一下。 - 必要的Python库:我们主要会用到几个库来处理网络请求、并发任务和文件操作。
pip install requests pandas tqdmrequests: 用来调用模型的API接口。pandas: 方便我们读取和处理CSV或Excel格式的提示词文件。tqdm: 给循环加个进度条,让你清楚知道任务进行到哪了,体验感更好。
- 模型API访问权限:确保你已经部署好了Qwen-Image-2512-Pixel-Art-LoRA模型,并且知道它的API调用地址(比如
http://localhost:8000/v1/images/generations)以及所需的认证信息(如果有的话,比如API Key)。
2.2 脚本的核心工作流程
整个脚本就像一条高效的流水线,它的工作流程非常清晰:
[提示词清单文件] → [脚本读取并解析] → [并发调用模型API] → [接收生成的图片] → [添加元数据/水印] → [按规则保存到文件夹]其中,“并发调用”是提升速度的关键,“错误重试”保证了流程的健壮性,“自动归类”则省去了你后期整理的麻烦。
3. 分步编写脚本
接下来,我们一步步把这条流水线用代码搭建起来。我会把完整的代码拆解开,并配上详细的解释。
3.1 第一步:读取批量提示词
我们首先得让脚本知道要生成什么。假设我们把所有提示词整理在一个CSV文件里,文件名叫prompts.csv,内容类似这样:
prompt,category,style “a pixel art warrior holding a sword, front view, fantasy style”,“character”,“combat” “a pixel art mage casting a fireball, side view, vibrant colors”,“character”,“magic” “a pixel art forest background with mushrooms, top-down view”,“background”,“environment” “a pixel art health potion item, glowing effect”,“item”,“consumable”第一列是具体的提示词,第二列是素材大类,第三列是子类或风格,方便我们后续分类保存。
现在,写代码来读取它:
import pandas as pd import os def load_prompts_from_csv(file_path): """ 从CSV文件加载提示词和分类信息。 参数: file_path (str): CSV文件的路径。 返回: list: 一个列表,里面每个元素都是一个字典,包含prompt, category, style等信息。 """ try: # 使用pandas读取CSV文件 df = pd.read_csv(file_path) # 将DataFrame转换为字典列表,便于后续处理 prompts_list = df.to_dict(‘records’) print(f“成功从 {file_path} 加载了 {len(prompts_list)} 条提示词。”) return prompts_list except FileNotFoundError: print(f“错误:找不到文件 {file_path},请检查路径是否正确。”) return [] except Exception as e: print(f“读取文件时发生错误:{e}”) return [] # 使用示例 if __name__ == “__main__”: prompts = load_prompts_from_csv(“prompts.csv”) for p in prompts[:2]: # 打印前两条看看 print(p)如果提示词是JSON格式,写法也类似,用Python内置的json库即可。这样,脚本就有了“生产任务清单”。
3.2 第二步:调用模型API生成单张图片
这是最核心的一步:如何与Qwen-Image-2512-Pixel-Art-LoRA模型对话,让它根据提示词生成图片。通常,这类模型会提供一个类似OpenAI格式的API。
我们需要写一个函数,负责发送一次生成请求并获取结果。
import requests import base64 from io import BytesIO from PIL import Image import time def generate_single_image(api_url, api_key, prompt_data, model_name=“Qwen-Image-2512-Pixel-Art-LoRA”): """ 调用API生成一张图片。 参数: api_url (str): 模型API的地址。 api_key (str): API密钥(如果需要)。 prompt_data (dict): 包含提示词等信息的字典。 model_name (str): 模型名称。 返回: tuple: (成功与否, 图片PIL对象或错误信息, 提示词信息) """ headers = { “Content-Type”: “application/json”, } # 如果有API Key,通常加在Authorization头里 if api_key: headers[“Authorization”] = f“Bearer {api_key}” # 构造请求体,参数需要根据你实际部署的API调整 payload = { “model”: model_name, “prompt”: prompt_data.get(‘prompt’), “n”: 1, # 每次生成1张 “size”: “1024x1024”, # 生成图片尺寸,根据模型支持调整 “response_format”: “b64_json” # 要求返回base64编码的图片 } try: response = requests.post(api_url, json=payload, headers=headers, timeout=60) response.raise_for_status() # 如果状态码不是200,抛出异常 result = response.json() # 解析返回的图片数据(base64格式) image_b64 = result[‘data’][0][‘b64_json’] image_data = base64.b64decode(image_b64) image = Image.open(BytesIO(image_data)) return True, image, prompt_data except requests.exceptions.Timeout: return False, “请求超时”, prompt_data except requests.exceptions.RequestException as e: return False, f“网络请求错误: {e}”, prompt_data except KeyError as e: return False, f“API返回数据格式异常: {e}”, prompt_data except Exception as e: return False, f“未知错误: {e}”, prompt_data这个函数是脚本的“工人”,每次调用它,它就去找模型“生产”一张图片。
3.3 第三步:实现多进程并发与错误重试
如果让这个“工人”一张一张顺序生产,那就太慢了。我们需要“雇佣”多个工人同时干活,这就是并发。同时,难免会有个别任务失败,我们需要给它们重试的机会。
这里我们用Python的concurrent.futures库中的ThreadPoolExecutor来实现多线程并发,它对于这种I/O密集型任务(网络请求)很有效。
from concurrent.futures import ThreadPoolExecutor, as_completed from tqdm import tqdm def batch_generate_images(api_url, api_key, prompts_list, max_workers=4, max_retries=2): """ 批量并发生成图片,支持错误重试。 参数: api_url (str): API地址。 api_key (str): API密钥。 prompts_list (list): 提示词字典列表。 max_workers (int): 最大并发线程数。 max_retries (int): 单任务最大重试次数。 返回: list: 成功生成的(图片对象, 提示词信息)列表。 list: 失败的任务信息列表。 """ successful_results = [] failed_tasks = [] # 定义一个内部函数,包含重试逻辑 def task_with_retry(prompt_item): retries = 0 while retries <= max_retries: success, result, prompt_info = generate_single_image(api_url, api_key, prompt_item) if success: return success, (result, prompt_info) # 成功,返回图片和提示词信息 else: retries += 1 if retries <= max_retries: print(f“提示词 ‘{prompt_item.get(‘prompt’)[:30]}...’ 第{retries}次重试...”) time.sleep(1) # 重试前稍作等待 else: return success, (result, prompt_info) # 重试次数用尽,返回失败信息 return False, (“Max retries exceeded”, prompt_item) print(f“开始批量生成 {len(prompts_list)} 张图片,使用 {max_workers} 个并发线程...”) with ThreadPoolExecutor(max_workers=max_workers) as executor: # 提交所有任务 future_to_prompt = {executor.submit(task_with_retry, p): p for p in prompts_list} # 使用tqdm创建进度条 for future in tqdm(as_completed(future_to_prompt), total=len(prompts_list), desc=“生成进度”): prompt_used = future_to_prompt[future] try: success, result = future.result() if success: successful_results.append(result) # result 是 (image, prompt_info) 元组 else: failed_tasks.append({“prompt”: prompt_used, “error”: result[0]}) except Exception as e: failed_tasks.append({“prompt”: prompt_used, “error”: str(e)}) print(f“批量生成完成!成功:{len(successful_results)},失败:{len(failed_tasks)}”) return successful_results, failed_tasksmax_workers控制同时工作的“工人”数量,可以根据你的电脑性能和API服务器的承受能力调整。max_retries给了失败任务“再来一次”的机会,提高了整体成功率。
3.4 第四步:为图片添加元数据与水印
生成的图片如果直接保存,时间久了可能连你自己都忘了当初是用什么提示词生成的。我们可以把关键的元信息(如提示词、分类)直接写入图片文件,或者以文本水印的方式添加到图片角落。
这里演示两种方式:
方式一:将元数据写入图片的EXIF信息(无损,但某些软件可能不显示)
from PIL import Image, PngImagePlugin import json def add_metadata_to_image(image, prompt_info): """ 将提示词信息作为元数据添加到图片中。 参数: image (PIL.Image): 图片对象。 prompt_info (dict): 提示词相关信息字典。 返回: PIL.Image: 添加了元数据的图片对象(副本)。 """ # 创建图片的副本进行操作 img_copy = image.copy() # 准备要存储的元数据 meta = PngImagePlugin.PngInfo() # 将prompt_info字典转换为JSON字符串存入 meta.add_text(“prompt_data”, json.dumps(prompt_info)) # 注意:保存时需要指定pnginfo参数。这里我们先不保存,只返回带信息的对象。 # 实际保存函数会用到这个meta对象。 return img_copy, meta方式二:在图片上添加文字水印(直观,但可能影响画面)
from PIL import ImageDraw, ImageFont def add_text_watermark(image, text, position=(10, 10), font_size=20): """ 在图片上添加文字水印。 参数: image (PIL.Image): 图片对象。 text (str): 水印文字。 position (tuple): 水印左上角坐标 (x, y)。 font_size (int): 字体大小。 返回: PIL.Image: 添加了水印的图片对象。 """ img_copy = image.copy() try: # 尝试加载字体,如果失败则使用默认字体 font = ImageFont.truetype(“arial.ttf”, font_size) except IOError: font = ImageFont.load_default() draw = ImageDraw.Draw(img_copy) # 在指定位置绘制白色文字,带黑色描边更清晰 draw.text(position, text, font=font, fill=(255, 255, 255, 128)) # 半透明白色 return img_copy3.5 第五步:按类别保存图片
最后一步,把成功生成的图片,按照我们之前在CSV里定义好的category和style字段,自动存放到对应的文件夹里,让素材库井井有条。
import os from datetime import datetime def save_images_with_organization(successful_results, base_output_dir=“./generated_pixel_art”): """ 将成功生成的图片按类别保存到文件夹,并添加元数据。 参数: successful_results (list): 由batch_generate_images返回的成功结果列表。 base_output_dir (str): 输出图片的根目录。 """ os.makedirs(base_output_dir, exist_ok=True) for img, prompt_info in successful_results: # 从提示词信息中获取分类 category = prompt_info.get(‘category’, ‘uncategorized’) style = prompt_info.get(‘style’, ‘general’) prompt_text = prompt_info.get(‘prompt’, ‘’) # 创建分类文件夹,例如:./generated_pixel_art/character/combat/ category_dir = os.path.join(base_output_dir, category, style) os.makedirs(category_dir, exist_ok=True) # 生成一个包含时间戳和提示词前几个词的唯一文件名 # 用提示词前20个字符(去除特殊字符)作为文件名的一部分 safe_prompt_part = “”.join([c for c in prompt_text[:20] if c.isalnum() or c in (‘ ‘, ‘-’, ‘_’)]).rstrip() timestamp = datetime.now().strftime(“%Y%m%d_%H%M%S”) filename = f“{timestamp}_{safe_prompt_part}.png” filepath = os.path.join(category_dir, filename) # 准备元数据并保存图片 img_with_meta, meta = add_metadata_to_image(img, prompt_info) # 保存为PNG,并嵌入元数据 img_with_meta.save(filepath, “PNG”, pnginfo=meta) # 可选:同时保存一个添加了简单文本水印的版本到另一个文件夹 # watermark_dir = os.path.join(base_output_dir, “with_watermark”, category, style) # os.makedirs(watermark_dir, exist_ok=True) # img_watermarked = add_text_watermark(img, f“Prompt: {prompt_text[:50]}...”) # img_watermarked.save(os.path.join(watermark_dir, filename)) print(f“所有图片已保存至目录: {base_output_dir}”)4. 把它们组合起来:完整的脚本示例
现在,我们把上面所有的函数组装成一个可以直接运行的完整脚本。你只需要修改开头的几个配置变量即可。
#!/usr/bin/env python3 “”” Qwen-Image-2512-Pixel-Art-LoRA 批量图片生成脚本。 功能:从CSV读取提示词,并发调用API生成图片,按类别保存。 “”” import pandas as pd import requests import base64 import json import os import time from io import BytesIO from concurrent.futures import ThreadPoolExecutor, as_completed from PIL import Image, PngImagePlugin from tqdm import tqdm from datetime import datetime # ==================== 配置区域 ==================== API_URL = “http://your_model_server:port/v1/images/generations” # 替换为你的API地址 API_KEY = “your_api_key_here” # 如果需要,替换为你的API密钥 MODEL_NAME = “Qwen-Image-2512-Pixel-Art-LoRA” PROMPTS_CSV_PATH = “prompts.csv” # 你的提示词CSV文件路径 OUTPUT_BASE_DIR = “./my_pixel_art_library” # 输出图片的根目录 MAX_WORKERS = 4 # 并发线程数,建议2-8之间 MAX_RETRIES = 2 # 单任务失败重试次数 # ==================== 配置结束 ==================== # 这里插入之前定义的所有函数:load_prompts_from_csv, generate_single_image, # batch_generate_images, add_metadata_to_image, save_images_with_organization # (为了节省篇幅,函数体省略,请将前面章节的函数代码复制粘贴到这里) def main(): “””主函数,执行批量生成流程。””” print(“=== Qwen像素艺术素材批量生成脚本启动 ===”) # 1. 加载提示词 print(f“1. 正在从 {PROMPTS_CSV_PATH} 加载提示词...”) prompts_list = load_prompts_from_csv(PROMPTS_CSV_PATH) if not prompts_list: print(“提示词列表为空,程序退出。”) return # 2. 批量生成图片 print(“2. 开始批量生成图片...”) successful_results, failed_tasks = batch_generate_images( api_url=API_URL, api_key=API_KEY, prompts_list=prompts_list, max_workers=MAX_WORKERS, max_retries=MAX_RETRIES ) # 3. 保存图片 if successful_results: print(“3. 正在保存生成的图片...”) save_images_with_organization(successful_results, OUTPUT_BASE_DIR) else: print(“3. 没有成功生成的图片可保存。”) # 4. 报告失败任务(如果有) if failed_tasks: print(“\n=== 以下任务生成失败 ===") for task in failed_tasks[:5]: # 只打印前5个失败任务 print(f“提示词: {task[‘prompt’].get(‘prompt’)[:50]}...”) print(f“错误: {task[‘error’]}\n”) if len(failed_tasks) > 5: print(f“... 以及另外 {len(failed_tasks)-5} 个失败任务。”) # 可选:将失败任务保存到文件,方便后续重试 fail_log_path = os.path.join(OUTPUT_BASE_DIR, “failed_tasks.json”) with open(fail_log_path, ‘w’, encoding=‘utf-8’) as f: json.dump(failed_tasks, f, ensure_ascii=False, indent=2) print(f“完整失败日志已保存至: {fail_log_path}”) print(“\n=== 脚本执行完毕 ===") if __name__ == “__main__”: main()把这个脚本保存为batch_generate_pixel_art.py,确保你的prompts.csv文件在同一目录下(或修改路径),然后根据你的模型部署情况修改API_URL和API_KEY。最后,在命令行运行:
python batch_generate_pixel_art.py接下来,泡杯咖啡,看着进度条慢慢走完,一个分类清晰、自带元数据的海量像素素材库就自动建好了。
5. 总结
整个脚本写下来,你会发现核心逻辑并不复杂,就是“读取任务 -> 并发执行 -> 处理结果 -> 保存归档”这样一个清晰的管道。最大的价值在于,它把你从重复、枯燥的手动操作中解放了出来。
实际使用中,你可能还会根据需求做一些调整,比如调整并发数避免把服务器压垮,或者修改图片保存的命名规则和目录结构。这个脚本提供了一个坚实的起点,你可以基于它扩展更多功能,比如生成后自动进行简单的图像质量检查,或者与项目管理工具联动。
用脚本做批量处理,一开始可能会花点时间设置,但一旦跑通,它带来的效率提升是巨大的。特别是对于需要持续产出大量素材的项目,这种自动化能力会成为你的核心竞争力。希望这个教程能帮你打开思路,不仅仅是生成像素图,很多重复性的AI创作任务,都可以用类似的思路来实现自动化。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。
