File size: 6,271 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 |
import torch
import os
import os
import json
import torch
import numpy as np
from scipy.spatial.transform import Rotation as R
import pdb
def compute_relative_pose_matrix2(
pose_a,
pose_b
) -> np.ndarray:
"""
计算两个相机姿态(7元数组)之间的相对位姿,输出3×4相机矩阵 [R_rel | t_rel]
数学定义:相对位姿描述“从姿态A到姿态B的变换”,即:
- 若点P在姿态A的相机坐标系下坐标为P_A,在姿态B的相机坐标系下坐标为P_B,
则满足 P_B = R_rel @ P_A + t_rel(R_rel为相对旋转矩阵,t_rel为相对平移向量)
参数:
pose_a: 参考姿态A,形状(7,)的数组/list,格式[tx_a, ty_a, tz_a, qx_a, qy_a, qz_a, qw_a]
- tx_a/ty_a/tz_a: 姿态A在世界坐标系的位置(平移向量)
- qx_a/qy_a/qz_a/qw_a: 姿态A的朝向(单位四元数,右手坐标系)
pose_b: 目标姿态B,格式与pose_a完全一致
返回:
3×4的相对位姿相机矩阵,前3列是3×3相对旋转矩阵R_rel,第4列是3×1相对平移向量t_rel
异常:
ValueError: 若输入姿态形状/格式不正确,或四元数非单位四元数
"""
# --------------------------
# 1. 输入校验(确保数据格式正确)
# --------------------------
# 转换为numpy数组并检查形状
pose_a = np.asarray(pose_a, dtype=np.float64)
pose_b = np.asarray(pose_b, dtype=np.float64)
if pose_a.shape != (7,):
raise ValueError(f"姿态A需为(7,)数组,实际输入形状{pose_a.shape}")
if pose_b.shape != (7,):
raise ValueError(f"姿态B需为(7,)数组,实际输入形状{pose_b.shape}")
# 分离平移向量和四元数
t_a = pose_a[:3] # 姿态A的世界坐标:[tx_a, ty_a, tz_a]
q_a = pose_a[3:] # 姿态A的四元数:[qx_a, qy_a, qz_a, qw_a]
t_b = pose_b[:3] # 姿态B的世界坐标
q_b = pose_b[3:] # 姿态B的四元数
# 检查四元数是否为单位四元数(避免旋转计算错误)
q_a_norm = np.linalg.norm(q_a)
q_b_norm = np.linalg.norm(q_b)
if not np.isclose(q_a_norm, 1.0, atol=1e-4):
raise ValueError(f"姿态A的四元数非单位四元数,模长为{q_a_norm:.6f}(需接近1.0)")
if not np.isclose(q_b_norm, 1.0, atol=1e-4):
raise ValueError(f"姿态B的四元数非单位四元数,模长为{q_b_norm:.6f}(需接近1.0)")
# --------------------------
# 2. 计算相对旋转矩阵 R_rel
# --------------------------
# 将四元数转换为Rotation对象(scipy自动处理右手坐标系)
rot_a = R.from_quat(q_a) # 姿态A的旋转矩阵(世界→A相机的旋转)
rot_b = R.from_quat(q_b) # 姿态B的旋转矩阵(世界→B相机的旋转)
# 相对旋转 = 姿态B的旋转 × 姿态A旋转的逆(单位旋转矩阵的逆=转置)
# 数学逻辑:R_rel 描述“A相机坐标系→B相机坐标系”的旋转
rot_rel = rot_b * rot_a.inv()
R_rel = rot_rel.as_matrix() # 转换为3×3矩阵, dtype=np.float64
# --------------------------
# 3. 计算相对平移向量 t_rel
# --------------------------
# 数学推导:t_rel = R_rel @ (-rot_a.inv() @ t_a) + (rot_b.inv() @ t_b)
# 简化后:t_rel = rot_a.inv().as_matrix().T @ (t_b - t_a)
# 物理意义:在A相机坐标系下,B相机相对于A相机的位置
R_a_T = rot_a.inv().as_matrix().T # 姿态A旋转矩阵的逆=转置(单位矩阵性质)
t_rel = R_a_T @ (t_b - t_a) # 3×1相对平移向量
# --------------------------
# 4. 组合为3×4相机矩阵
# --------------------------
# 拼接旋转矩阵(3×3)和平移向量(3×1),形成3×4矩阵
relative_cam_matrix = np.hstack([R_rel, t_rel.reshape(3, 1)])
return relative_cam_matrix
def compute_relative_pose_matrix(pose1, pose2):
"""
计算相邻两帧的相对位姿,返回3×4的相机矩阵 [R_rel | t_rel]
参数:
pose1: 第i帧的相机位姿,形状为(7,)的数组 [tx1, ty1, tz1, qx1, qy1, qz1, qw1]
pose2: 第i+1帧的相机位姿,形状为(7,)的数组 [tx2, ty2, tz2, qx2, qy2, qz2, qw2]
返回:
relative_matrix: 3×4的相对位姿矩阵,前3列是旋转矩阵R_rel,第4列是平移向量t_rel
"""
# 分离平移向量和四元数
t1 = pose1[:3] # 第i帧平移 [tx1, ty1, tz1]
q1 = pose1[3:] # 第i帧四元数 [qx1, qy1, qz1, qw1]
t2 = pose2[:3] # 第i+1帧平移
q2 = pose2[3:] # 第i+1帧四元数
# 1. 计算相对旋转矩阵 R_rel
rot1 = R.from_quat(q1) # 第i帧旋转
rot2 = R.from_quat(q2) # 第i+1帧旋转
rot_rel = rot2 * rot1.inv() # 相对旋转 = 后一帧旋转 × 前一帧旋转的逆
R_rel = rot_rel.as_matrix() # 转换为3×3矩阵
# 2. 计算相对平移向量 t_rel
R1_T = rot1.as_matrix().T # 前一帧旋转矩阵的转置(等价于逆)
t_rel = R1_T @ (t2 - t1) # 相对平移 = R1^T × (t2 - t1)
# 3. 组合为3×4矩阵 [R_rel | t_rel]
relative_matrix = np.hstack([R_rel, t_rel.reshape(3, 1)])
return relative_matrix
encoded_data = torch.load(
os.path.join('/share_zhuyixuan05/zhuyixuan05/spatialvid/fdb39216-0d15-5f0f-a78f-c599913a4a2e_0000600_0000900', "encoded_video.pth"),
weights_only=False,
map_location="cpu"
)
cam_data_ori = np.load('./poses.npy')
cam_data_seq_ori = cam_data_ori
print(cam_data_seq_ori.shape)
print('---------------------------')
cam_data = encoded_data['cam_emb']
cam_data_seq = cam_data_seq_ori #
cam_data_seq_inter = cam_data['extrinsic']
print(cam_data_seq_inter.shape)
keyframe_original_idx = list(range(10))
relative_cams = []
for idx in keyframe_original_idx:
cam_prev = cam_data_seq[idx]
cam_next = cam_data_seq[idx+1]
relative_cam = compute_relative_pose_matrix2(cam_prev,cam_next)
relative_cams.append(torch.as_tensor(relative_cam[:3,:]))
relative_cam = compute_relative_pose_matrix2(cam_data_seq_inter[0],cam_data_seq_inter[-1])
relative_cams.append(torch.as_tensor(relative_cam[:3,:]))
print(relative_cams[-1])
|