修改了配图方法

This commit is contained in:
jinye_huang 2025-05-09 14:00:46 +08:00
parent a551a87291
commit b57dd9de55

View File

@ -177,9 +177,27 @@ class PosterNotesCreator:
num_additional_images: int = 3,
output_filename_template: str = "additional_{index}.jpg",
variation_strength: str = "medium",
extra_effects: bool = True
extra_effects: bool = True,
collage_style: str = None
) -> List[str]:
"""选择未被海报使用的图像作为额外配图并处理为3:4比例"""
"""
选择未被海报使用的图像作为额外配图处理为3:4比例的拼图
Args:
run_id: 运行ID
topic_index: 主题索引
variant_index: 变体索引
poster_metadata_path: 海报元数据路径
source_image_dir: 源图像目录
num_additional_images: 要使用的额外图像数量默认为3
output_filename_template: 输出文件名模板
variation_strength: 变化强度可以是 'low', 'medium', 'high'
extra_effects: 是否应用额外效果
collage_style: 拼图风格可以是 'grid', 'mosaic', 'polaroid', 'slice', 'random' None不使用拼图
Returns:
List[str]: 保存的笔记图像路径列表
"""
logger.info(f"开始为主题 {topic_index} 变体 {variant_index} 选择额外配图")
# 获取候选图像
@ -220,7 +238,8 @@ class PosterNotesCreator:
output_filename_template.format(index=i+1),
image_seed,
variation_strength,
extra_effects
extra_effects,
collage_style
)
future_to_image[future] = (i, image_filename)
@ -313,51 +332,357 @@ class PosterNotesCreator:
output_filename,
seed,
variation_strength,
extra_effects
extra_effects,
collage_style=None
):
"""处理单张图像 - 此方法可在独立进程中运行"""
try:
# 加载图像
# 加载图像
image = Image.open(image_path)
# 处理图像为3:4比例并添加微小变化
processed_image = self.optimized_process_image(
# 处理图像,优先使用拼图处理而不是数字指纹模块
if collage_style:
# 如果指定了拼图风格,则使用拼图处理
processed_image = self.create_collage_image(
image,
(3, 4),
style=collage_style,
seed=seed
)
else:
# 调整为目标比例但不使用数字指纹模块
processed_image = self.optimized_process_image(
image,
(3, 4),
add_variation=True,
seed=seed,
seed=seed,
variation_strength=variation_strength,
extra_effects=extra_effects
extra_effects=False # 不使用高强度数字指纹模块
)
# 创建元数据
# 创建元数据
additional_metadata = {
"original_image": image_filename,
"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
}
"is_additional_image": True,
"processed": True,
"aspect_ratio": "3:4",
"variation_applied": True,
"variation_strength": variation_strength,
"collage_style": collage_style if collage_style else "none"
}
# 使用输出处理器保存图像
# 使用输出处理器保存图像
return self.output_handler.handle_generated_image(
run_id,
topic_index,
variant_index,
'additional', # 图像类型为additional
processed_image,
output_filename,
additional_metadata
)
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 create_collage_image(
self,
image: Image.Image,
target_ratio: Tuple[int, int] = (3, 4),
style: str = "grid",
seed: int = None
) -> Image.Image:
"""
创建拼图图像
Args:
image: 原始图像
target_ratio: 目标宽高比默认为(3, 4)
style: 拼图风格, 可以是 "grid", "mosaic", "polaroid", "slice", "random"
seed: 随机种子
Returns:
Image.Image: 拼图后的图像
"""
logger.info(f"创建拼图图像,风格: {style}")
# 设置随机种子
if seed is not None:
random.seed(seed)
np.random.seed(seed)
# 调整图像为目标比例
width, height = image.size
current_ratio = width / height
target_ratio_value = target_ratio[0] / target_ratio[1]
# 调整大小
if current_ratio > target_ratio_value: # 图片较宽
new_height = 1200
new_width = int(new_height * current_ratio)
else: # 图片较高
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:
crop_width = int(resized_height * target_ratio_value)
crop_x = (resized_width - crop_width) // 2
image_base = resized_image.crop((crop_x, 0, crop_x + crop_width, resized_height))
else:
crop_height = int(resized_width / target_ratio_value)
crop_y = (resized_height - crop_height) // 2
image_base = resized_image.crop((0, crop_y, resized_width, crop_y + crop_height))
# 确保base是RGB模式
image_base = image_base.convert('RGB')
base_width, base_height = image_base.size
# 根据指定风格创建拼图
if style == "random":
# 随机选择一种风格
style = random.choice(["grid", "mosaic", "polaroid", "slice"])
if style == "grid":
# 网格风格: 将图像分割为网格并随机调整每个网格块
grid_size = random.randint(2, 4) # 网格大小
cell_width = base_width // grid_size
cell_height = base_height // grid_size
# 创建空白画布
collage = Image.new('RGB', (base_width, base_height), (255, 255, 255))
# 处理每个网格
for row in range(grid_size):
for col in range(grid_size):
# 计算当前网格的位置
left = col * cell_width
top = row * cell_height
right = left + cell_width
bottom = top + cell_height
# 裁剪当前网格块
cell = image_base.crop((left, top, right, bottom))
# 随机应用效果
effect = random.choice(["rotate", "brightness", "contrast", "none"])
if effect == "rotate":
angle = random.uniform(-5, 5)
cell = cell.rotate(angle, resample=Image.BICUBIC, expand=False)
elif effect == "brightness":
factor = random.uniform(0.9, 1.1)
enhancer = ImageEnhance.Brightness(cell)
cell = enhancer.enhance(factor)
elif effect == "contrast":
factor = random.uniform(0.9, 1.1)
enhancer = ImageEnhance.Contrast(cell)
cell = enhancer.enhance(factor)
# 添加细小边框
border_size = random.randint(1, 3)
bordered_cell = Image.new('RGB', (cell.width + border_size*2, cell.height + border_size*2), (255, 255, 255))
bordered_cell.paste(cell, (border_size, border_size))
# 粘贴回拼图
collage.paste(bordered_cell.resize((cell_width, cell_height)), (left, top))
elif style == "mosaic":
# 马赛克风格: 创建不规则大小的方块组成的拼图
collage = Image.new('RGB', (base_width, base_height), (255, 255, 255))
# 创建不同大小的块
blocks = []
min_size = min(base_width, base_height) // 6
max_size = min(base_width, base_height) // 3
# 生成一些随机块
for _ in range(20): # 尝试放置20个块
block_width = random.randint(min_size, max_size)
block_height = random.randint(min_size, max_size)
left = random.randint(0, base_width - block_width)
top = random.randint(0, base_height - block_height)
blocks.append((left, top, left + block_width, top + block_height))
# 按面积排序块,大的先放
blocks.sort(key=lambda b: (b[2]-b[0])*(b[3]-b[1]), reverse=True)
# 放置每个块
for block in blocks:
left, top, right, bottom = block
# 裁剪原图对应区域
cell = image_base.crop(block)
# 随机应用滤镜
filter_type = random.choice(["none", "blur", "sharpen", "edge_enhance"])
if filter_type == "blur":
cell = cell.filter(ImageFilter.GaussianBlur(radius=random.uniform(0.3, 0.8)))
elif filter_type == "sharpen":
cell = cell.filter(ImageFilter.SHARPEN)
elif filter_type == "edge_enhance":
cell = cell.filter(ImageFilter.EDGE_ENHANCE)
# 添加边框
border_size = random.randint(2, 5)
bordered_cell = Image.new('RGB', (cell.width + border_size*2, cell.height + border_size*2), (240, 240, 240))
bordered_cell.paste(cell, (border_size, border_size))
# 粘贴到拼图上
collage.paste(bordered_cell, (left, top))
elif style == "polaroid":
# 宝丽来风格: 模拟拍立得照片排列
collage = Image.new('RGB', (base_width, base_height), (245, 245, 245))
# 创建2-4张宝丽来照片
num_photos = random.randint(2, 4)
# 根据照片数量确定大小
if num_photos == 2:
photo_width = base_width // 2 - 20
photo_height = int(photo_width * 0.9) # 稍扁一些
elif num_photos == 3:
photo_width = base_width // 3 - 15
photo_height = int(photo_width * 0.9)
else: # 4
photo_width = base_width // 2 - 15
photo_height = base_height // 2 - 15
# 根据照片数量计算布局
layouts = []
if num_photos == 2:
# 水平放置两张
layouts = [
(10, (base_height - photo_height) // 2),
(base_width - photo_width - 10, (base_height - photo_height) // 2 + random.randint(-10, 10))
]
elif num_photos == 3:
# 水平放置三张
layouts = [
(10, (base_height - photo_height) // 2 + random.randint(-15, 15)),
((base_width - photo_width) // 2, (base_height - photo_height) // 2 + random.randint(-5, 5)),
(base_width - photo_width - 10, (base_height - photo_height) // 2 + random.randint(-15, 15))
]
else: # 4
# 2x2网格放置
layouts = [
(10, 10),
(base_width - photo_width - 10, 10 + random.randint(-5, 5)),
(10 + random.randint(-5, 5), base_height - photo_height - 10),
(base_width - photo_width - 10, base_height - photo_height - 10 + random.randint(-5, 5))
]
# 创建并放置每张宝丽来照片
for i, (left, top) in enumerate(layouts):
# 为每张照片选择不同区域
src_left = random.randint(0, base_width - photo_width)
src_top = random.randint(0, base_height - photo_height)
photo = image_base.crop((src_left, src_top, src_left + photo_width, src_top + photo_height))
# 应用宝丽来效果
# 1. 提高对比度
enhancer = ImageEnhance.Contrast(photo)
photo = enhancer.enhance(1.2)
# 2. 轻微增加亮度
enhancer = ImageEnhance.Brightness(photo)
photo = enhancer.enhance(1.05)
# 3. 创建宝丽来边框
border_width = 10
frame = Image.new('RGB', (photo_width + border_width*2, photo_height + border_width*4), (255, 255, 255))
frame.paste(photo, (border_width, border_width))
# 4. 随机旋转
angle = random.uniform(-5, 5)
frame = frame.rotate(angle, resample=Image.BICUBIC, expand=False)
# 粘贴到拼图中
collage.paste(frame, (left, top))
elif style == "slice":
# 切片风格: 水平或垂直切片并错开
direction = random.choice(["horizontal", "vertical"])
collage = Image.new('RGB', (base_width, base_height), (255, 255, 255))
if direction == "horizontal":
# 水平切片
num_slices = random.randint(4, 8)
slice_height = base_height // num_slices
for i in range(num_slices):
# 切出原图片片
top = i * slice_height
bottom = min(top + slice_height, base_height)
slice_img = image_base.crop((0, top, base_width, bottom))
# 确定偏移量
offset = random.randint(-30, 30) if i % 2 == 1 else 0
# 确保偏移后不超出边界
offset = max(-base_width // 4, min(base_width // 4, offset))
# 粘贴到拼图,带偏移
paste_left = offset
if paste_left < 0:
# 如果左侧偏移超出边界,需要裁剪
slice_img = slice_img.crop((-paste_left, 0, slice_img.width, slice_img.height))
paste_left = 0
elif paste_left + slice_img.width > base_width:
# 如果右侧偏移超出边界,需要裁剪
slice_img = slice_img.crop((0, 0, base_width - paste_left, slice_img.height))
collage.paste(slice_img, (paste_left, top))
else:
# 垂直切片
num_slices = random.randint(4, 8)
slice_width = base_width // num_slices
for i in range(num_slices):
# 切出原图片片
left = i * slice_width
right = min(left + slice_width, base_width)
slice_img = image_base.crop((left, 0, right, base_height))
# 确定偏移量
offset = random.randint(-30, 30) if i % 2 == 1 else 0
# 确保偏移后不超出边界
offset = max(-base_height // 4, min(base_height // 4, offset))
# 粘贴到拼图,带偏移
paste_top = offset
if paste_top < 0:
# 如果上侧偏移超出边界,需要裁剪
slice_img = slice_img.crop((0, -paste_top, slice_img.width, slice_img.height))
paste_top = 0
elif paste_top + slice_img.height > base_height:
# 如果下侧偏移超出边界,需要裁剪
slice_img = slice_img.crop((0, 0, slice_img.width, base_height - paste_top))
collage.paste(slice_img, (left, paste_top))
else:
# 默认情况,直接返回调整后的图像
logger.warning(f"未知的拼图风格: {style},使用原始图像")
collage = image_base
# 清理元数据
result = self.strip_metadata(collage)
# 重置随机种子
if seed is not None:
random.seed()
np.random.seed()
logger.info(f"拼图图像创建完成,风格: {style}")
return result
def add_dct_noise(self, image: Image.Image, intensity: float = 0.1, block_size: int = 8) -> Image.Image:
"""
在DCT域添加噪声以对抗pHash (需要Scipy) - 强化版
@ -1457,10 +1782,27 @@ def select_additional_images(
output_handler: OutputHandler,
output_filename_template: str = "additional_{index}.jpg",
variation_strength: str = "medium",
extra_effects: bool = True
extra_effects: bool = True,
collage_style: str = None
) -> List[str]:
"""
选择未被海报使用的图像作为额外配图并处理为3:4比例
选择未被海报使用的图像作为额外配图并处理为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: 变化强度
extra_effects: 是否应用额外效果
collage_style: 拼图风格可以是 'grid', 'mosaic', 'polaroid', 'slice', 'random' None不使用拼图
Returns:
List[str]: 保存的笔记图像路径列表
"""
logger.info(f"开始为主题 {topic_index} 变体 {variant_index} 选择额外配图")
@ -1472,7 +1814,7 @@ def select_additional_images(
# 创建处理器实例
creator = PosterNotesCreator(output_handler)
# 使用优化后的方法处理图像
# 使用修改后的方法处理图像
return creator.create_additional_images(
run_id,
topic_index,
@ -1482,5 +1824,6 @@ def select_additional_images(
num_additional_images,
output_filename_template,
variation_strength,
extra_effects
extra_effects,
collage_style
)