File size: 9,541 Bytes
08bf07d |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
import os
import json
import matplotlib.pyplot as plt
import numpy as np
from pose_classifier import PoseClassifier
import torch
from collections import defaultdict
def analyze_turning_patterns_detailed(dataset_path, num_samples=50):
"""详细分析转弯模式,基于相对于reference的pose变化"""
classifier = PoseClassifier()
samples_path = os.path.join(dataset_path, "samples")
all_analyses = []
sample_count = 0
# 用于统计每个类别的样本
class_samples = defaultdict(list)
print("=== 开始分析样本(基于相对于reference的变化)===")
for item in sorted(os.listdir(samples_path)): # 排序以便有序输出
if sample_count >= num_samples:
break
sample_dir = os.path.join(samples_path, item)
if os.path.isdir(sample_dir):
poses_path = os.path.join(sample_dir, "poses.json")
if os.path.exists(poses_path):
try:
with open(poses_path, 'r') as f:
poses_data = json.load(f)
target_relative_poses = poses_data['target_relative_poses']
if len(target_relative_poses) > 0:
# 🔧 创建相对pose向量(已经是相对于reference的)
pose_vecs = []
for pose_data in target_relative_poses:
# 相对位移(已经是相对于reference计算的)
translation = torch.tensor(pose_data['relative_translation'], dtype=torch.float32)
# 🔧 相对旋转(需要从current和reference计算)
current_rotation = torch.tensor(pose_data['current_rotation'], dtype=torch.float32)
reference_rotation = torch.tensor(pose_data['reference_rotation'], dtype=torch.float32)
# 计算相对旋转:q_relative = q_ref^-1 * q_current
relative_rotation = calculate_relative_rotation(current_rotation, reference_rotation)
# 组合为7D向量:[relative_translation, relative_rotation]
pose_vec = torch.cat([translation, relative_rotation], dim=0)
pose_vecs.append(pose_vec)
if pose_vecs:
pose_sequence = torch.stack(pose_vecs, dim=0)
# 🔧 使用新的分析方法
analysis = classifier.analyze_pose_sequence(pose_sequence)
analysis['sample_name'] = item
all_analyses.append(analysis)
# 🔧 详细输出每个样本的分类信息
print(f"\n--- 样本 {sample_count + 1}: {item} ---")
print(f"总帧数: {analysis['total_frames']}")
print(f"总距离: {analysis['total_distance']:.4f}")
# 分类分布
class_dist = analysis['class_distribution']
print(f"分类分布:")
for class_name, count in class_dist.items():
percentage = count / analysis['total_frames'] * 100
print(f" {class_name}: {count} 帧 ({percentage:.1f}%)")
# 🔧 调试前几个pose的分类过程
print(f"前3帧的详细分类过程:")
for i in range(min(3, len(pose_vecs))):
debug_info = classifier.debug_single_pose(
pose_vecs[i][:3], pose_vecs[i][3:7]
)
print(f" 帧{i}: {debug_info['classification']} "
f"(yaw: {debug_info['yaw_angle_deg']:.2f}°, "
f"forward: {debug_info['forward_movement']:.3f})")
# 运动段落
print(f"运动段落:")
for i, segment in enumerate(analysis['motion_segments']):
print(f" 段落{i+1}: {segment['class']} (帧 {segment['start_frame']}-{segment['end_frame']}, 持续 {segment['duration']} 帧)")
# 🔧 确定主要运动类型
dominant_class = max(class_dist.items(), key=lambda x: x[1])
dominant_class_name = dominant_class[0]
dominant_percentage = dominant_class[1] / analysis['total_frames'] * 100
print(f"主要运动类型: {dominant_class_name} ({dominant_percentage:.1f}%)")
# 将样本添加到对应类别
class_samples[dominant_class_name].append({
'name': item,
'percentage': dominant_percentage,
'analysis': analysis
})
sample_count += 1
except Exception as e:
print(f"❌ 处理样本 {item} 时出错: {e}")
print("\n" + "="*60)
print("=== 按类别分组的样本统计(基于相对于reference的变化)===")
# 🔧 按类别输出样本列表
for class_name in ['forward', 'backward', 'left_turn', 'right_turn']:
samples = class_samples[class_name]
print(f"\n🔸 {class_name.upper()} 类样本 (共 {len(samples)} 个):")
if samples:
# 按主要类别占比排序
samples.sort(key=lambda x: x['percentage'], reverse=True)
for i, sample_info in enumerate(samples, 1):
print(f" {i:2d}. {sample_info['name']} ({sample_info['percentage']:.1f}%)")
# 显示详细的段落信息
segments = sample_info['analysis']['motion_segments']
segment_summary = []
for seg in segments:
if seg['duration'] >= 2: # 只显示持续时间>=2帧的段落
segment_summary.append(f"{seg['class']}({seg['duration']})")
if segment_summary:
print(f" 段落: {' -> '.join(segment_summary)}")
else:
print(" (无样本)")
# 🔧 统计总体模式
print(f"\n" + "="*60)
print("=== 总体统计 ===")
total_forward = sum(a['class_distribution']['forward'] for a in all_analyses)
total_backward = sum(a['class_distribution']['backward'] for a in all_analyses)
total_left_turn = sum(a['class_distribution']['left_turn'] for a in all_analyses)
total_right_turn = sum(a['class_distribution']['right_turn'] for a in all_analyses)
total_frames = total_forward + total_backward + total_left_turn + total_right_turn
print(f"总样本数: {len(all_analyses)}")
print(f"总帧数: {total_frames}")
print(f"Forward: {total_forward} 帧 ({total_forward/total_frames*100:.1f}%)")
print(f"Backward: {total_backward} 帧 ({total_backward/total_frames*100:.1f}%)")
print(f"Left Turn: {total_left_turn} 帧 ({total_left_turn/total_frames*100:.1f}%)")
print(f"Right Turn: {total_right_turn} 帧 ({total_right_turn/total_frames*100:.1f}%)")
# 🔧 样本分布统计
print(f"\n按主要类型的样本分布:")
for class_name in ['forward', 'backward', 'left_turn', 'right_turn']:
count = len(class_samples[class_name])
percentage = count / len(all_analyses) * 100 if all_analyses else 0
print(f" {class_name}: {count} 样本 ({percentage:.1f}%)")
return all_analyses, class_samples
def calculate_relative_rotation(current_rotation, reference_rotation):
"""计算相对旋转四元数"""
q_current = torch.tensor(current_rotation, dtype=torch.float32)
q_ref = torch.tensor(reference_rotation, dtype=torch.float32)
# 计算参考旋转的逆 (q_ref^-1)
q_ref_inv = torch.tensor([q_ref[0], -q_ref[1], -q_ref[2], -q_ref[3]])
# 四元数乘法计算相对旋转: q_relative = q_ref^-1 * q_current
w1, x1, y1, z1 = q_ref_inv
w2, x2, y2, z2 = q_current
relative_rotation = torch.tensor([
w1 * w2 - x1 * x2 - y1 * y2 - z1 * z2,
w1 * x2 + x1 * w2 + y1 * z2 - z1 * y2,
w1 * y2 - x1 * z2 + y1 * w2 + z1 * x2,
w1 * z2 + x1 * y2 - y1 * x2 + z1 * w2
])
return relative_rotation
if __name__ == "__main__":
dataset_path = "/share_zhuyixuan05/zhuyixuan05/nuscenes_video_generation_2"
print("开始详细分析pose分类(基于相对于reference的变化)...")
all_analyses, class_samples = analyze_turning_patterns_detailed(dataset_path, num_samples=4000)
print(f"\n🎉 分析完成! 共处理 {len(all_analyses)} 个样本") |