提问人:bhomaidan90 提问时间:10/25/2023 最后编辑:bhomaidan90 更新时间:10/26/2023 访问量:79
如何从深度图像和边界框创建 OrientedBoundingBox
How to create an OrientedBoundingBox from Depth image and bounding box
问:
我想使用分段蒙版(矩形)和深度图像裁剪 poincloud,(我可以认为现在没有旋转)。
import open3d as o3d
## dummy pointcloud
demo_icp_pcds = o3d.data.DemoICPPointClouds()
pcd = o3d.io.read_point_cloud(demo_icp_pcds.paths[0])
## dummy depth mask
depth_mask = np.ones((640, 480), dtype=np.uint8)
## Crop PCD
## mask boundaries: [(xmin, xmax), (y_min, y_max)]
rect = [(20, 50), (70, 75)]
o_box = o3d.geometry.OrientedBoundingBox()
o_box.center = [0.0, 0.0, 0.0]
o_box.extent = [1.0, 2.0, 3.0]
o_box.R = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
cropped_pcd = pcd.crop(o_box)
我想将矩形 (x, y) 和深度 z 的信息提供给 orietned 边界框。谁能告诉我怎么做?谢谢。
答:
0赞
bhomaidan90
10/26/2023
#1
这是我的解决方案供参考:
def obbs_from_depth_mask(
depth: np.ndarray, rects: List[List]
) -> List[o3d.geometry.OrientedBoundingBox]:
obbs = []
for rect in rects:
obb = o3d.geometry.OrientedBoundingBox()
## [xmin, xmax, ymin, ymax]
x_min = rect[0]
y_min = rect[2]
z_min = depth[y_min, x_min]
##
x_max = rect[1]
y_max = rect[3]
z_max = depth[y_max, x_max]
center = [
(x_min + x_max) / 2,
(y_min + y_max) / 2,
(z_min + z_max) / 2,
]
extent = [
math.abs(x_max - x_min),
math.abs(y_max - y_min),
math.abs(z_max - z_min),
]
## Get rotation
P1= np.array([x_min, y_min, z_min])
P2= np.array([x_max, y_max, z_max])
D = P2 - P1
U = D / np.linalg.norm(D)
X = np.array([1, 0, 0])
V = np.cross(U, X)
if np.linalg.norm(V) == 0:
X = np.array([0, 1, 0])
V = np.cross(U, X)
rotation_matrix = np.column_stack((U, V, X))
obb.center = center
obb.extent = extent
obb.R = rotation_matrix
obbs.append(obb)
return obbs
评论
1赞
saurabheights
10/26/2023
您应该删除此代码。 不正确。并使用 obb 等类的构造函数正确初始化,以后不要更改这些值。obb.extent = half_extent
1赞
saurabheights
10/26/2023
另外,我希望不是像素位置,而是相机坐标系中反向投影位置的位置。xmin, xmax, ymin, ymax
0赞
bhomaidan90
10/26/2023
@saurabheights感谢您的注意,我已经将其修复到全部而不是一半
1赞
saurabheights
10/26/2023
#2
如果您的裁剪体积是长方体并与 x,y,z 轴对齐的轴对齐,则使用轴对齐的边界框进行裁剪要容易得多。无论如何,以旋转为标识的定向边界框是等价的。有关裁剪示例,请参阅以下代码。
import open3d as o3d
lower_b = [-2.0, -2.0, 1.0]
upper_b = [4.0, 2.0, 2.0]
bbox = o3d.geometry.AxisAlignedBoundingBox(min_bound=lower_b, max_bound=upper_b)
bbox.color = [0.46, 0.32, 1.0]
print(bbox, bbox.get_extent(), bbox.volume(), bbox.color)
ply_point_cloud = o3d.data.PLYPointCloud()
pcd = o3d.io.read_point_cloud(ply_point_cloud.path)
origin = o3d.geometry.TriangleMesh.create_coordinate_frame(size=1, origin=[0, 0, 0])
o3d.visualization.draw_geometries([origin, bbox, pcd],
zoom=0.3412,
front=[0.4257, -0.2125, -0.8795],
lookat=[2.6172, 2.0475, 1.532],
up=[-0.0694, -0.9768, 0.2024])
pcd1 = pcd.crop(bbox)
o3d.visualization.draw_geometries([origin, bbox, pcd1],
zoom=0.3412,
front=[0.4257, -0.2125, -0.8795],
lookat=[2.6172, 2.0475, 1.532],
up=[-0.0694, -0.9768, 0.2024])
obbox = o3d.geometry.OrientedBoundingBox(center=[2.0, 1.0, 1.5], extent=[1.0, 2.0, 3.0],
R=[[1, 0, 0], [0, 1, 0], [0, 0, 1]])
pcd2 = pcd.crop(obbox)
obbox.color = [0.46, 0.32, 1.0]
o3d.visualization.draw_geometries([origin, obbox, pcd],
zoom=0.3412,
front=[0.4257, -0.2125, -0.8795],
lookat=[2.6172, 2.0475, 1.532],
up=[-0.0694, -0.9768, 0.2024])
o3d.visualization.draw_geometries([origin, obbox, pcd2],
zoom=0.3412,
front=[0.4257, -0.2125, -0.8795],
lookat=[2.6172, 2.0475, 1.532],
up=[-0.0694, -0.9768, 0.2024])
另外,请遵循 2 个提示:-
- 添加坐标轴,用于可视化 x、y、z 轴。XYZ = RGB,即红轴为 X。
- 展示台的背景是白色的,不幸的是,边界框的默认颜色是白色。我正在尝试改变这一点,但最终决定将取决于 repo 维护者。
此外,如果使用轴对齐的边界框,请小心。确保在所有三个轴上都min_bound < max_bound。这已经由我最近的 PR 修复 - https://github.com/isl-org/Open3D/pull/6444,但是更改仅在开发版本中可用。
评论
o3d.geometry.OrientedBoundingBox(depth_mask)
o3d.geometry.OrientedBoundingBox
o3d.geometry.AxisAlignedBoundingBox