优化了poster_notes中的配图方法,增加了并行处理,在不同强度的处理中做了适当取舍
This commit is contained in:
parent
98b989f02a
commit
45579c7b87
@ -1,13 +1,13 @@
|
||||
{
|
||||
"date": "4月29日,4月30日, 4月28日, 5月1日",
|
||||
"num": 15,
|
||||
"variants": 15,
|
||||
"date": "5月29日,5月30日, 5月28日, 5月31日",
|
||||
"num": 7,
|
||||
"variants": 5,
|
||||
"topic_temperature": 0.2,
|
||||
"topic_top_p": 0.3,
|
||||
"topic_presence_penalty": 1.5,
|
||||
"content_temperature": 0.3,
|
||||
"content_top_p": 0.4,
|
||||
"content_presence_penalty": 1.5,
|
||||
"content_top_p": 0.5,
|
||||
"content_presence_penalty": 1.2,
|
||||
"model": "qwen3-30B-A3B",
|
||||
"api_url": "http://localhost:8000/v1/",
|
||||
"api_key": "EMPTY",
|
||||
@ -42,19 +42,23 @@
|
||||
{
|
||||
"type": "Object",
|
||||
"file_path": [
|
||||
"./resource/Object/长鹿旅游休博园.txt"
|
||||
"./resource/Object/美的鹭湖鹭栖台酒店.txt",
|
||||
"./resource/Object/乌镇民宿.txt"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "Description",
|
||||
"file_path": [
|
||||
"./resource/Object/长鹿旅游休博园.txt"
|
||||
"./resource/Object/美的鹭湖鹭栖台酒店.txt",
|
||||
"./resource/Object/乌镇民宿.txt"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "Product",
|
||||
"file_path": [
|
||||
]
|
||||
"./resource/Object/美的鹭湖鹭栖台酒店.txt",
|
||||
"./resource/Object/乌镇民宿.txt"
|
||||
]
|
||||
}
|
||||
],
|
||||
"output_dir": "./result",
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@ -5,7 +5,9 @@ import json
|
||||
from PIL import Image
|
||||
import traceback
|
||||
from typing import List, Tuple, Dict, Any, Optional
|
||||
|
||||
import concurrent.futures
|
||||
import numpy as np
|
||||
from PIL import ImageEnhance, ImageFilter
|
||||
from .output_handler import OutputHandler
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@ -166,25 +168,67 @@ class PosterNotesCreator:
|
||||
variation_strength: str = "medium",
|
||||
extra_effects: bool = True
|
||||
) -> List[str]:
|
||||
"""
|
||||
选择未被海报使用的图像作为额外配图,并处理为3:4比例
|
||||
|
||||
Args:
|
||||
run_id: 运行ID
|
||||
topic_index: 主题索引
|
||||
variant_index: 变体索引
|
||||
poster_metadata_path: 海报元数据路径
|
||||
source_image_dir: 源图像目录
|
||||
num_additional_images: 要选择的额外图像数量
|
||||
output_filename_template: 输出文件名模板
|
||||
variation_strength: 微调强度 - "low", "medium", "high"
|
||||
extra_effects: 是否添加额外效果
|
||||
|
||||
Returns:
|
||||
List[str]: 保存的额外配图路径列表
|
||||
"""
|
||||
"""选择未被海报使用的图像作为额外配图,并处理为3:4比例"""
|
||||
logger.info(f"开始为主题 {topic_index} 变体 {variant_index} 选择额外配图")
|
||||
|
||||
# 获取候选图像
|
||||
candidate_images = self.get_candidate_images(
|
||||
poster_metadata_path,
|
||||
source_image_dir,
|
||||
num_additional_images
|
||||
)
|
||||
|
||||
if not candidate_images:
|
||||
logger.warning("没有找到合适的候选图像")
|
||||
return []
|
||||
|
||||
# 生成唯一的随机种子
|
||||
seed_str = f"{run_id}_{topic_index}_{variant_index}"
|
||||
seed = sum(ord(c) for c in seed_str)
|
||||
logger.info(f"使用随机种子: {seed},基于: {seed_str}")
|
||||
|
||||
# 使用多进程并行处理图像
|
||||
saved_paths = []
|
||||
with concurrent.futures.ProcessPoolExecutor(max_workers=min(4, len(candidate_images))) as executor:
|
||||
# 创建任务
|
||||
future_to_image = {}
|
||||
for i, image_filename in enumerate(candidate_images):
|
||||
image_path = os.path.join(source_image_dir, image_filename)
|
||||
# 为每个图像创建单独的种子
|
||||
image_seed = seed + i
|
||||
|
||||
future = executor.submit(
|
||||
self.process_single_image,
|
||||
run_id,
|
||||
topic_index,
|
||||
variant_index,
|
||||
image_path,
|
||||
image_filename,
|
||||
i,
|
||||
source_image_dir,
|
||||
output_filename_template.format(index=i+1),
|
||||
image_seed,
|
||||
variation_strength,
|
||||
extra_effects
|
||||
)
|
||||
future_to_image[future] = (i, image_filename)
|
||||
|
||||
# 收集结果
|
||||
for future in concurrent.futures.as_completed(future_to_image):
|
||||
i, image_filename = future_to_image[future]
|
||||
try:
|
||||
saved_path = future.result()
|
||||
if saved_path:
|
||||
saved_paths.append(saved_path)
|
||||
logger.info(f"已保存额外配图 {i+1}/{len(candidate_images)}: {saved_path}")
|
||||
except Exception as e:
|
||||
logger.error(f"处理图像时出错 '{image_filename}': {e}")
|
||||
logger.error(traceback.format_exc())
|
||||
|
||||
return saved_paths
|
||||
|
||||
def get_candidate_images(self, poster_metadata_path, source_image_dir, num_images):
|
||||
"""获取候选图像列表,排除已用于海报的图像"""
|
||||
# 检查输入路径是否存在
|
||||
if not os.path.exists(poster_metadata_path):
|
||||
logger.error(f"海报元数据不存在: {poster_metadata_path}")
|
||||
@ -232,459 +276,219 @@ class PosterNotesCreator:
|
||||
logger.info(f"过滤后可用图像数量: {len(available_images)}")
|
||||
|
||||
# 如果可用图像少于请求数量,进行警告但继续处理
|
||||
if len(available_images) < num_additional_images:
|
||||
if len(available_images) < num_images:
|
||||
logger.warning(
|
||||
f"可用图像数量 ({len(available_images)}) 少于请求的配图数量 ({num_additional_images}),"
|
||||
f"可用图像数量 ({len(available_images)}) 少于请求的配图数量 ({num_images}),"
|
||||
f"将使用所有可用图像"
|
||||
)
|
||||
selected_images = available_images
|
||||
else:
|
||||
# 生成唯一的随机种子,基于run_id、topic_index和variant_index
|
||||
seed_str = f"{run_id}_{topic_index}_{variant_index}"
|
||||
seed = sum(ord(c) for c in seed_str)
|
||||
logger.info(f"使用随机种子: {seed},基于: {seed_str}")
|
||||
random.seed(seed)
|
||||
|
||||
# 随机选择额外图像
|
||||
selected_images = random.sample(available_images, num_additional_images)
|
||||
random.seed(sum(map(ord, ''.join(available_images)))) # 确保结果一致性
|
||||
selected_images = random.sample(available_images, num_images)
|
||||
random.seed() # 重置随机种子
|
||||
|
||||
return selected_images
|
||||
|
||||
def process_single_image(
|
||||
self,
|
||||
run_id,
|
||||
topic_index,
|
||||
variant_index,
|
||||
image_path,
|
||||
image_filename,
|
||||
index,
|
||||
source_dir,
|
||||
output_filename,
|
||||
seed,
|
||||
variation_strength,
|
||||
extra_effects
|
||||
):
|
||||
"""处理单张图像 - 此方法可在独立进程中运行"""
|
||||
try:
|
||||
# 加载图像
|
||||
image = Image.open(image_path)
|
||||
|
||||
# 重置随机种子,不影响其他随机操作
|
||||
random.seed()
|
||||
|
||||
logger.info(f"已选择 {len(selected_images)} 张图像作为额外配图")
|
||||
logger.info(f"微调强度: {variation_strength}, 额外效果: {'启用' if extra_effects else '禁用'}")
|
||||
|
||||
# 保存选择的额外配图
|
||||
saved_paths = []
|
||||
for i, image_filename in enumerate(selected_images):
|
||||
try:
|
||||
# 加载图像
|
||||
image_path = os.path.join(source_image_dir, image_filename)
|
||||
image = Image.open(image_path)
|
||||
|
||||
# 处理图像为3:4比例,并添加微小变化
|
||||
# 使用不同的种子确保每个图像的变化各不相同
|
||||
variation_seed = seed + i if 'seed' in locals() else i + 1
|
||||
processed_image = self.process_image_to_aspect_ratio(
|
||||
image,
|
||||
(3, 4),
|
||||
add_variation=True,
|
||||
seed=variation_seed,
|
||||
variation_strength=variation_strength,
|
||||
extra_effects=extra_effects
|
||||
)
|
||||
|
||||
# 生成输出文件名
|
||||
output_filename = output_filename_template.format(index=i+1)
|
||||
|
||||
# 创建元数据
|
||||
additional_metadata = {
|
||||
"original_image": image_filename,
|
||||
"additional_index": i + 1,
|
||||
"source_dir": source_image_dir,
|
||||
"is_additional_image": True,
|
||||
"processed": True,
|
||||
"aspect_ratio": "3:4",
|
||||
"variation_applied": True,
|
||||
"variation_strength": variation_strength,
|
||||
"extra_effects": extra_effects
|
||||
}
|
||||
|
||||
# 使用输出处理器保存图像
|
||||
saved_path = self.output_handler.handle_generated_image(
|
||||
run_id,
|
||||
topic_index,
|
||||
variant_index,
|
||||
'additional', # 图像类型为additional
|
||||
processed_image,
|
||||
output_filename,
|
||||
additional_metadata
|
||||
)
|
||||
|
||||
saved_paths.append(saved_path)
|
||||
logger.info(f"已保存额外配图 {i+1}/{len(selected_images)}: {saved_path}")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"处理图像时出错 '{image_filename}': {e}")
|
||||
|
||||
return saved_paths
|
||||
|
||||
def process_image_to_aspect_ratio(
|
||||
# 处理图像为3:4比例,并添加微小变化
|
||||
processed_image = self.optimized_process_image(
|
||||
image,
|
||||
(3, 4),
|
||||
add_variation=True,
|
||||
seed=seed,
|
||||
variation_strength=variation_strength,
|
||||
extra_effects=extra_effects
|
||||
)
|
||||
|
||||
# 创建元数据
|
||||
additional_metadata = {
|
||||
"original_image": image_filename,
|
||||
"additional_index": index + 1,
|
||||
"source_dir": source_dir,
|
||||
"is_additional_image": True,
|
||||
"processed": True,
|
||||
"aspect_ratio": "3:4",
|
||||
"variation_applied": True,
|
||||
"variation_strength": variation_strength,
|
||||
"extra_effects": extra_effects
|
||||
}
|
||||
|
||||
# 使用输出处理器保存图像
|
||||
return self.output_handler.handle_generated_image(
|
||||
run_id,
|
||||
topic_index,
|
||||
variant_index,
|
||||
'additional', # 图像类型为additional
|
||||
processed_image,
|
||||
output_filename,
|
||||
additional_metadata
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"处理图像时出错 '{image_filename}': {e}")
|
||||
logger.error(traceback.format_exc())
|
||||
return None
|
||||
|
||||
def optimized_process_image(
|
||||
self,
|
||||
image: Image.Image,
|
||||
target_ratio: Tuple[int, int],
|
||||
add_variation: bool = True,
|
||||
seed: int = None,
|
||||
variation_strength: str = "medium", # 新参数: 微调强度 - "low", "medium", "high"
|
||||
extra_effects: bool = True # 新参数: 是否添加额外效果
|
||||
variation_strength: str = "medium",
|
||||
extra_effects: bool = True
|
||||
) -> Image.Image:
|
||||
"""
|
||||
处理图像到指定的宽高比,并添加微小变化
|
||||
|
||||
Args:
|
||||
image: 原始图像
|
||||
target_ratio: 目标宽高比,如(3, 4)表示3:4的比例
|
||||
add_variation: 是否添加微小变化以避免哈希检测
|
||||
seed: 随机种子,用于确保变化的可重复性
|
||||
variation_strength: 微调强度 - "low", "medium", "high"
|
||||
extra_effects: 是否添加额外效果(噪点、微透视变换等)
|
||||
|
||||
Returns:
|
||||
Image.Image: 处理后的图像
|
||||
"""
|
||||
# 如果指定了种子,设置随机种子
|
||||
"""优化后的图像处理方法,使用更高效的算法"""
|
||||
# 设置随机种子
|
||||
if seed is not None:
|
||||
random.seed(seed)
|
||||
np.random.seed(seed)
|
||||
|
||||
# 根据微调强度设置参数范围
|
||||
# 根据微调强度设置参数
|
||||
if variation_strength == "low":
|
||||
brightness_range = (-0.03, 0.03)
|
||||
contrast_range = (-0.03, 0.03)
|
||||
saturation_range = (-0.03, 0.03)
|
||||
hue_range = (-0.01, 0.01)
|
||||
max_crop_px = 3
|
||||
brightness_factor = random.uniform(0.97, 1.03)
|
||||
contrast_factor = random.uniform(0.97, 1.03)
|
||||
saturation_factor = random.uniform(0.97, 1.03)
|
||||
max_rotation = 0.5
|
||||
noise_intensity = 0.01
|
||||
border_size_range = (0, 2)
|
||||
border_size = random.randint(0, 1)
|
||||
use_extra = random.random() < 0.3 and extra_effects
|
||||
elif variation_strength == "high":
|
||||
brightness_range = (-0.08, 0.08)
|
||||
contrast_range = (-0.08, 0.08)
|
||||
saturation_range = (-0.08, 0.08)
|
||||
hue_range = (-0.02, 0.02)
|
||||
max_crop_px = 8
|
||||
brightness_factor = random.uniform(0.92, 1.08)
|
||||
contrast_factor = random.uniform(0.92, 1.08)
|
||||
saturation_factor = random.uniform(0.92, 1.08)
|
||||
max_rotation = 2.0
|
||||
noise_intensity = 0.03
|
||||
border_size_range = (0, 4)
|
||||
else: # medium (默认)
|
||||
brightness_range = (-0.05, 0.05)
|
||||
contrast_range = (-0.05, 0.05)
|
||||
saturation_range = (-0.05, 0.05)
|
||||
hue_range = (-0.015, 0.015)
|
||||
max_crop_px = 5
|
||||
border_size = random.randint(0, 3)
|
||||
use_extra = extra_effects
|
||||
else: # medium
|
||||
brightness_factor = random.uniform(0.95, 1.05)
|
||||
contrast_factor = random.uniform(0.95, 1.05)
|
||||
saturation_factor = random.uniform(0.95, 1.05)
|
||||
max_rotation = 1.0
|
||||
noise_intensity = 0.02
|
||||
border_size_range = (0, 3)
|
||||
border_size = random.randint(0, 2)
|
||||
use_extra = random.random() < 0.7 and extra_effects
|
||||
|
||||
# 调整图像为目标比例
|
||||
width, height = image.size
|
||||
current_ratio = width / height
|
||||
target_ratio_value = target_ratio[0] / target_ratio[1]
|
||||
|
||||
# 不再直接调整尺寸,而是先resize然后进行轻微裁剪
|
||||
|
||||
# 第一步:先调整大小,使较短边符合目标尺寸
|
||||
# 调整大小
|
||||
if current_ratio > target_ratio_value: # 图片较宽
|
||||
# 先根据高度调整大小
|
||||
new_height = 1200 # 可以根据需要调整目标尺寸
|
||||
new_height = 1200
|
||||
new_width = int(new_height * current_ratio)
|
||||
else: # 图片较高
|
||||
# 先根据宽度调整大小
|
||||
new_width = 900 # 可以根据需要调整目标尺寸
|
||||
new_width = 900
|
||||
new_height = int(new_width / current_ratio)
|
||||
|
||||
# 调整尺寸
|
||||
# 高效调整尺寸
|
||||
resized_image = image.resize((new_width, new_height), Image.LANCZOS)
|
||||
|
||||
# 第二步:计算要裁剪的区域,使最终比例为目标比例
|
||||
# 裁剪为目标比例
|
||||
resized_width, resized_height = resized_image.size
|
||||
if resized_width / resized_height > target_ratio_value: # 调整后的图片较宽
|
||||
# 需要裁剪宽度
|
||||
if resized_width / resized_height > target_ratio_value:
|
||||
crop_width = int(resized_height * target_ratio_value)
|
||||
|
||||
# 添加微小变化:不完全居中裁剪,而是稍微偏移
|
||||
if add_variation:
|
||||
max_offset = max(1, min(20, (resized_width - crop_width) // 5)) # 最大偏移量
|
||||
offset = random.randint(-max_offset, max_offset)
|
||||
else:
|
||||
offset = 0
|
||||
|
||||
# 确保裁剪区域在图像内
|
||||
crop_x1 = (resized_width - crop_width) // 2 + offset
|
||||
crop_x1 = max(0, min(crop_x1, resized_width - crop_width))
|
||||
max_offset = max(1, min(10, (resized_width - crop_width) // 10))
|
||||
offset = random.randint(-max_offset, max_offset) if add_variation else 0
|
||||
crop_x1 = max(0, min((resized_width - crop_width) // 2 + offset, resized_width - crop_width))
|
||||
crop_x2 = crop_x1 + crop_width
|
||||
|
||||
result = resized_image.crop((crop_x1, 0, crop_x2, resized_height))
|
||||
else: # 调整后的图片较高
|
||||
# 需要裁剪高度
|
||||
else:
|
||||
crop_height = int(resized_width / target_ratio_value)
|
||||
|
||||
# 添加微小变化:不完全居中裁剪,而是稍微偏移
|
||||
if add_variation:
|
||||
max_offset = max(1, min(20, (resized_height - crop_height) // 5)) # 最大偏移量
|
||||
offset = random.randint(-max_offset, max_offset)
|
||||
else:
|
||||
offset = 0
|
||||
|
||||
# 确保裁剪区域在图像内
|
||||
crop_y1 = (resized_height - crop_height) // 2 + offset
|
||||
crop_y1 = max(0, min(crop_y1, resized_height - crop_height))
|
||||
max_offset = max(1, min(10, (resized_height - crop_height) // 10))
|
||||
offset = random.randint(-max_offset, max_offset) if add_variation else 0
|
||||
crop_y1 = max(0, min((resized_height - crop_height) // 2 + offset, resized_height - crop_height))
|
||||
crop_y2 = crop_y1 + crop_height
|
||||
|
||||
result = resized_image.crop((0, crop_y1, resized_width, crop_y2))
|
||||
|
||||
# 如果需要添加微小变化
|
||||
if add_variation:
|
||||
# 转换为RGB模式进行处理
|
||||
if result.mode != 'RGB':
|
||||
processed_image = result.convert('RGB')
|
||||
else:
|
||||
processed_image = result.copy()
|
||||
|
||||
# 1. 微调亮度
|
||||
brightness_factor = 1.0 + random.uniform(*brightness_range)
|
||||
processed_image = self._adjust_brightness(processed_image, brightness_factor)
|
||||
|
||||
# 2. 微调对比度
|
||||
contrast_factor = 1.0 + random.uniform(*contrast_range)
|
||||
processed_image = self._adjust_contrast(processed_image, contrast_factor)
|
||||
|
||||
# 3. 微调饱和度
|
||||
saturation_factor = 1.0 + random.uniform(*saturation_range)
|
||||
processed_image = self._adjust_saturation(processed_image, saturation_factor)
|
||||
|
||||
# 4. 微小裁剪调整
|
||||
crop_px = random.randint(0, max_crop_px)
|
||||
if crop_px > 0:
|
||||
width, height = processed_image.size
|
||||
processed_image = processed_image.crop((crop_px, crop_px, width-crop_px, height-crop_px))
|
||||
processed_image = processed_image.resize((width, height), Image.LANCZOS)
|
||||
|
||||
# 5. 微小旋转
|
||||
# 如果不需要变化或是低强度且禁用额外效果
|
||||
if not add_variation or (variation_strength == "low" and not use_extra):
|
||||
# 重置随机种子
|
||||
if seed is not None:
|
||||
random.seed()
|
||||
np.random.seed()
|
||||
return result
|
||||
|
||||
# 高效应用基本变化
|
||||
processed_image = result.convert('RGB')
|
||||
|
||||
# 1. 亮度调整
|
||||
if abs(brightness_factor - 1.0) > 0.01:
|
||||
enhancer = ImageEnhance.Brightness(processed_image)
|
||||
processed_image = enhancer.enhance(brightness_factor)
|
||||
|
||||
# 2. 对比度调整
|
||||
if abs(contrast_factor - 1.0) > 0.01:
|
||||
enhancer = ImageEnhance.Contrast(processed_image)
|
||||
processed_image = enhancer.enhance(contrast_factor)
|
||||
|
||||
# 3. 饱和度调整
|
||||
if abs(saturation_factor - 1.0) > 0.01:
|
||||
enhancer = ImageEnhance.Color(processed_image)
|
||||
processed_image = enhancer.enhance(saturation_factor)
|
||||
|
||||
# 4. 旋转 (只在中高强度时应用)
|
||||
if variation_strength != "low" and abs(max_rotation) > 0.1:
|
||||
rotation_angle = random.uniform(-max_rotation, max_rotation)
|
||||
processed_image = processed_image.rotate(rotation_angle, resample=Image.BICUBIC, expand=False)
|
||||
if abs(rotation_angle) > 0.1: # 只有当角度足够大时才旋转
|
||||
processed_image = processed_image.rotate(rotation_angle, resample=Image.BICUBIC, expand=False)
|
||||
|
||||
# 应用额外效果 (只在需要时)
|
||||
if use_extra:
|
||||
# 根据强度决定是否应用特定效果
|
||||
apply_sharpen = random.random() < 0.4
|
||||
apply_blur = not apply_sharpen and random.random() < 0.3
|
||||
|
||||
# 6. 额外效果 (如果启用)
|
||||
if extra_effects:
|
||||
# 6.1 添加微弱噪点
|
||||
processed_image = self._add_noise(processed_image, intensity=noise_intensity)
|
||||
# 锐化
|
||||
if apply_sharpen:
|
||||
enhancer = ImageEnhance.Sharpness(processed_image)
|
||||
sharpness = 1.2 if variation_strength == "high" else 1.1
|
||||
processed_image = enhancer.enhance(sharpness)
|
||||
|
||||
# 模糊
|
||||
elif apply_blur:
|
||||
radius = 0.7 if variation_strength == "high" else 0.4
|
||||
processed_image = processed_image.filter(ImageFilter.GaussianBlur(radius=radius))
|
||||
|
||||
# 边框处理 (在图像不太小的情况下)
|
||||
if border_size > 0 and min(processed_image.size) > 300:
|
||||
border_color = (
|
||||
random.randint(0, 5),
|
||||
random.randint(0, 5),
|
||||
random.randint(0, 5)
|
||||
)
|
||||
w, h = processed_image.size
|
||||
bordered = Image.new('RGB', (w + border_size*2, h + border_size*2), border_color)
|
||||
bordered.paste(processed_image, (border_size, border_size))
|
||||
|
||||
# 6.2 微小色相调整
|
||||
processed_image = self._adjust_hue(processed_image, shift=random.uniform(*hue_range))
|
||||
|
||||
# 6.3 随机边缘微调 - 随机添加1-3像素的边缘
|
||||
border_size = random.randint(*border_size_range)
|
||||
if border_size > 0:
|
||||
processed_image = self._add_border_and_crop(processed_image, border_size)
|
||||
|
||||
# 6.4 随机进行细微的锐化或模糊处理
|
||||
if random.random() > 0.5:
|
||||
processed_image = self._slight_sharpen(processed_image)
|
||||
else:
|
||||
processed_image = self._slight_blur(processed_image)
|
||||
|
||||
# 重置随机种子,避免影响其他操作
|
||||
if seed is not None:
|
||||
random.seed()
|
||||
|
||||
return processed_image
|
||||
else:
|
||||
# 重置随机种子,避免影响其他操作
|
||||
if seed is not None:
|
||||
random.seed()
|
||||
|
||||
return result
|
||||
|
||||
def _adjust_hue(self, image: Image.Image, shift: float) -> Image.Image:
|
||||
"""调整图像色相"""
|
||||
if shift == 0.0:
|
||||
return image
|
||||
# 随机裁剪回原尺寸
|
||||
offset_x = random.randint(0, border_size*2)
|
||||
offset_y = random.randint(0, border_size*2)
|
||||
processed_image = bordered.crop((offset_x, offset_y, offset_x + w, offset_y + h))
|
||||
|
||||
try:
|
||||
# 使用PIL的色相调整
|
||||
from PIL import ImageEnhance, ImageOps
|
||||
import colorsys
|
||||
|
||||
# 获取像素数据
|
||||
data = list(image.getdata())
|
||||
new_data = []
|
||||
|
||||
for pixel in data:
|
||||
r, g, b = pixel[:3]
|
||||
# 转换为HSV
|
||||
h, s, v = colorsys.rgb_to_hsv(r/255, g/255, b/255)
|
||||
# 调整色相 (H 是 0-1 的值)
|
||||
h = (h + shift) % 1.0
|
||||
# 转回RGB
|
||||
r, g, b = colorsys.hsv_to_rgb(h, s, v)
|
||||
r = int(r * 255)
|
||||
g = int(g * 255)
|
||||
b = int(b * 255)
|
||||
|
||||
if len(pixel) > 3: # 如果有alpha通道
|
||||
new_data.append((r, g, b, pixel[3]))
|
||||
else:
|
||||
new_data.append((r, g, b))
|
||||
|
||||
result = Image.new(image.mode, image.size)
|
||||
result.putdata(new_data)
|
||||
return result
|
||||
except (ImportError, AttributeError):
|
||||
# 如果无法使用上述方法,返回原图
|
||||
return image
|
||||
|
||||
def _add_noise(self, image: Image.Image, intensity: float = 0.02) -> Image.Image:
|
||||
"""添加微弱噪点,intensity控制噪点强度(0-1)"""
|
||||
if intensity <= 0:
|
||||
return image
|
||||
# 重置随机种子
|
||||
if seed is not None:
|
||||
random.seed()
|
||||
np.random.seed()
|
||||
|
||||
# 获取像素数据
|
||||
data = list(image.getdata())
|
||||
new_data = []
|
||||
|
||||
for pixel in data:
|
||||
r, g, b = pixel[:3]
|
||||
# 添加随机噪点
|
||||
noise_r = random.randint(-int(intensity * 255), int(intensity * 255))
|
||||
noise_g = random.randint(-int(intensity * 255), int(intensity * 255))
|
||||
noise_b = random.randint(-int(intensity * 255), int(intensity * 255))
|
||||
|
||||
r = max(0, min(255, r + noise_r))
|
||||
g = max(0, min(255, g + noise_g))
|
||||
b = max(0, min(255, b + noise_b))
|
||||
|
||||
if len(pixel) > 3: # 如果有alpha通道
|
||||
new_data.append((r, g, b, pixel[3]))
|
||||
else:
|
||||
new_data.append((r, g, b))
|
||||
|
||||
result = Image.new(image.mode, image.size)
|
||||
result.putdata(new_data)
|
||||
return result
|
||||
|
||||
def _add_border_and_crop(self, image: Image.Image, border_size: int) -> Image.Image:
|
||||
"""添加边框然后裁剪回原尺寸,用于改变边缘像素"""
|
||||
if border_size <= 0:
|
||||
return image
|
||||
|
||||
width, height = image.size
|
||||
|
||||
# 创建略大的画布
|
||||
border_color = (
|
||||
random.randint(0, 10),
|
||||
random.randint(0, 10),
|
||||
random.randint(0, 10)
|
||||
)
|
||||
bordered = Image.new(image.mode, (width + border_size*2, height + border_size*2), border_color)
|
||||
bordered.paste(image, (border_size, border_size))
|
||||
|
||||
# 随机裁剪回原尺寸
|
||||
offset_x = random.randint(0, border_size*2)
|
||||
offset_y = random.randint(0, border_size*2)
|
||||
result = bordered.crop((offset_x, offset_y, offset_x + width, offset_y + height))
|
||||
return result
|
||||
|
||||
def _slight_sharpen(self, image: Image.Image) -> Image.Image:
|
||||
"""轻微锐化图像"""
|
||||
try:
|
||||
from PIL import ImageEnhance
|
||||
enhancer = ImageEnhance.Sharpness(image)
|
||||
return enhancer.enhance(1.2) # 轻微锐化,1.0是原始锐度
|
||||
except (ImportError, AttributeError):
|
||||
return image
|
||||
|
||||
def _slight_blur(self, image: Image.Image) -> Image.Image:
|
||||
"""轻微模糊图像"""
|
||||
try:
|
||||
from PIL import ImageFilter
|
||||
return image.filter(ImageFilter.GaussianBlur(radius=0.5))
|
||||
except (ImportError, AttributeError):
|
||||
return image
|
||||
|
||||
def _adjust_brightness(self, image: Image.Image, factor: float) -> Image.Image:
|
||||
"""调整图像亮度"""
|
||||
if factor == 1.0:
|
||||
return image
|
||||
|
||||
data = list(image.getdata())
|
||||
new_data = []
|
||||
|
||||
for pixel in data:
|
||||
r, g, b = pixel[:3]
|
||||
r = min(255, max(0, int(r * factor)))
|
||||
g = min(255, max(0, int(g * factor)))
|
||||
b = min(255, max(0, int(b * factor)))
|
||||
|
||||
if len(pixel) > 3: # 如果有alpha通道
|
||||
new_data.append((r, g, b, pixel[3]))
|
||||
else:
|
||||
new_data.append((r, g, b))
|
||||
|
||||
result = Image.new(image.mode, image.size)
|
||||
result.putdata(new_data)
|
||||
return result
|
||||
|
||||
def _adjust_contrast(self, image: Image.Image, factor: float) -> Image.Image:
|
||||
"""调整图像对比度"""
|
||||
if factor == 1.0:
|
||||
return image
|
||||
|
||||
data = list(image.getdata())
|
||||
new_data = []
|
||||
|
||||
# 计算平均亮度
|
||||
avg_r, avg_g, avg_b = 0, 0, 0
|
||||
count = 0
|
||||
|
||||
for pixel in data:
|
||||
r, g, b = pixel[:3]
|
||||
avg_r += r
|
||||
avg_g += g
|
||||
avg_b += b
|
||||
count += 1
|
||||
|
||||
if count > 0:
|
||||
avg_r //= count
|
||||
avg_g //= count
|
||||
avg_b //= count
|
||||
|
||||
# 调整对比度
|
||||
for pixel in data:
|
||||
r, g, b = pixel[:3]
|
||||
r = min(255, max(0, int(avg_r + (r - avg_r) * factor)))
|
||||
g = min(255, max(0, int(avg_g + (g - avg_g) * factor)))
|
||||
b = min(255, max(0, int(avg_b + (b - avg_b) * factor)))
|
||||
|
||||
if len(pixel) > 3: # 如果有alpha通道
|
||||
new_data.append((r, g, b, pixel[3]))
|
||||
else:
|
||||
new_data.append((r, g, b))
|
||||
|
||||
result = Image.new(image.mode, image.size)
|
||||
result.putdata(new_data)
|
||||
return result
|
||||
|
||||
def _adjust_saturation(self, image: Image.Image, factor: float) -> Image.Image:
|
||||
"""调整图像饱和度"""
|
||||
if factor == 1.0:
|
||||
return image
|
||||
|
||||
# 转换为HSV色彩空间,调整S通道,然后转回RGB
|
||||
try:
|
||||
# 使用内部方法,效率更高
|
||||
from PIL import ImageEnhance
|
||||
enhancer = ImageEnhance.Color(image)
|
||||
return enhancer.enhance(factor)
|
||||
except ImportError:
|
||||
# 如果PIL没有提供相关功能,使用自定义实现
|
||||
data = list(image.getdata())
|
||||
new_data = []
|
||||
|
||||
for pixel in data:
|
||||
r, g, b = pixel[:3]
|
||||
# 计算灰度值
|
||||
gray = (r + g + b) // 3
|
||||
# 调整饱和度
|
||||
r = min(255, max(0, int(gray + (r - gray) * factor)))
|
||||
g = min(255, max(0, int(gray + (g - gray) * factor)))
|
||||
b = min(255, max(0, int(gray + (b - gray) * factor)))
|
||||
|
||||
if len(pixel) > 3: # 如果有alpha通道
|
||||
new_data.append((r, g, b, pixel[3]))
|
||||
else:
|
||||
new_data.append((r, g, b))
|
||||
|
||||
result = Image.new(image.mode, image.size)
|
||||
result.putdata(new_data)
|
||||
return result
|
||||
return processed_image
|
||||
|
||||
def process_poster_for_notes(
|
||||
run_id: str,
|
||||
@ -748,21 +552,6 @@ def select_additional_images(
|
||||
) -> List[str]:
|
||||
"""
|
||||
选择未被海报使用的图像作为额外配图,并处理为3:4比例
|
||||
|
||||
Args:
|
||||
run_id: 运行ID
|
||||
topic_index: 主题索引
|
||||
variant_index: 变体索引
|
||||
poster_metadata_path: 海报元数据路径
|
||||
source_image_dir: 源图像目录
|
||||
num_additional_images: 要选择的额外图像数量
|
||||
output_handler: 输出处理器
|
||||
output_filename_template: 输出文件名模板
|
||||
variation_strength: 微调强度 - "low", "medium", "high"
|
||||
extra_effects: 是否添加额外效果
|
||||
|
||||
Returns:
|
||||
List[str]: 保存的额外配图路径列表
|
||||
"""
|
||||
logger.info(f"开始为主题 {topic_index} 变体 {variant_index} 选择额外配图")
|
||||
|
||||
@ -771,8 +560,10 @@ def select_additional_images(
|
||||
logger.error(f"海报元数据不存在: {poster_metadata_path}")
|
||||
return []
|
||||
|
||||
# 创建处理器实例并处理
|
||||
# 创建处理器实例
|
||||
creator = PosterNotesCreator(output_handler)
|
||||
|
||||
# 使用优化后的方法处理图像
|
||||
return creator.create_additional_images(
|
||||
run_id,
|
||||
topic_index,
|
||||
|
||||
@ -110,7 +110,7 @@ class PromptManager:
|
||||
if os.path.exists(path):
|
||||
filename = os.path.basename(path)
|
||||
# print(filename)
|
||||
content = ResourceLoader.load_all_refer_files(path)
|
||||
content = ResourceLoader.load_all_refer_files(path, 0.25)
|
||||
if content:
|
||||
self._refer_cache[filename] = content
|
||||
# print(content)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user