如何优化代码实现目录中图像序列的规范化批量合并输出?
改进图像序列合并代码的方案
原代码存在硬编码扩展名、未按前缀+扩展名分组、帧号提取逻辑不够精准等问题,以下是修复并优化后的实现:
核心改进点
- 动态解析每个文件的前缀、帧号、扩展名,不再依赖硬编码
- 按「前缀+扩展名」分组,确保同序列文件才会被合并
- 增强帧号提取的鲁棒性,适配你给出的命名规则
- 自动处理单文件和多文件序列的输出格式
完整代码实现
import os import re from itertools import groupby scanDir = "你的目标目录路径" fileFormats = [".exr", ".dpx"] # 可扩展支持的格式 def parse_filename(filename): # 拆分文件名和扩展名 name_part, ext = os.path.splitext(filename) ext = ext.lstrip('.') # 去掉扩展名前的点 # 匹配末尾的连续数字(帧号) match = re.search(r'(\d+)$', name_part) if not match: return None # 无帧号的文件跳过 frame_num = match.group(1) # 获取前缀(去掉末尾的帧号部分) prefix = name_part[:-len(frame_num)] return (prefix, frame_num, ext) if os.path.exists(scanDir): # 收集所有符合格式的文件并解析 parsed_files = [] for root, _, filenames in os.walk(scanDir): for file in filenames: # 检查扩展名是否在允许列表中 ext = os.path.splitext(file)[1].lower() if ext in [f'.{fmt.lower()}' for fmt in fileFormats]: parsed = parse_filename(file) if parsed: parsed_files.append(parsed) # 先按(前缀,扩展名)排序,确保同序列的文件排在一起 parsed_files.sort(key=lambda x: (x[0], x[2], int(x[1]))) # 按(前缀,扩展名)分组 grouped = groupby(parsed_files, key=lambda x: (x[0], x[2])) result = [] for (prefix, ext), files in grouped: frames = sorted([int(f[1]) for f in files]) if len(frames) == 1: # 单文件直接输出原格式 result.append(f"{prefix}{frames[0]}.{ext}") else: # 多文件合并成范围格式,保留帧号的原始位数 first_frame_str = str(frames[0]).zfill(len(str(frames[0]))) last_frame_str = str(frames[-1]).zfill(len(str(frames[-1]))) result.append(f"{prefix}{first_frame_str}-{last_frame_str}.{ext}") else: result = [] # 打印结果 for item in result: print(item)
代码说明
parse_filename函数:负责拆分每个文件的前缀、帧号和扩展名,通过正则精准匹配文件名末尾的连续数字作为帧号,避免误匹配前缀中的数字。- 分组逻辑:使用
groupby按「前缀+扩展名」分组,保证只有同序列的文件才会被合并,解决原代码跨序列分组的问题。 - 帧号处理:将帧号转为整数排序后,转回字符串并保留原始位数(比如1001不会变成1),保证输出格式和原文件名一致。
- 格式兼容:通过
fileFormats配置支持的扩展名,无需硬编码,可灵活扩展。
测试示例
对于输入文件:test.1001.exr、test.1002.exr、test02.1001.dpx、test02.1002.dpx
输出结果:
test.1001-1002.exr test02.1001-1002.dpx
内容的提问来源于stack exchange,提问作者Tim
相关产品推荐
相关产品推荐

