Files
openMVS/libs/MVS/utils/get_world_point.py
T
2025-07-21 10:09:12 +08:00

118 lines
3.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'''
获取Mesh的深度图
required:
- open3d
- numpy
- numba
'''
import open3d as o3d
import numpy as np
from numba import njit
@njit
def _process_all_points(Z, width, height, cx, cy, fx, fy, c2w):
"""JIT优化的所有点处理函数"""
# 手动创建像素网格(替代np.meshgrid)
u = np.zeros((height, width), dtype=np.float64)
v = np.zeros((height, width), dtype=np.float64)
for y in range(height):
for x in range(width):
u[y, x] = x
v[y, x] = y
# 创建输出数组
Z_all = np.zeros_like(Z)
# 手动处理有效点
for y in range(height):
for x in range(width):
if Z[y, x] > 0 and Z[y, x] < 1e9 and not np.isnan(Z[y, x]):
Z_all[y, x] = Z[y, x]
else:
Z_all[y, x] = -10000
# 计算所有点的3D坐标
X_all = (u - cx) * Z_all / fx
Y_all = (v - cy) * Z_all / fy
# 创建齐次坐标
points_3d = np.zeros((height * width, 4))
points_3d[:, 0] = X_all.reshape(-1)
points_3d[:, 1] = Y_all.reshape(-1)
points_3d[:, 2] = Z_all.reshape(-1)
points_3d[:, 3] = 1.0
# 坐标变换
return points_3d @ c2w.T
@njit
def _process_valid_points(Z, width, height, cx, cy, fx, fy, c2w):
"""JIT优化的有效点处理函数"""
# 首先计算有效点的数量
valid_count = 0
for y in range(height):
for x in range(width):
if Z[y, x] > 0 and Z[y, x] < 1e9 and not np.isnan(Z[y, x]):
valid_count += 1
# 创建输出数组
X_valid = np.zeros(valid_count)
Y_valid = np.zeros(valid_count)
Z_valid = np.zeros(valid_count)
# 填充有效点数据
idx = 0
for y in range(height):
for x in range(width):
if Z[y, x] > 0 and Z[y, x] < 1e9 and not np.isnan(Z[y, x]):
Z_valid[idx] = Z[y, x]
X_valid[idx] = (x - cx) * Z_valid[idx] / fx
Y_valid[idx] = (y - cy) * Z_valid[idx] / fy
idx += 1
# 创建齐次坐标
points_3d = np.zeros((valid_count, 4))
points_3d[:, 0] = X_valid
points_3d[:, 1] = Y_valid
points_3d[:, 2] = Z_valid
points_3d[:, 3] = 1.0
# 坐标变换
return points_3d @ c2w.T
def get_world_points(depth_map: o3d.geometry.Image, K: np.ndarray, c2w: np.ndarray, all_point: bool = False) -> np.ndarray:
'''
获取深度图对应的世界坐标点云
param:
depth_map: 深度图
K: 相机内参矩阵
c2w: 相机坐标系到世界坐标系的变换矩阵
all_point: 是否返回所有点(包括无效点)
return:
np.ndarray: 点云坐标(世界坐标系)
- 当all_point=False时:只包含有效深度值的点云
- 当all_point=True时:包含所有点的点云,无效点深度值设为10000
'''
# 转换为numpy数组
Z = np.asarray(depth_map)
height, width = Z.shape
# 获取内参
fx, fy = K[0, 0], K[1, 1]
cx, cy = K[0, 2], K[1, 2]
# 确保数据类型兼容性(Numba要求)
Z = Z.astype(np.float64)
c2w = c2w.astype(np.float64)
if all_point:
return _process_all_points(Z, width, height, cx, cy, fx, fy, c2w)
else:
return _process_valid_points(Z, width, height, cx, cy, fx, fy, c2w)