import io import os import tarfile import pickle import zstandard import numpy as np # 数据集路径列表 archive_paths = [ f"/home/dataset-assist-0/usr/lh/ysh/dw/RL/AR/data/DyMesh_50000v_16f_0000_part_{str(i).zfill(2)}" for i in range(4) ] TARGET_CHECK_COUNT = 20 collected_objects = [] print(f"🚀 开始跨包搜寻前 {TARGET_CHECK_COUNT} 个有效的 16 帧物体进行数值检查...\n") # ================= 阶段 1:流式收集前 20 个物体 ================= for archive_path in archive_paths: if len(collected_objects) >= TARGET_CHECK_COUNT: break try: with open(archive_path, 'rb') as fh: dctx = zstandard.ZstdDecompressor() with dctx.stream_reader(fh) as reader: with tarfile.open(fileobj=reader, mode='r|') as tar: while True: try: member = tar.next() if member is None: break except tarfile.ReadError: break if member.isfile(): f = tar.extractfile(member) if f is not None: try: mem_file = io.BytesIO(f.read()) data = pickle.load(mem_file) if isinstance(data, dict) and 'vertices' in data and 'faces' in data: vertices = data['vertices'] if vertices.shape[0] == 16: collected_objects.append({ 'name': os.path.basename(member.name), 'vertices': vertices, 'faces': data['faces'] }) if len(collected_objects) >= TARGET_CHECK_COUNT: break except Exception: continue except FileNotFoundError: continue actual_count = len(collected_objects) if actual_count < 2: print(f"❌ 收集到的物体数量不足 ({actual_count}个),无法进行对比检查。") exit() print(f"\n✅ 成功收集 {actual_count} 个物体,开始进行数值一致性深度交叉比对:") print("=" * 80) # ================= 阶段 2:检查 1 — 单文件内部帧间差异 (是否是静态死动效) ================= print("\n🔍 【检查项 1】每个文件内部的 16 帧之间是否完全相同(检查物体是否在运动):") print("-" * 80) static_objects_count = 0 for idx, obj in enumerate(collected_objects): verts = obj['vertices'] # Shape: (16, V, 3) # 以第一帧为基准,对比后续 15 帧 first_frame = verts[0] frame_static_flags = [] for f_idx in range(1, 16): # 使用 np.allclose 应对浮点数微小误差,如果你要求绝对一模一样,可以换成 np.array_equal is_same = np.allclose(first_frame, verts[f_idx], atol=1e-6) frame_static_flags.append(is_same) # 计算当前物体帧间完全相同的比例 same_ratio = sum(frame_static_flags) / 15.0 * 100 if same_ratio == 100.0: status_str = "❌ 静态(16帧数值完全相同,物体根本没动)" static_objects_count += 1 elif same_ratio > 0.0: status_str = f"⚠️ 部分帧停滞 (有 {same_ratio:.1f}% 的帧与第一帧完全一样)" else: status_str = "✅ 动态正常(帧间数值均有变化)" print(f"[{idx+1:02d}] 物体: {obj['name']} -> {status_str}") # ================= 阶段 3:检查 2 — 不同文件之间的内容重复率 (检查是否存在李鬼) ================= print("\n🔍 【检查项 2】不同文件之间是否存在完全重复的样本(交叉对比):") print("-" * 80) duplicate_pairs = 0 total_pairs_checked = 0 # 对 20 个物体进行两两组合交叉比对 (Combinations) for i in range(actual_count): for j in range(i + 1, actual_count): total_pairs_checked += 1 obj_A = collected_objects[i] obj_B = collected_objects[j] # 首先检查顶点矩阵的 Shape 是否一致,如果 Shape 不同,说明肯定不是同一个物体 if obj_A['vertices'].shape != obj_B['vertices'].shape: continue # 如果 Shape 相同,进一步比对 16 帧的数值 is_verts_duplicate = np.allclose(obj_A['vertices'], obj_B['vertices'], atol=1e-6) is_faces_duplicate = np.array_equal(obj_A['faces'], obj_B['faces']) if is_verts_duplicate and is_faces_duplicate: duplicate_pairs += 1 print(f"🚨 发现完全重复的样本对: 物体 {i+1:02d} == 物体 {j+1:02d}") print(f" ↳ A: {obj_A['name']}") print(f" ↳ B: {obj_B['name']}") # ================= 阶段 4:总结报告与百分比打印 ================= print("\n" + "=" * 80) print("📊 检查结果数据大总结报告") print("=" * 80) # 计算百分比 static_percent = (static_objects_count / actual_count) * 100 duplicate_percent = (duplicate_pairs / total_pairs_checked) * 100 if total_pairs_checked > 0 else 0.0 print(f"1. 动效停滞率 (单文件内部):") print(f" - 检查总数: {actual_count} 个物体") print(f" - 静态死模型数量: {static_objects_count} 个") print(f" - 【结论】当前抽样样本中有 {static_percent:.2f}% 的物体属于“完全不动”的伪4D数据") print("-" * 40) print(f"2. 样本去重重复率 (跨文件外部):") print(f" - 总共交叉比对组合数: {total_pairs_checked} 对") print(f" - 完全一模一样的绝对重复对数: {duplicate_pairs} 对") print(f" - 【结论】当前抽样样本之间的绝对内容重复率为: {duplicate_percent:.2f}%") print("=" * 80 + "\n")