今天在使用ICL-NUIM数据集做点云配准测试,先用深度图生成了点云模型,然后把两个点云模型配准,由于数据集自带了gt位姿坐标,所以顺便把这个坐标转化成位姿变换矩阵的形式,结果发现转换玩的点云完全不齐!

真是奇了怪了,我的四元数转位姿变换矩阵的方法是用了Eigen自带的方法,应该没有问题。(如下图)

然后相机内参也用的数据集的内参,但是怎么就配不起来呢,总不能是数据集自带的gt位姿有误吧?

求大伙解答!急
!
今天在使用ICL-NUIM数据集做点云配准测试,先用深度图生成了点云模型,然后把两个点云模型配准,由于数据集自带了gt位姿坐标,所以顺便把这个坐标转化成位姿变换矩阵的形式,结果发现转换玩的点云完全不齐!



求大伙解答!急
!
晚上好🌙🌙🌙
本答案参考通义千问
你遇到的问题是使用 ICL-NUIM 数据集进行点云配准时,虽然已经正确生成了点云模型并尝试将它们对齐,但最终的配准结果却完全不匹配。这确实是一个常见但复杂的问题,可能涉及多个方面的原因。
重点:
- 确保你使用的是正确的 相机内参矩阵(如
fx,fy,cx,cy)。- 深度图的单位是否为米?有些数据集可能用毫米,需要转换。
- 点云的坐标系是否一致?比如是否是右手坐标系?
[R | t],即先旋转后平移。重点:
- 如果你的点云是基于 相机坐标系 生成的,那么配准时应该使用 从世界到相机的变换矩阵 来将点云从一个视角变换到另一个视角。
- 如果你错误地使用了 相机到世界 的变换矩阵,那么点云会“翻转”或“错位”。
重点:
- 不建议直接怀疑数据集的 GT 位姿,除非你有明确的证据(例如:多个不同算法都失败)。
以下是详细的步骤和代码示例:
import numpy as np
import cv2
import os
from pyntcloud import PyntCloud
import open3d as o3d
import matplotlib.pyplot as plt
# 设置路径
data_dir = "path/to/icl-nuim"
scene_name = "livingroom1"
depth_path = os.path.join(data_dir, scene_name, "depth", "00000.png")
rgb_path = os.path.join(data_dir, scene_name, "rgb", "00000.png")
gt_pose_path = os.path.join(data_dir, scene_name, "gt.txt")
# 读取深度图(假设是16-bit PNG)
depth_img = cv2.imread(depth_path, -1)
depth_img = depth_img.astype(np.float32) / 1000.0 # 转换为米(假设单位是毫米)
# 相机内参(根据数据集文档)
fx = 481.207
fy = 480.591
cx = 319.5
cy = 239.5
# 生成点云
h, w = depth_img.shape
points = []
for v in range(h):
for u in range(w):
z = depth_img[v, u]
if z > 0:
x = (u - cx) * z / fx
y = (v - cy) * z / fy
points.append([x, y, z])
point_cloud = np.array(points)
# 读取 GT 位姿(假设格式为 [tx, ty, tz, qx, qy, qz, qw])
with open(gt_pose_path, 'r') as f:
lines = f.readlines()
for line in lines:
parts = line.strip().split()
if len(parts) == 8:
tx, ty, tz, qx, qy, qz, qw = map(float, parts)
break
# 使用 Eigen 的四元数转变换矩阵(Python 中可以用 scipy 或其他库)
from scipy.spatial.transform import Rotation as R
quat = np.array([qx, qy, qz, qw])
rotation = R.from_quat(quat)
R_mat = rotation.as_matrix()
t_vec = np.array([tx, ty, tz])
# 构造变换矩阵
T_gt = np.eye(4)
T_gt[:3, :3] = R_mat
T_gt[:3, 3] = t_vec
# 将点云转换为齐次坐标
homogeneous_points = np.hstack((point_cloud, np.ones((len(point_cloud), 1))))
# 应用变换矩阵
transformed_points = T_gt @ homogeneous_points.T
transformed_points = transformed_points[:3, :].T
# 可视化
pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(transformed_points)
o3d.visualization.draw_geometries([pcd])
import open3d as o3d
# 假设你有两个点云 A 和 B
# 使用 Open3D 的 ICP 算法
reg_p2p = o3d.pipelines.registration.registration_icp(
pcd_a, pcd_b,
max_correspondence_distance=0.05,
estimation_method=o3d.pipelines.registration.TransformationEstimationPointToPlane(),
criteria=o3d.pipelines.registration.RANSACConvergenceCriteria(100000, 0.999)
)
# 应用变换
final_transform = reg_p2p.transformation
| 问题 | 解决方案 | |------|----------| | 点云不对齐 | 检查相机内参、深度图单位、点云坐标系一致性 | | 四元数转矩阵错误 | 确认旋转方向(相机到世界 vs 世界到相机) | | 配准结果差 | 使用 ICP 算法进行优化,检查点云密度和噪声 | | 数据集 GT 有问题 | 先排除自己的实现问题,再怀疑数据集 |
| 关键点 | 说明 | |--------|------| | 点云生成 | 必须使用正确的内参和深度单位 | | 位姿转换 | 注意四元数的方向和变换矩阵的构造 | | 配准方法 | 推荐使用 ICP 算法自动对齐 | | 调试建议 | 先手动验证,再自动化 |
如果你愿意提供具体的代码片段或图像,我可以进一步帮助你定位问题!希望这些信息对你有帮助!