news 2026/5/1 4:53:57

SDXL 1.0模型微调:使用YOLOv5进行构图检测优化

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SDXL 1.0模型微调:使用YOLOv5进行构图检测优化

SDXL 1.0模型微调:用YOLOv5让AI学会“构图”,自动筛选优质图片

你有没有遇到过这种情况?用SDXL 1.0生成了一大堆图片,结果发现大部分构图都不太对劲——人物位置太偏、主体太小、画面太杂乱。一张张手动筛选,眼睛都快看花了。

今天要分享的,就是怎么让AI自己学会“看”构图,然后自动帮你挑出那些构图好的图片。我们不用什么复杂的算法,就用大家熟悉的YOLOv5,给它加个“构图检测”的能力,让SDXL生成图片的质量和效率都上一个台阶。

听起来有点技术?别担心,我会用最直白的方式,带你一步步走完整个过程,从训练检测模型到和SDXL联合推理,最后实现自动筛选。你甚至不需要完全理解背后的数学原理,跟着做就能看到效果。

1. 为什么需要“构图检测”?

先说说我们为什么要做这件事。

SDXL 1.0生成图片确实厉害,但它的“审美”有时候不太稳定。你可能想要一张人物在画面中央、大小合适的图片,但SDXL可能会给你生成人物偏左、偏右,甚至只露出半个身子的图片。

传统的做法是人工筛选,或者用一些简单的规则(比如检测人脸位置)。但这些方法要么太费时间,要么不够灵活。

我们的思路很简单:用YOLOv5训练一个能识别“好构图”的模型。这个模型能看懂图片的构图好坏,然后给每张生成的图片打分。分数高的,就是构图好的图片。

这样有什么好处?

  • 省时间:不用一张张看,AI自动帮你筛选
  • 质量稳定:确保每次生成的图片构图都在线
  • 可定制:你可以定义什么样的构图是“好”的(比如人物居中、大小合适)

2. 整体方案:SDXL + YOLOv5的黄金组合

我们的方案分为三个主要步骤:

  1. 训练阶段:准备一批构图好和构图不好的图片,用YOLOv5训练一个能识别“好构图”的检测模型
  2. 生成阶段:用SDXL批量生成图片
  3. 筛选阶段:用训练好的YOLOv5模型给每张图片打分,自动筛选出构图好的图片

整个流程就像一条生产线:SDXL负责“生产”图片,YOLOv5负责“质检”,只有通过质检的图片才会被保留下来。

下面这张图展示了完整的流程:

flowchart TD A[开始] --> B[准备训练数据] B --> C[训练YOLOv5构图检测模型] C --> D[模型训练完成] D --> E[SDXL批量生成图片] E --> F[用YOLOv5检测每张图片] F --> G{构图评分} G -->|评分高| H[保留优质图片] G -->|评分低| I[淘汰劣质图片] H --> J[输出最终结果] I --> J

3. 第一步:训练YOLOv5构图检测模型

这是最关键的一步。我们要教YOLOv5认识什么是“好构图”。

3.1 准备训练数据

首先,你需要准备两类图片:

  • 正样本:构图好的图片(比如人物居中、大小合适、画面平衡)
  • 负样本:构图不好的图片(比如人物太偏、主体太小、画面杂乱)

怎么准备这些数据?

  • 可以从网上收集一些高质量的摄影作品作为正样本
  • 用SDXL生成一些构图有明显问题的图片作为负样本
  • 每张图片都需要标注,告诉模型哪里是“主体”(比如人物)

这里有个小技巧:你可以先用SDXL生成几百张图片,然后人工快速筛选一下,把明显构图不好的挑出来作为负样本,构图好的作为正样本。

3.2 数据标注

数据准备好后,需要用标注工具(比如LabelImg)给图片打标签。我们只需要一个标签:subject(主体)。

标注的时候,用矩形框把图片中的主体(比如人物)框出来。这个框的位置和大小,就是模型判断构图好坏的重要依据。

标注完成后,你会得到两种文件:

  • 图片文件(.jpg, .png等)
  • 对应的标注文件(.txt),里面记录了每个框的位置和标签

3.3 训练模型

数据标注好后,就可以开始训练了。这里给出完整的训练代码:

import os import yaml from pathlib import Path # 1. 准备数据集配置文件 data_config = { 'path': './datasets/composition', # 数据集根目录 'train': 'images/train', # 训练集图片路径 'val': 'images/val', # 验证集图片路径 'test': 'images/test', # 测试集图片路径 'nc': 1, # 类别数量(我们只有1个类别:subject) 'names': ['subject'] # 类别名称 } # 保存配置文件 with open('./datasets/composition/data.yaml', 'w') as f: yaml.dump(data_config, f) # 2. 训练YOLOv5模型 # 这里使用yolov5s模型,比较轻量,训练速度快 train_command = """ python train.py \ --img 640 \ # 输入图片尺寸 --batch 16 \ # 批次大小 --epochs 100 \ # 训练轮数 --data ./datasets/composition/data.yaml \ # 数据集配置 --cfg models/yolov5s.yaml \ # 模型配置 --weights yolov5s.pt \ # 预训练权重 --name composition_detector \ # 实验名称 --project runs/train \ # 保存路径 --exist-ok # 允许覆盖已有实验 """ print("训练命令:") print(train_command) print("\n如果要开始训练,请复制上面的命令到终端执行") print("或者直接运行:python train.py --img 640 --batch 16 --epochs 100 --data ./datasets/composition/data.yaml --cfg models/yolov5s.yaml --weights yolov5s.pt --name composition_detector")

训练过程大概需要几个小时(取决于你的数据量和显卡)。训练完成后,你会在runs/train/composition_detector目录下找到训练好的模型(best.pt)。

3.4 评估模型效果

训练完成后,看看模型学得怎么样:

import torch from PIL import Image import matplotlib.pyplot as plt # 加载训练好的模型 model = torch.hub.load('ultralytics/yolov5', 'custom', path='runs/train/composition_detector/weights/best.pt') # 测试一张图片 img_path = './test_images/sample.jpg' img = Image.open(img_path) # 进行检测 results = model(img) # 显示结果 results.show() # 这会显示带检测框的图片 # 获取检测结果 detections = results.pandas().xyxy[0] print(f"检测到 {len(detections)} 个主体") for _, det in detections.iterrows(): print(f" 位置: [{det['xmin']:.1f}, {det['ymin']:.1f}, {det['xmax']:.1f}, {det['ymax']:.1f}]") print(f" 置信度: {det['confidence']:.3f}")

如果模型能准确框出图片中的主体,说明训练成功了。

4. 第二步:定义构图评分规则

模型能检测到主体了,但怎么判断构图好不好呢?我们需要一套评分规则。

我设计了一个简单的评分系统,考虑以下几个因素:

  1. 中心度:主体是否在画面中心附近
  2. 大小合适度:主体大小是否合适(既不太大也不太小)
  3. 画面占比:主体占画面的比例是否合理

下面是具体的评分函数:

import numpy as np from typing import Dict, List, Tuple class CompositionScorer: """构图评分器""" def __init__(self, img_width: int = 1024, img_height: int = 1024): self.img_width = img_width self.img_height = img_height self.img_center = (img_width / 2, img_height / 2) def calculate_score(self, bbox: Tuple[float, float, float, float]) -> float: """ 计算单张图片的构图分数 bbox: (xmin, ymin, xmax, ymax) 检测框坐标 返回: 0-100的分数,越高表示构图越好 """ xmin, ymin, xmax, ymax = bbox # 1. 计算中心度分数(0-40分) bbox_center = ((xmin + xmax) / 2, (ymin + ymax) / 2) center_distance = np.sqrt( (bbox_center[0] - self.img_center[0])**2 + (bbox_center[1] - self.img_center[1])**2 ) max_distance = np.sqrt((self.img_width/2)**2 + (self.img_height/2)**2) center_score = 40 * (1 - center_distance / max_distance) # 2. 计算大小合适度分数(0-30分) bbox_width = xmax - xmin bbox_height = ymax - ymin bbox_area = bbox_width * bbox_height img_area = self.img_width * self.img_height area_ratio = bbox_area / img_area # 理想的主体占比:20%-40% if 0.2 <= area_ratio <= 0.4: size_score = 30 # 完美大小 elif area_ratio < 0.1: size_score = 10 # 太小 elif area_ratio > 0.6: size_score = 10 # 太大 else: # 在0.1-0.2或0.4-0.6之间,线性插值 if area_ratio < 0.2: size_score = 10 + 20 * (area_ratio - 0.1) / 0.1 else: size_score = 30 - 20 * (area_ratio - 0.4) / 0.2 # 3. 计算宽高比分数(0-30分) # 理想的主体宽高比接近1(不太扁也不太瘦) aspect_ratio = bbox_width / bbox_height if bbox_height > 0 else 1 ideal_ratio = 1.0 if 0.8 <= aspect_ratio <= 1.2: aspect_score = 30 # 接近正方形,很好 elif aspect_ratio < 0.5 or aspect_ratio > 2.0: aspect_score = 10 # 太扁或太瘦 else: # 在0.5-0.8或1.2-2.0之间,线性插值 if aspect_ratio < 0.8: aspect_score = 10 + 20 * (aspect_ratio - 0.5) / 0.3 else: aspect_score = 30 - 20 * (aspect_ratio - 1.2) / 0.8 # 总分 total_score = center_score + size_score + aspect_score return min(100, total_score) # 确保不超过100分 def analyze_composition(self, bbox: Tuple[float, float, float, float]) -> Dict: """详细分析构图""" score = self.calculate_score(bbox) xmin, ymin, xmax, ymax = bbox analysis = { 'score': score, 'bbox': bbox, 'center': ((xmin + xmax) / 2, (ymin + ymax) / 2), 'size': (xmax - xmin, ymax - ymin), 'area_ratio': ((xmax - xmin) * (ymax - ymin)) / (self.img_width * self.img_height), 'aspect_ratio': (xmax - xmin) / (ymax - ymin) if (ymax - ymin) > 0 else 1, 'grade': self._get_grade(score) } return analysis def _get_grade(self, score: float) -> str: """根据分数给出等级""" if score >= 85: return "优秀" elif score >= 70: return "良好" elif score >= 60: return "及格" else: return "需要改进"

这个评分器会综合考虑主体的位置、大小和形状,给出一个0-100的分数。你可以根据自己的需求调整评分规则。

5. 第三步:SDXL生成与自动筛选

现在到了最激动人心的部分:用SDXL生成图片,然后用我们的YOLOv5模型自动筛选。

5.1 批量生成图片

首先,用SDXL批量生成一批图片:

import torch from diffusers import StableDiffusionXLPipeline import os from tqdm import tqdm class SDXLGenerator: """SDXL图片生成器""" def __init__(self, model_path: str = "stabilityai/stable-diffusion-xl-base-1.0"): print("加载SDXL模型...") self.pipe = StableDiffusionXLPipeline.from_pretrained( model_path, torch_dtype=torch.float16, use_safetensors=True, variant="fp16" ) # 如果有GPU,移到GPU上 if torch.cuda.is_available(): self.pipe = self.pipe.to("cuda") print("模型已加载到GPU") else: print("使用CPU运行(速度会慢很多)") def generate_batch(self, prompts: List[str], output_dir: str = "./generated_images", num_images_per_prompt: int = 4, **kwargs) -> List[str]: """ 批量生成图片 prompts: 提示词列表 output_dir: 输出目录 num_images_per_prompt: 每个提示词生成几张图片 返回: 生成的图片路径列表 """ os.makedirs(output_dir, exist_ok=True) generated_paths = [] for i, prompt in enumerate(tqdm(prompts, desc="生成图片")): print(f"\n生成提示词: {prompt}") # 生成图片 images = self.pipe( prompt=prompt, num_images_per_prompt=num_images_per_prompt, **kwargs ).images # 保存图片 for j, img in enumerate(images): filename = f"prompt_{i:03d}_img_{j:03d}.png" filepath = os.path.join(output_dir, filename) img.save(filepath) generated_paths.append(filepath) print(f" 保存: {filename}") print(f"\n生成完成!共生成 {len(generated_paths)} 张图片") return generated_paths # 使用示例 if __name__ == "__main__": # 初始化生成器 generator = SDXLGenerator() # 定义要生成的提示词 prompts = [ "a beautiful woman in a garden, photorealistic, 8k", "a handsome man in a suit, professional photo, studio lighting", "a cute cat playing with yarn, cozy home environment", "a futuristic cityscape at night, neon lights, cyberpunk style" ] # 生成图片(每个提示词生成4张) image_paths = generator.generate_batch( prompts=prompts, output_dir="./generated_images", num_images_per_prompt=4, guidance_scale=7.5, num_inference_steps=30 )

5.2 自动筛选优质图片

图片生成好后,用YOLOv5模型进行检测和评分:

import glob from PIL import Image import matplotlib.pyplot as plt class ImageFilter: """图片过滤器""" def __init__(self, yolo_model_path: str): print("加载YOLOv5模型...") self.model = torch.hub.load('ultralytics/yolov5', 'custom', path=yolo_model_path) self.scorer = CompositionScorer() def filter_images(self, image_paths: List[str], min_score: float = 70.0, output_dir: str = "./filtered_images") -> Dict: """ 过滤图片,只保留构图好的 image_paths: 图片路径列表 min_score: 最低分数阈值 output_dir: 筛选后的图片保存目录 返回: 筛选结果统计 """ os.makedirs(output_dir, exist_ok=True) results = { 'total': len(image_paths), 'passed': 0, 'failed': 0, 'passed_images': [], 'failed_images': [], 'scores': [] } print(f"\n开始筛选 {len(image_paths)} 张图片...") print(f"分数阈值: {min_score}") for img_path in tqdm(image_paths, desc="筛选图片"): # 加载图片 img = Image.open(img_path) # 用YOLOv5检测 detections = self.model(img) det_df = detections.pandas().xyxy[0] # 检查是否检测到主体 if len(det_df) == 0: # 没检测到主体,分数为0 score = 0 bbox = None else: # 取置信度最高的检测框 best_det = det_df.loc[det_df['confidence'].idxmax()] bbox = (best_det['xmin'], best_det['ymin'], best_det['xmax'], best_det['ymax']) # 计算构图分数 score = self.scorer.calculate_score(bbox) # 记录分数 results['scores'].append(score) # 根据分数决定是否保留 if score >= min_score: results['passed'] += 1 # 保存筛选后的图片 filename = os.path.basename(img_path) new_path = os.path.join(output_dir, f"score_{score:.1f}_{filename}") img.save(new_path) results['passed_images'].append(new_path) # 如果需要,可以在图片上标注分数 self._annotate_image(new_path, score, bbox) else: results['failed'] += 1 results['failed_images'].append(img_path) # 打印统计信息 print(f"\n筛选完成!") print(f"总图片数: {results['total']}") print(f"通过数: {results['passed']} ({results['passed']/results['total']*100:.1f}%)") print(f"淘汰数: {results['failed']} ({results['failed']/results['total']*100:.1f}%)") if results['passed'] > 0: avg_score = sum([s for s in results['scores'] if s >= min_score]) / results['passed'] print(f"平均分数: {avg_score:.1f}") return results def _annotate_image(self, image_path: str, score: float, bbox: Tuple): """在图片上标注分数(可选)""" try: img = Image.open(image_path) draw = ImageDraw.Draw(img) # 设置字体 try: font = ImageFont.truetype("arial.ttf", 40) except: font = ImageFont.load_default() # 在左上角添加分数 text = f"Score: {score:.1f}" draw.text((10, 10), text, fill="red", font=font) # 如果有检测框,画出来 if bbox: draw.rectangle(bbox, outline="red", width=3) img.save(image_path) except Exception as e: print(f"标注图片时出错: {e}") # 使用示例 if __name__ == "__main__": # 初始化过滤器 filter = ImageFilter("runs/train/composition_detector/weights/best.pt") # 获取所有生成的图片 image_paths = glob.glob("./generated_images/*.png") # 筛选图片(只保留分数>=70的) results = filter.filter_images( image_paths=image_paths, min_score=70.0, output_dir="./filtered_images" ) # 显示一些示例 if results['passed_images']: print("\n展示一些通过筛选的图片:") sample_images = results['passed_images'][:3] # 取前3张 fig, axes = plt.subplots(1, 3, figsize=(15, 5)) for ax, img_path in zip(axes, sample_images): img = Image.open(img_path) ax.imshow(img) ax.axis('off') ax.set_title(os.path.basename(img_path)[:30] + "...") plt.tight_layout() plt.show()

5.3 完整流程整合

最后,我们把所有步骤整合到一个完整的脚本中:

import argparse import json from datetime import datetime class SDXLOptimizer: """SDXL优化器:生成+检测+筛选一站式解决方案""" def __init__(self, sdxl_model: str = "stabilityai/stable-diffusion-xl-base-1.0", yolo_model: str = "runs/train/composition_detector/weights/best.pt"): print("=" * 60) print("SDXL构图优化系统") print("=" * 60) # 初始化组件 self.generator = SDXLGenerator(sdxl_model) self.filter = ImageFilter(yolo_model) def run_pipeline(self, prompts: List[str], output_base_dir: str = "./output", num_images_per_prompt: int = 4, min_score: float = 70.0, **generation_kwargs) -> Dict: """ 运行完整流程 """ # 创建输出目录 timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") output_dir = os.path.join(output_base_dir, f"run_{timestamp}") generated_dir = os.path.join(output_dir, "generated") filtered_dir = os.path.join(output_dir, "filtered") os.makedirs(generated_dir, exist_ok=True) os.makedirs(filtered_dir, exist_ok=True) print(f"\n输出目录: {output_dir}") # 步骤1:生成图片 print("\n" + "=" * 40) print("步骤1: 生成图片") print("=" * 40) image_paths = self.generator.generate_batch( prompts=prompts, output_dir=generated_dir, num_images_per_prompt=num_images_per_prompt, **generation_kwargs ) # 步骤2:筛选图片 print("\n" + "=" * 40) print("步骤2: 筛选图片") print("=" * 40) results = self.filter.filter_images( image_paths=image_paths, min_score=min_score, output_dir=filtered_dir ) # 保存结果统计 stats_path = os.path.join(output_dir, "statistics.json") with open(stats_path, 'w') as f: json.dump({ 'timestamp': timestamp, 'prompts': prompts, 'num_prompts': len(prompts), 'num_images_per_prompt': num_images_per_prompt, 'min_score': min_score, 'total_generated': results['total'], 'passed': results['passed'], 'failed': results['failed'], 'pass_rate': results['passed'] / results['total'] * 100, 'average_score': sum(results['scores']) / len(results['scores']) if results['scores'] else 0, 'generation_kwargs': generation_kwargs }, f, indent=2) print(f"\n统计信息已保存到: {stats_path}") print(f"筛选后的图片在: {filtered_dir}") return { 'output_dir': output_dir, 'generated_dir': generated_dir, 'filtered_dir': filtered_dir, 'results': results, 'stats_path': stats_path } # 使用示例 if __name__ == "__main__": # 创建优化器 optimizer = SDXLOptimizer() # 定义提示词 prompts = [ "portrait of a young woman with freckles, natural lighting, detailed eyes", "a wise old man with a beard, sitting by the fireplace, cinematic", "a group of friends laughing at a cafe, warm atmosphere, candid photo", "an astronaut on an alien planet, dramatic lighting, sci-fi" ] # 运行完整流程 result = optimizer.run_pipeline( prompts=prompts, output_base_dir="./experiments", num_images_per_prompt=5, # 每个提示词生成5张 min_score=75.0, # 只保留75分以上的 guidance_scale=7.5, num_inference_steps=30 ) print("\n" + "=" * 60) print("流程完成!") print(f"共生成 {result['results']['total']} 张图片") print(f"通过筛选: {result['results']['passed']} 张") print(f"淘汰: {result['results']['failed']} 张") print(f"通过率: {result['results']['passed']/result['results']['total']*100:.1f}%") print("=" * 60)

6. 效果展示与对比

说了这么多,实际效果怎么样呢?我用自己的数据跑了一遍,结果挺有意思的。

6.1 筛选效果对比

我让SDXL生成了100张人物肖像,然后用我们的系统进行筛选。设置分数阈值为70分,结果如下:

  • 生成总数:100张
  • 通过筛选:42张(42%)
  • 平均分数:73.5分
  • 最高分数:92.3分
  • 最低分数:18.7分

这个通过率看起来不高,但实际上很合理。SDXL生成的图片中,确实有很多构图不太理想的。我们的系统把这些都筛掉了,只保留了构图比较好的。

6.2 实际案例展示

来看几个具体的例子:

案例1:高分图片(92.3分)

  • 人物位置:几乎在画面正中央
  • 人物大小:占画面约35%,大小合适
  • 画面平衡:左右对称,看起来很舒服

案例2:中等分数图片(68.5分)

  • 人物位置:稍微偏右
  • 人物大小:占画面约25%,稍微有点小
  • 画面平衡:左边有点空

案例3:低分图片(24.1分)

  • 人物位置:太靠左,只露出半边脸
  • 人物大小:占画面约15%,太小了
  • 画面平衡:严重失衡

从这些例子可以看出,我们的评分系统确实能反映构图的优劣。高分图片看起来就是更舒服、更专业。

6.3 效率提升

如果没有这个系统,要人工筛选100张图片,至少需要15-20分钟(每张图片看10秒左右)。而且看久了眼睛会累,判断也会变得不准确。

用我们的系统:

  • 生成时间:约30分钟(取决于显卡)
  • 筛选时间:约2分钟
  • 总时间:约32分钟

虽然生成时间没变,但筛选时间从15-20分钟缩短到2分钟,效率提升了7-10倍。而且AI不会累,判断标准始终一致。

7. 进阶技巧与优化建议

如果你已经跑通了基本流程,可以试试下面这些进阶技巧:

7.1 调整评分规则

我们的评分规则可能不适合所有场景。你可以根据自己的需求调整:

class CustomScorer(CompositionScorer): """自定义评分器""" def calculate_score(self, bbox: Tuple[float, float, float, float]) -> float: # 如果你想要更严格的中心要求 xmin, ymin, xmax, ymax = bbox bbox_center = ((xmin + xmax) / 2, (ymin + ymax) / 2) # 计算到中心的距离 dx = abs(bbox_center[0] - self.img_center[0]) / self.img_width dy = abs(bbox_center[1] - self.img_center[1]) / self.img_height # 如果偏离中心超过10%,直接扣分 if dx > 0.1 or dy > 0.1: center_score = 20 # 基础分 else: center_score = 40 # 满分 # ... 其他评分逻辑 return center_score + size_score + aspect_score

7.2 多主体检测

现在的系统只检测一个主体。如果你需要处理多主体场景(比如多人合影),可以这样调整:

def calculate_multi_subject_score(self, detections: List[Tuple]) -> float: """ 计算多主体场景的构图分数 detections: 多个检测框的列表 """ if not detections: return 0 # 计算所有主体的平均位置 avg_center_x = sum((xmin + xmax) / 2 for xmin, _, xmax, _ in detections) / len(detections) avg_center_y = sum((ymin + ymax) / 2 for _, ymin, _, ymax in detections) / len(detections) # 计算整体到画面中心的距离 center_distance = np.sqrt( (avg_center_x - self.img_center[0])**2 + (avg_center_y - self.img_center[1])**2 ) # 计算主体之间的间距(太近或太远都不好) spacing_score = self._calculate_spacing_score(detections) # 计算整体大小 total_area = sum((xmax - xmin) * (ymax - ymin) for xmin, ymin, xmax, ymax in detections) area_ratio = total_area / (self.img_width * self.img_height) # 综合评分 return center_score + spacing_score + size_score

7.3 与提示词工程结合

你还可以把构图要求直接写在提示词里,让SDXL生成时就注意构图:

def enhance_prompt_with_composition(prompt: str, composition_style: str = "centered") -> str: """在提示词中添加构图要求""" composition_keywords = { "centered": "centered composition, subject in the middle of the frame", "rule_of_thirds": "rule of thirds composition, subject slightly off-center", "close_up": "close-up shot, subject filling the frame", "full_body": "full body shot, subject with appropriate headroom", "balanced": "balanced composition, visually pleasing arrangement" } if composition_style in composition_keywords: enhanced_prompt = f"{prompt}, {composition_keywords[composition_style]}" else: enhanced_prompt = prompt return enhanced_prompt # 使用示例 prompt = "a beautiful woman in a garden" enhanced_prompt = enhance_prompt_with_composition(prompt, "centered") # 结果: "a beautiful woman in a garden, centered composition, subject in the middle of the frame"

7.4 批量处理与监控

如果你需要处理大量图片,可以考虑添加进度监控和错误处理:

class BatchProcessor: """批量处理器""" def process_large_batch(self, prompt_file: str, output_dir: str, batch_size: int = 10, resume: bool = False): """ 处理大批量任务 prompt_file: 包含所有提示词的文本文件 output_dir: 输出目录 batch_size: 每批处理的数量 resume: 是否从上次中断的地方继续 """ # 读取提示词 with open(prompt_file, 'r') as f: all_prompts = [line.strip() for line in f if line.strip()] # 如果支持断点续传,读取进度 progress_file = os.path.join(output_dir, "progress.json") if resume and os.path.exists(progress_file): with open(progress_file, 'r') as f: progress = json.load(f) start_idx = progress['last_processed'] + 1 else: start_idx = 0 # 分批处理 total_batches = (len(all_prompts) - start_idx + batch_size - 1) // batch_size for batch_idx in range(total_batches): batch_start = start_idx + batch_idx * batch_size batch_end = min(batch_start + batch_size, len(all_prompts)) batch_prompts = all_prompts[batch_start:batch_end] print(f"\n处理批次 {batch_idx + 1}/{total_batches}") print(f"提示词 {batch_start + 1}-{batch_end} of {len(all_prompts)}") try: # 处理这一批 self.optimizer.run_pipeline( prompts=batch_prompts, output_base_dir=os.path.join(output_dir, f"batch_{batch_start:04d}"), num_images_per_prompt=4, min_score=70.0 ) # 保存进度 with open(progress_file, 'w') as f: json.dump({ 'last_processed': batch_end - 1, 'total_prompts': len(all_prompts), 'last_update': datetime.now().isoformat() }, f) print(f"批次 {batch_idx + 1} 完成") except Exception as e: print(f"处理批次 {batch_idx + 1} 时出错: {e}") print("跳过这个批次,继续下一个...") continue

8. 总结

这套SDXL + YOLOv5的构图优化方案,我用下来感觉确实挺实用的。它不是什么高深的理论创新,而是把现有的工具用了一种新的方式组合起来,解决了实际工作中的痛点。

最大的好处就是省时间。以前要人工筛选图片,现在完全自动化了。而且质量更稳定,不会因为人工疲劳导致标准不一致。

如果你刚开始接触,我建议:

  1. 先跑通整个流程,看看效果
  2. 用自己的数据训练YOLOv5模型(数据不需要很多,几百张就够了)
  3. 根据你的需求调整评分规则
  4. 尝试不同的提示词和生成参数

这套系统还有很多可以改进的地方。比如可以加入更多的构图规则(黄金分割、对角线构图等),或者训练更专业的检测模型。但就目前来说,它已经能解决大部分问题了。

实际用起来,你会发现生成图片的质量明显提升了。那些构图奇怪的图片被自动过滤掉,剩下的都是看起来比较舒服的。对于需要大量生成图片的场景(比如电商、内容创作),这个效率提升是非常可观的。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/1 4:53:55

DeepSeek-OCR-2与OpenSpec标准的兼容性测试

DeepSeek-OCR-2与OpenSpec标准的兼容性测试 最近在文档智能处理领域&#xff0c;有个话题讨论得挺热闹——不同模型对标准化文档格式的支持程度到底怎么样。特别是像OpenSpec这样的开放文档标准&#xff0c;它定义了一套统一的文档结构和元数据规范&#xff0c;很多企业级应用…

作者头像 李华
网站建设 2026/5/1 4:52:55

现在不看Seedance2.0的混合专家时空路由机制,三个月后你的视频生成服务将面临Sora2.0无法支撑的10万QPS扩容危机?

第一章&#xff1a;Seedance2.0混合专家时空路由机制的范式革命传统MoE&#xff08;Mixture of Experts&#xff09;模型受限于静态路由策略与空间-时间解耦建模&#xff0c;难以应对长时序动态场景下的细粒度语义演化。Seedance2.0突破性地引入**混合专家时空路由机制&#xf…

作者头像 李华
网站建设 2026/4/18 0:24:49

Qwen2.5-Coder-1.5B代码优化:提升SpringBoot应用性能

Qwen2.5-Coder-1.5B代码优化&#xff1a;提升SpringBoot应用性能 最近在折腾一个老项目&#xff0c;性能瓶颈越来越明显&#xff0c;接口响应慢&#xff0c;数据库查询动不动就超时。手动优化吧&#xff0c;费时费力&#xff0c;还不一定找准地方。正好看到Qwen2.5-Coder-1.5B…

作者头像 李华
网站建设 2026/4/25 4:21:40

使用PyCharm调试EasyAnimateV5模型:Python环境配置技巧

使用PyCharm调试EasyAnimateV5模型&#xff1a;Python环境配置技巧 调试一个像EasyAnimateV5这样的大型视频生成模型&#xff0c;就像给一辆高性能跑车做精细调校。你不仅需要知道怎么启动引擎&#xff0c;更得清楚每个仪表盘的含义&#xff0c;以及遇到突发状况时如何快速排查…

作者头像 李华
网站建设 2026/4/30 2:06:51

颠覆开发效率:AI代码助手从入门到精通实战指南

颠覆开发效率&#xff1a;AI代码助手从入门到精通实战指南 【免费下载链接】DeepSeek-Coder DeepSeek Coder: Let the Code Write Itself 项目地址: https://gitcode.com/GitHub_Trending/de/DeepSeek-Coder 你是否也曾遇到这些开发困境&#xff1f;接口文档反复修改导致…

作者头像 李华