首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Open3D -裁剪具有多边形体积的点云

Open3D -裁剪具有多边形体积的点云
EN

Stack Overflow用户
提问于 2020-04-17 18:58:31
回答 3查看 3.5K关注 0票数 1

所有人,

我想从点云中裁剪和保存一个区域,然后保存它。

我有BBox坐标(maxx,maxy,minx,miny),它们是点云的MaxP和MinP,想要把它做成一个多边形。使用bbox_to_Polygon(MaxP,MinP),BBox坐标被转换为角点。这些应该用来创建两个多边形。在此基础上,我用pyny3D做了一个Polyhedron

我想,现在我可以给open3d.visualization.SelectionPolygonVolume()提供一个卷了。我不想使用Open3d文档Crop from Cloud中描述的JSON文件。所以我找到了这个How to Create a open3d.visualization.SelectionPolygonVolume Object Without Loading a json Filel

为什么是orthogonal_axis="Y"?为什么不只使用"Z"-axis呢?在example of JSON-File中,Y值为0。我建议是因为orthogonal_axis="Y",但我不明白为什么?难道我们不需要一个PolygonVolume吗?

如果能帮上忙我会很感激。

我正在使用Google Colab和Jupyter Notebook Python 3.6

代码语言:javascript
复制
#Vertics Poyhedrol to create a PolygonVolume
bounding_polygon = np.array([

#Vertics Polygon 1
        [488.8989868164062, 612.208984375, 286.5320129394531],
        [485.114990234375, 612.208984375, 286.5320129394531],
        [485.114990234375, 605.0880126953125, 286.5320129394531],
        [488.8989868164062, 605.0880126953125, 286.5320129394531],
#Vertics Polygon2
        [488.89898681640625, 612.208984375, 291.6619873046875], 
        [485.114990234375, 612.208984375, 291.6619873046875], 
        [485.114990234375, 605.0880126953125, 291.6619873046875],
        [488.89898681640625, 605.0880126953125, 291.6619873046875]]).astype("float64") 


vol = o3d.visualization.SelectionPolygonVolume()
vol.orthogonal_axis = "Y"
vol.axis_max = 500
vol.axis_min = 700
vol.bounding_polygon = o3d.utility.Vector3dVector(bounding_polygon)

comp = vol.crop_point_cloud(pcd)
comp

#Since I took the MaxP and MinP of the Pointcloud as BBCoords I would expect the same number of points. But I get this:
#`geometry::PointCloud with 0 points`

下面是完整的代码

代码语言:javascript
复制
import numpy as np
import pyny3d
import pyny3d.geoms as pyny
import open3d as o3d
from open3d import JVisualizer

path_incloud = ('/gdrive/My Drive/Colab Notebooks/Georeferenzierung/BildGeoreferenzieren/PointCloud/PointCloudFormats/Kranfundament - Cloud.ply')
pcd = o3d.io.read_point_cloud(path_incloud)
print("Input Cloud:", pcd)

visualizer = JVisualizer()
visualizer.add_geometry(pcd)
visualizer.show()

def bbox_to_Polygon(MaxP,MinP):


      p1= [MaxP[0], MaxP[1], MinP[2]]
      p2= [MaxP[0],MinP[1],MinP[2]]
      p3= [MinP[0],MaxP[1],MinP[2]]
      p4= MinP
      p5= MaxP
      p6= [MinP[0],MaxP[1],MaxP[2]]
      p7= [MinP[0],MinP[1],MaxP[2]]
      p8= [MaxP[0],MinP[1], MaxP[2]]

      listPoints1 = [p1,p3,p4,p2]
      print(listPoints1)

      listPoints2 = [p5,p6,p7,p8]
      print(listPoints2)
      return  listPoints1,listPoints2

MaxP = MaxPoint_PointCloud 
MinP = MinPoint_PointCloud

listPointsPoly1 , listPointsPoly2  = bbox_to_Polygon(MaxP= MaxP, MinP=MinP)

poly1 = pyny.Polygon(np.array(listPoints1))
poly2 = pyny.Polygon(np.array(listPoints2))

poly1.plot()
poly2.plot()

polyhedron = pyny.Polyhedron.by_two_polygons(poly1, poly2)

polyhedron.plot('b')

MaxP = MaxPoint_PointCloud 
MinP = MinPoint_PointCloud

#Vertics Poyhedrol to create a PolygonVolume
bounding_polygon = np.array([
#Vertics Polygon 1
        [488.8989868164062, 612.208984375, 286.5320129394531],
        [485.114990234375, 612.208984375, 286.5320129394531],
        [485.114990234375, 605.0880126953125, 286.5320129394531],
        [488.8989868164062, 605.0880126953125, 286.5320129394531],
#Vertics Polygon2
    [488.89898681640625, 612.208984375, 291.6619873046875], 
    [485.114990234375, 612.208984375, 291.6619873046875], 
    [485.114990234375, 605.0880126953125, 291.6619873046875],
    [488.89898681640625, 605.0880126953125, 291.6619873046875]]).astype("float64") 


vol = o3d.visualization.SelectionPolygonVolume()
vol.orthogonal_axis = "Y"
vol.axis_max = 1000
vol.axis_min = -1000
vol.bounding_polygon = o3d.utility.Vector3dVector(bounding_polygon)

comp = vol.crop_point_cloud(pcd)
print("Cropped Cloud",comp)
EN

回答 3

Stack Overflow用户

发布于 2020-11-19 13:33:36

这篇文章帮助我在长方体的边界内裁剪了一个点云。我也经常遇到使用vol.crop_point_cloud(pcd)geometry::PointCloud with 0 points,无法让它工作,但我找到了一个不同的解决方案。

我最终引用此PR #1218来使用open3d.geometry.OrientedBoundingBox长方体体积来裁剪点云。下面的代码在start_position周围创建了一个200m x 200m的“瓦片”长方体,它对应于点云内的ego车辆起始姿势,并过滤仅位于瓦片内的点。

代码语言:javascript
复制
import json
import numpy as np
import open3d as o3d

CUBOID_EXTENT_METERS = 200

METERS_BELOW_START = 5
METERS_ABOVE_START = 30

def main():
  ## Point Cloud
  points = np.array([
    ## These points lie inside the cuboid
    [-2770.94365061042, 722.0595600050154, -20.004812609192445],
    [-2755.94365061042, 710.0595600050154, -20.004812609192445],
    [-2755.94365061042, 710.0595600050154, -15.004812609192445],

    ## These points lie outside the cuboid
    [-2755.94365061042 + CUBOID_EXTENT_METERS, 710.0595600050154, -15.004812609192445],
    [-2755.94365061042, 710.0595600050154 + CUBOID_EXTENT_METERS, -15.004812609192445],
  ]).reshape([-1, 3])

  point_cloud = o3d.geometry.PointCloud()
  point_cloud.points = o3d.utility.Vector3dVector(points)

  ## Start point here corresponds to an ego vehicle position start in a point cloud
  start_position = {'x': -2755.94365061042, 'y': 722.0595600050154, 'z': -20.004812609192445}
  cuboid_points = getCuboidPoints(start_position)

  points = o3d.utility.Vector3dVector(cuboid_points)
  oriented_bounding_box = o3d.geometry.OrientedBoundingBox.create_from_points(points)
  point_cloud_crop = point_cloud.crop(oriented_bounding_box)

  # View original point cloud with the cuboid, all 5 points present
  o3d.visualization.draw_geometries([point_cloud, oriented_bounding_box])

  # View cropped point cloud with the cuboid, only 3 points present
  o3d.visualization.draw_geometries([point_cloud_crop, oriented_bounding_box])

def getCuboidPoints(start_position):
  return np.array([
    # Vertices Polygon1
    [start_position['x'] + (CUBOID_EXTENT_METERS / 2), start_position['y'] + (CUBOID_EXTENT_METERS / 2), start_position['z'] + METERS_ABOVE_START], # face-topright
    [start_position['x'] - (CUBOID_EXTENT_METERS / 2), start_position['y'] + (CUBOID_EXTENT_METERS / 2), start_position['z'] + METERS_ABOVE_START], # face-topleft
    [start_position['x'] - (CUBOID_EXTENT_METERS / 2), start_position['y'] - (CUBOID_EXTENT_METERS / 2), start_position['z'] + METERS_ABOVE_START], # rear-topleft
    [start_position['x'] + (CUBOID_EXTENT_METERS / 2), start_position['y'] - (CUBOID_EXTENT_METERS / 2), start_position['z'] + METERS_ABOVE_START], # rear-topright

    # Vertices Polygon 2
    [start_position['x'] + (CUBOID_EXTENT_METERS / 2), start_position['y'] + (CUBOID_EXTENT_METERS / 2), start_position['z'] - METERS_BELOW_START],
    [start_position['x'] - (CUBOID_EXTENT_METERS / 2), start_position['y'] + (CUBOID_EXTENT_METERS / 2), start_position['z'] - METERS_BELOW_START],
    [start_position['x'] - (CUBOID_EXTENT_METERS / 2), start_position['y'] - (CUBOID_EXTENT_METERS / 2), start_position['z'] - METERS_BELOW_START],
    [start_position['x'] + (CUBOID_EXTENT_METERS / 2), start_position['y'] - (CUBOID_EXTENT_METERS / 2), start_position['z'] - METERS_BELOW_START],
  ]).astype("float64") 

if __name__ == '__main__':
  main()
票数 2
EN

Stack Overflow用户

发布于 2020-06-09 13:43:56

您可以选择任何轴作为orthogonal_axis。例如,如果选择Z,则使用Z=0使用一组点定义多边形。然后设置Z最小值和最大值,就像使用Z最小值和最大值之间的多边形挤出体积一样。希望这能有所帮助。

票数 0
EN

Stack Overflow用户

发布于 2020-12-18 08:32:00

以下是演示如何使用顶点的np.array裁剪点云的简化版本:

代码语言:javascript
复制
"""
corners = [[ 5.31972845 -3.21384387  0.30217625]
 [ 5.34483288 -1.13804348  0.29917539]
 [ 7.69983939 -1.16651864  0.30329364]
 [ 7.67473496 -3.24231903  0.3062945 ]
 [ 5.31845904 -3.21276837  1.03551451]
 [ 5.34356348 -1.13696798  1.03251366]
 [ 7.69856999 -1.16544314  1.03663191]
 [ 7.67346556 -3.24124353  1.03963277]]
"""
corners = np.array(...)

# Convert the corners array to have type float64
bounding_polygon = corners.astype("float64")

# Create a SelectionPolygonVolume
vol = o3d.visualization.SelectionPolygonVolume()

# You need to specify what axis to orient the polygon to.
# I choose the "Y" axis. I made the max value the maximum Y of
# the polygon vertices and the min value the minimum Y of the
# polygon vertices.
vol.orthogonal_axis = "Y"
vol.axis_max = np.max(bounding_polygon[:, 1])
vol.axis_min = np.min(bounding_polygon[:, 1])

# Set all the Y values to 0 (they aren't needed since we specified what they
# should be using just vol.axis_max and vol.axis_min).
bounding_polygon[:, 1] = 0

# Convert the np.array to a Vector3dVector
vol.bounding_polygon = o3d.utility.Vector3dVector(bounding_polygon)

# Crop the point cloud using the Vector3dVector
cropped_pcd = vol.crop_point_cloud(pcd)

# Get a nice looking bounding box to display around the newly cropped point cloud
# (This part is optional and just for display purposes)
bounding_box = cropped_pcd.get_axis_aligned_bounding_box()
bounding_box.color = (1, 0, 0)

# Draw the newly cropped PCD and bounding box
o3d.visualization.draw_geometries([cropped_pcd, bounding_box],
                                  zoom=2,
                                  front=[5, -2, 0.5],
                                  lookat=[7.67473496, -3.24231903,  0.3062945],
                                  up=[1.0, 0.0, 0.0])

前面的示例:

示例之后(这是来自云中心的蓝色大块点):

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61269980

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档