0xZohar commited on
Commit
a3d60c3
·
verified ·
1 Parent(s): e71ff0b

Add code/cube3d/training/merge_obj_by_prefix.py

Browse files
code/cube3d/training/merge_obj_by_prefix.py ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import re
3
+ import shutil
4
+ import json # 修复:补充json导入(原代码虽未用,但避免后续扩展报错)
5
+ import pandas as pd # 修复:补充pandas导入(同理,确保依赖完整)
6
+ from collections import defaultdict
7
+
8
+ def extract_merge_key(filename):
9
+ """提取合并键:开头连续数字为键(用于分组),字母开头返回原文件名并标记"""
10
+ name_without_ext = os.path.splitext(filename)[0]
11
+ # 匹配开头连续数字(如"123_bolt"→"123","A001"无匹配)
12
+ num_match = re.match(r'^\d+', name_without_ext)
13
+ if num_match:
14
+ return num_match.group(), 'num_start' # 数字开头:返回数字键+类型
15
+ else:
16
+ return name_without_ext, 'letter_start' # 字母开头:返回原名+类型
17
+
18
+ def merge_obj_by_prefix(input_dir, output_dir):
19
+ """
20
+ 按.obj前缀合并:每组复制排序后第一个文件到输出目录,字母开头文件单独打印
21
+ """
22
+ # 1. 初始化存储:数字前缀→文件路径列表,字母开头文件列表
23
+ num_groups = defaultdict(list) # key: 数字前缀, value: [文件路径1, 文件路径2, ...]
24
+ letter_files = [] # 存储字母开头的文件名(仅记录,不复制)
25
+
26
+ # 2. 扫描输入目录所有.obj文件(递归包含子目录)
27
+ print(f"开始扫描 {input_dir} 下的.obj文件...\n")
28
+ for root, _, files in os.walk(input_dir):
29
+ for file in files:
30
+ if file.lower().endswith('.obj'): # 兼容 .OBJ 大写后缀
31
+ file_path = os.path.join(root, file)
32
+ merge_key, start_type = extract_merge_key(file)
33
+
34
+ if start_type == 'num_start':
35
+ # 数字开头:加入对应分组
36
+ num_groups[merge_key].append(file_path)
37
+ print(f" 数字开头:{file} → 归入组【{merge_key}】")
38
+ else:
39
+ # 字母开头:加入未合并列表
40
+ letter_files.append(file)
41
+ print(f" 字母开头:{file} → 不合并(仅记录)")
42
+
43
+ # 3. 检查是否有可处理的文件
44
+ if not num_groups and not letter_files:
45
+ print(f"警告:在 {input_dir} 中未找到任何.obj文件!")
46
+ return
47
+
48
+ # 4. 创建输出目录(清空原有内容,避免旧文件干扰)
49
+ if os.path.exists(output_dir):
50
+ shutil.rmtree(output_dir) # 删除原有目录及文件
51
+ os.makedirs(output_dir, exist_ok=True)
52
+ print(f"\n已创建干净的输出目录:{output_dir}")
53
+
54
+ # 5. 处理每个数字分组:排序后复制第一个文件到输出目录
55
+ copied_count = 0
56
+ print(f"\n开始处理合并组(共 {len(num_groups)} 组):")
57
+ for group_key in sorted(num_groups.keys()): # 按数字前缀排序(如123→456)
58
+ file_paths = num_groups[group_key]
59
+ # 对组内文件按文件名排序(确保每次复制顺序一致)
60
+ sorted_files = sorted(file_paths, key=lambda x: os.path.basename(x))
61
+ first_file = sorted_files[0] # 取排序后第一个文件
62
+ first_filename = os.path.basename(first_file)
63
+
64
+ # 复制文件到输出目录(保留原文件名)
65
+ dest_path = os.path.join(output_dir, first_filename)
66
+ shutil.copy2(first_file, dest_path) # copy2 保留文件元信息(修改时间等)
67
+ copied_count += 1
68
+
69
+ print(f" 组【{group_key}】:复制排序后第一个文件 → {first_filename}")
70
+
71
+ # 6. 单独打印字母开头的未合并文件
72
+ print(f"\n=== 字母开头的未合并零件列表(共 {len(letter_files)} 个)===")
73
+ if letter_files:
74
+ for idx, file in enumerate(sorted(letter_files), 1): # 排序后打印,更整齐
75
+ print(f" {idx}. {file}")
76
+ else:
77
+ print(" 无字母开头的未合并零件")
78
+
79
+ # 7. 输出最终统计
80
+ print(f"\n=== 处理完成统计 ===")
81
+ print(f" 合并组总数:{len(num_groups)} 组")
82
+ print(f" 成功复制文件数:{copied_count} 个(输出目录:{output_dir})")
83
+ print(f" 未合并文件数:{len(letter_files)} 个(仅记录,未复制)")
84
+
85
+ if __name__ == "__main__":
86
+ # --------------------------
87
+ # 配置参数(请根据实际情况修改)
88
+ # --------------------------
89
+ INPUT_DIR = "/public/home/wangshuo/gap/assembly/data/part_obj_300" # .obj源文件目录(递归扫描)
90
+ OUTPUT_DIR = "/public/home/wangshuo/gap/assembly/data/part_obj_300_merge_by_prefix" # 合并后文件输出目录(仅存复制的文件)
91
+
92
+ # 执行合并逻辑
93
+ merge_obj_by_prefix(INPUT_DIR, OUTPUT_DIR)
94
+ print(f"\n✅ .obj零件合并复制完成!输出目录仅保留每组排序后第一个文件。")