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)} 个样本")