修改了配图方法
This commit is contained in:
parent
a551a87291
commit
b57dd9de55
@ -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
|
||||
)
|
||||
Loading…
x
Reference in New Issue
Block a user