同步了选图模块

This commit is contained in:
jinye_huang 2025-04-27 16:13:28 +08:00
parent d9f37d6816
commit ba22befda1
3 changed files with 73 additions and 172 deletions

View File

@ -6,13 +6,10 @@ import math
from pathlib import Path
from PIL import Image, ImageDraw, ImageEnhance, ImageFilter, ImageOps
import logging # Import logging module
import re
class ImageCollageCreator:
def __init__(self, ):
"""初始化拼图创建器"""
self.collage_style = None
self.created_collages = []
# 定义可用拼接样式
self.collage_styles = [
@ -136,119 +133,31 @@ class ImageCollageCreator:
print(f"增强图片效果时出错: {str(e)}")
return img
def find_directory_fuzzy_match(self, base_dir, target_name):
"""
对图片目录进行模糊匹配查找最匹配目标名称的目录
Args:
base_dir: 基础目录路径
target_name: 目标对象名称
Returns:
tuple: (最佳匹配目录路径, 匹配分数) 如果没有匹配则返回 (None, 0)
"""
logging.info(f"尝试对图片目录进行模糊匹配: {target_name}")
try:
# 1. 获取base_dir下的所有目录
all_dirs = [d for d in os.listdir(base_dir)
if os.path.isdir(os.path.join(base_dir, d))]
logging.info(f"找到 {len(all_dirs)} 个图片目录可用于模糊匹配")
if not all_dirs:
logging.warning(f"基础目录 {base_dir} 下没有可用于匹配的子目录")
return None, 0
# 2. 提取对象名称中的关键词
# 首先通过常见分隔符分割(+、空格、_、-等)
parts = re.split(r'[+\s_\-]', target_name)
keywords = []
for part in parts:
# 只保留长度大于1的有意义关键词
if len(part) > 1:
keywords.append(part)
# 尝试匹配更短的语义单元例如中文的2-3个字的词语
for i in range(len(target_name) - 1):
keyword = target_name[i:i+2] # 提取2个字符
if len(keyword) == 2 and all('\u4e00' <= c <= '\u9fff' for c in keyword):
keywords.append(keyword)
logging.info(f"用于目录模糊匹配的关键词: {keywords}")
# 3. 对每个目录进行评分
dir_scores = {}
for directory in all_dirs:
score = 0
dir_lower = directory.lower()
# 为每个匹配的关键词增加分数
for keyword in keywords:
if keyword.lower() in dir_lower:
score += 1
# 如果得分大于0至少匹配一个关键词记录该目录
if score > 0:
dir_scores[directory] = score
# 4. 选择得分最高的目录
if dir_scores:
best_match = max(dir_scores.items(), key=lambda x: x[1])
found_dir = best_match[0]
score = best_match[1]
logging.info(f"模糊匹配成功!匹配目录: {found_dir},匹配分数: {score}")
return os.path.join(base_dir, found_dir), score
else:
logging.warning(f"模糊匹配未找到任何包含关键词的目录")
return None, 0
except Exception as e:
logging.exception(f"目录模糊匹配过程中出错: {e}")
return None, 0
def create_collage_with_style(self, input_dir, style=None, target_size=None):
"""
创建特定样式的照片拼贴
如果input_dir不存在会尝试进行模糊匹配
"""创建指定样式的拼接画布
Args:
input_dir: 包含图片的目录路径或目标对象名称
style: 拼贴画样式例如"grid_2x2", "overlap"
target_size: 拼贴画目标尺寸例如(900, 1200)
参数:
input_dir: 输入图片目录路径
style: 拼贴样式如不指定则随机选择
target_size: 目标尺寸默认为(900, 1200)
Returns:
tuple: (PIL.Image 拼贴画对象, 使用的图片文件列表)
返回:
tuple: (拼贴图, 选择的图片名称列表)如果创建失败则返回(None, [])
"""
logging.info(f"--- Starting Collage Creation for Directory: {input_dir} ---") # Start Log
try:
# 使用默认样式如果未指定
if style is None:
if self.collage_style is None:
style = "grid_2x2"
else:
style = self.collage_style
logging.info(f"Using collage style: {style}")
# 使用默认尺寸如果未指定
# 设置默认尺寸为3:4比例
if target_size is None:
target_size = (900, 1200) # 默认尺寸
target_size = (900, 1200) # 3:4比例
# 如果没有指定样式,随机选择一种
if style is None or style not in self.collage_styles:
style = random.choice(self.collage_styles)
logging.info(f"Using collage style: {style} with target size: {target_size}")
# 检查输入目录是否存在
if not os.path.exists(input_dir) or not os.path.isdir(input_dir):
# 尝试从输入路径获取基础目录和对象名称
base_dir = os.path.dirname(input_dir)
object_name = os.path.basename(input_dir)
# 如果基础目录存在,尝试模糊匹配
if os.path.exists(base_dir) and os.path.isdir(base_dir):
matched_dir, score = self.find_directory_fuzzy_match(base_dir, object_name)
if matched_dir and score > 0:
logging.info(f"使用模糊匹配的图片目录: {matched_dir}")
input_dir = matched_dir
else:
logging.error(f"无法找到匹配的图片目录: {input_dir}")
return None, []
else:
logging.error(f"输入目录不存在且无法进行模糊匹配: {input_dir}")
# 检查目录是否存在
if not os.path.exists(input_dir):
logging.error(f"Input directory does not exist: {input_dir}")
return None, []
# 支持的图片格式
@ -781,82 +690,74 @@ class ImageCollageCreator:
def process_directory(directory_path, style=None, target_size=(900, 1200), output_count=1):
"""
处理目录中的图片并创建指定数量的拼贴图
处理指定目录中的图片创建指定数量的拼贴图
如果给定的目录不存在会尝试进行模糊匹配
参数:
directory_path: 包含图片的目录路径
target_size: 拼贴图目标尺寸默认为 (900, 1200)
output_count: 需要生成的拼贴图数量默认为 1
Args:
directory_path: 图片目录路径或目标对象名称
style: 拼贴画样式例如"grid_2x2"如果为None则随机选择
target_size: 拼贴画尺寸默认为(900, 1200)
output_count: 要生成的拼贴画数量
Returns:
list: 成功创建的拼贴图列表 (PIL Image对象)
返回:
tuple: (拼贴图列表, 使用的图片名称列表的列表)如果生成失败返回 ([], [])
拼贴图列表是PIL.Image对象列表
图片名称列表是一个列表的列表每个子列表包含一张拼贴图使用的图片文件名
"""
logging.info(f"处理目录中的图片并创建 {output_count} 个拼贴图: {directory_path}")
# 创建拼贴图实例
# 创建 ImageCollageCreator 实例
collage_creator = ImageCollageCreator()
# 如果指定了样式,设置样式
if style:
collage_creator.set_collage_style(style)
collage_images = []
used_image_names = [] # 存储每个拼贴图使用的图片文件名
# 检查目录是否存在
if not os.path.exists(directory_path) or not os.path.isdir(directory_path):
# 尝试从路径获取基础目录和对象名称
base_dir = os.path.dirname(directory_path)
object_name = os.path.basename(directory_path)
if not os.path.exists(directory_path):
logging.error(f"目录不存在: {directory_path}")
return [], []
# 如果基础目录存在,尝试模糊匹配
if os.path.exists(base_dir) and os.path.isdir(base_dir):
matched_dir, score = collage_creator.find_directory_fuzzy_match(base_dir, object_name)
if matched_dir and score > 0:
logging.info(f"使用模糊匹配的图片目录: {matched_dir}")
directory_path = matched_dir
else:
logging.error(f"无法找到匹配的图片目录: {directory_path}")
return []
else:
logging.error(f"输入目录不存在且无法进行模糊匹配: {directory_path}")
return []
# 支持的图片格式
image_extensions = ('.jpg', '.jpeg', '.png', '.bmp')
# 获取有效图片文件列表
image_extensions = ('.jpg', '.jpeg', '.png', '.webp', '.bmp', '.gif')
# 获取目录中的所有有效图片文件
try:
all_files = os.listdir(directory_path)
image_files = [f for f in all_files
all_images_names = [f for f in all_files
if f.lower().endswith(image_extensions) and os.path.isfile(os.path.join(directory_path, f))]
logging.info(f"目录中找到 {len(image_files)} 个有效图片文件")
if not image_files:
logging.warning(f"目录中未找到有效图片: {directory_path}")
return []
if not all_images_names:
logging.error(f"目录中没有有效的图片文件: {directory_path}")
return [], []
logging.info(f"目录中找到 {len(all_images_names)} 个有效图片文件")
except Exception as e:
logging.exception(f"无法读取目录 {directory_path}: {e}")
return []
logging.exception(f"列出目录内容时出错: {e}")
return [], []
# 创建指定数量的拼贴图
created_collages = []
# 尝试创建请求数量的拼贴图
for i in range(output_count):
# 如果指定了样式则使用指定样式否则让create_collage_with_style自行选择
if style:
collage, used_images = collage_creator.create_collage_with_style(directory_path, style=style, target_size=target_size)
else:
# 随机选择一种样式
available_styles = collage_creator.collage_styles
random_style = random.choice(available_styles)
collage, used_images = collage_creator.create_collage_with_style(directory_path, style=random_style, target_size=target_size)
try:
# 创建拼贴图,使用指定样式
collage, selected_images_names = collage_creator.create_collage_with_style(
directory_path,
style=style,
target_size=target_size
)
if collage:
created_collages.append(collage)
logging.info(f"成功创建拼贴图 {len(created_collages)}/{output_count}")
else:
logging.warning(f"创建拼贴图 {i+1}/{output_count} 失败")
collage_images.append(collage)
logging.info(f"已处理目录 {directory_path},成功创建 {len(created_collages)}/{output_count} 个拼贴图")
return created_collages
# 从输出日志中解析出使用的图片名称
# 由于我们修改了create_collage_with_style来打印选择的图片
# 可能需要进一步修改为直接返回选择的图片
used_image_names.append(selected_images_names)
logging.info(f"成功创建拼贴图 {i+1}/{output_count}")
else:
logging.error(f"无法创建拼贴图 {i+1}/{output_count}")
except Exception as e:
logging.exception(f"创建拼贴图 {i+1}/{output_count} 时发生异常: {e}")
logging.info(f"已处理目录 {directory_path},成功创建 {len(collage_images)}/{output_count} 个拼贴图")
return collage_images, used_image_names
def find_main_subject(image):
# ... (keep the existing implementation) ...