Open3D 網格操作

2021-02-19 一點雲手冊
網格

Open3D有一個名為TriangleMesh的三維三角形網格的數據結構。下面的代碼演示如何從ply 文件中讀取三角形網格並列印其頂點和三角形。

[2]:
print("Testing mesh in Open3D...")
mesh = o3dtut.get_knot_mesh()
print(mesh)
print('Vertices:')
print(np.asarray(mesh.vertices))
print('Triangles:')
print(np.asarray(mesh.triangles))


Testing mesh in Open3D...
TriangleMesh with 1440 points and 2880 triangles.
Vertices:
[[  4.51268387  28.68865967 -76.55680847]
[  7.63622284  35.52046967 -69.78063965]
[  6.21986008  44.22465134 -64.82303619]
...
[-22.12651634  31.28466606 -87.37570953]
[-13.91188431  25.4865818  -86.25827026]
[ -5.27768707  23.36245346 -81.43279266]]
Triangles:
[[   0   12   13]
[   0   13    1]
[   1   13   14]
...
[1438   11 1439]
[1439   11    0]
[1439    0 1428]]

類TriangleMesh 含有一些像 vertices 和triangles的數據變量。Open3D通過numpy提供對這些欄位的直接內存訪問。

可視化 3D 網格
[3]:
print("Try to render a mesh with normals (exist: " +
     str(mesh.has_vertex_normals()) + ") and colors (exist: " +
     str(mesh.has_vertex_colors()) + ")")
o3d.visualization.draw_geometries([mesh])
print("A mesh with no normals and no colors does not look good.")


Try to render a mesh with normals (exist: True) and colors (exist: False)


A mesh with no normals and no colors does not look good.

您可以旋轉和移動網格,但它是用統一的灰色繪製的,看起來不像「3d」的。原因是當前網格沒有頂點或面的法線。所以使用統一的顏色著色來代替更複雜的Phong著色。

曲面法線估計

讓我們用曲面法線繪製網格。

[4]:
print("Computing normal and rendering it.")
mesh.compute_vertex_normals()
print(np.asarray(mesh.triangle_normals))
o3d.visualization.draw_geometries([mesh])


Computing normal and rendering it.
[[ 0.79164373 -0.53951444  0.28674793]
[ 0.8319824  -0.53303008  0.15389681]
[ 0.83488162 -0.09250101  0.54260136]
...
[ 0.16269924 -0.76215917 -0.6266118 ]
[ 0.52755226 -0.83707495 -0.14489352]
[ 0.56778973 -0.76467734 -0.30476777]]


它使用mesh的成員函數 compute_vertex_normals和paint_uniform_color。

裁剪網格

我們通過直接操作網格的triangle和triangle_normals 數據欄位來刪除曲面的一半。這是通過numpy完成的。

[5]:
print("We make a partial mesh of only the first half triangles.")
mesh1 = copy.deepcopy(mesh)
mesh1.triangles = o3d.utility.Vector3iVector(
   np.asarray(mesh1.triangles)[:len(mesh1.triangles) // 2, :])
mesh1.triangle_normals = o3d.utility.Vector3dVector(
   np.asarray(mesh1.triangle_normals)[:len(mesh1.triangle_normals) // 2, :])
print(mesh1.triangles)
o3d.visualization.draw_geometries([mesh1])


We make a partial mesh of only the first half triangles.
std::vector<Eigen::Vector3i> with 1440 elements.
Use numpy.asarray() to access data.


網格上色

函數paint_uniform_color 使用統一的顏色繪製網格。顏色在RGB空間[0,1]範圍內。

[6]:
print("Painting the mesh")
mesh1.paint_uniform_color([1, 0.706, 0])
o3d.visualization.draw_geometries([mesh1])


Painting the mesh

網格屬性

三角網格有幾個可以用Open3D測試的屬性,其中一個重要的屬性是manifold屬性,我們可以用函數is_edge_manifold 測試三角形網格是否是edge manifold,用函數is_vertex_manifold判斷是否是頂點manifold。三角形網格是edge manifold,如果每個邊都是一個或兩個三角形的邊界。函數 is_edge_manifold帶有 bool 參數allow_boundary_edges 定義是否允許邊界邊。此外,如果頂點的star是 edge‐manifold 和 edge‐connected 就表示三角形是頂點manifold。例如兩個或多個面僅由一個頂點連接而不是由一個邊連接。

另一個性質是自相交的檢驗。如果網格中存在與另一個網格相交的三角形,則函數 is_self_intersecting返回 True。watertight網格可以定義為edge manifold、vertex manifold和不自交的網格。函數is_watertight 在Open3D中實現此檢查。

我們也可以測試三角形網格,如果它是可定向的,也就是說,當所有法線指向外部時就說三角形是可定向的。調用Open3D中相應的函數is_orientable.

下面的代碼針對這些屬性測試了許多三角形網格,並將結果可視化。Non-manifold邊顯示為紅色,邊界邊顯示為綠色,non-manifold頂點顯示為綠色點,自交三角形顯示為粉紅色。

[7]:
def check_properties(name, mesh):
   mesh.compute_vertex_normals()

   edge_manifold = mesh.is_edge_manifold(allow_boundary_edges=True)
   edge_manifold_boundary = mesh.is_edge_manifold(allow_boundary_edges=False)
   vertex_manifold = mesh.is_vertex_manifold()
   self_intersecting = mesh.is_self_intersecting()
   watertight = mesh.is_watertight()
   orientable = mesh.is_orientable()

   print(name)
   print(f" edge_manifold:         {edge_manifold}")
   print(f" edge_manifold_boundary: {edge_manifold_boundary}")
   print(f" vertex_manifold:       {vertex_manifold}")
   print(f" self_intersecting:     {self_intersecting}")
   print(f" watertight:             {watertight}")
   print(f" orientable:             {orientable}")

   geoms = [mesh]
   if not edge_manifold:
       edges = mesh.get_non_manifold_edges(allow_boundary_edges=True)
       geoms.append(o3dtut.edges_to_lineset(mesh, edges, (1, 0, 0)))
   if not edge_manifold_boundary:
       edges = mesh.get_non_manifold_edges(allow_boundary_edges=False)
       geoms.append(o3dtut.edges_to_lineset(mesh, edges, (0, 1, 0)))
   if not vertex_manifold:
       verts = np.asarray(mesh.get_non_manifold_vertices())
       pcl = o3d.geometry.PointCloud(
           points=o3d.utility.Vector3dVector(np.asarray(mesh.vertices)[verts]))
       pcl.paint_uniform_color((0, 0, 1))
       geoms.append(pcl)
   if self_intersecting:
       intersecting_triangles = np.asarray(
           mesh.get_self_intersecting_triangles())
       intersecting_triangles = intersecting_triangles[0:1]
       intersecting_triangles = np.unique(intersecting_triangles)
       print(" # visualize self-intersecting triangles")
       triangles = np.asarray(mesh.triangles)[intersecting_triangles]
       edges = [
           np.vstack((triangles[:, i], triangles[:, j]))
           for i, j in [(0, 1), (1, 2), (2, 0)]
      ]
       edges = np.hstack(edges).T
       edges = o3d.utility.Vector2iVector(edges)
       geoms.append(o3dtut.edges_to_lineset(mesh, edges, (1, 0, 1)))
   o3d.visualization.draw_geometries(geoms, mesh_show_back_face=True)
[8]:
check_properties('Knot', o3dtut.get_knot_mesh())
check_properties('Moebius', o3d.geometry.TriangleMesh.create_moebius(twists=1))
check_properties("non-manifold edge", o3dtut.get_non_manifold_edge_mesh())
check_properties("non-manifold vertex", o3dtut.get_non_manifold_vertex_mesh())
check_properties("open box", o3dtut.get_open_box_mesh())
check_properties("intersecting_boxes", o3dtut.get_intersecting_boxes_mesh())


Knot
 edge_manifold:          True
 edge_manifold_boundary: True
 vertex_manifold:        True
 self_intersecting:      False
 watertight:             True
 orientable:             True


Moebius
 edge_manifold:          True
 edge_manifold_boundary: False
 vertex_manifold:        True
 self_intersecting:      False
 watertight:             False
 orientable:             False

non-manifold edge
 edge_manifold:          False
 edge_manifold_boundary: False
 vertex_manifold:        True
 self_intersecting:      False
 watertight:             False
 orientable:             True

non-manifold vertex
 edge_manifold:          True
 edge_manifold_boundary: True
 vertex_manifold:        False
 self_intersecting:      False
 watertight:             False
 orientable:             True

open box
 edge_manifold:          True
 edge_manifold_boundary: False
 vertex_manifold:        True
 self_intersecting:      False
 watertight:             False
 orientable:             True

intersecting_boxes
 edge_manifold:          True
 edge_manifold_boundary: True
 vertex_manifold:        True
 self_intersecting:      True
 watertight:             False
 orientable:             True
 # visualize self-intersecting triangles

網格濾波

Open3D包含許多過濾網格的方法。在下面我們將展示如何使用3種已經實現的過濾器,來平滑加噪後的三角形網格。

均值濾波

最簡單的過濾器是平均過濾器。給定頂點 (v_i) 由相鄰頂點的平均值給出 (\mathcal{N})。

\begin{equation} v_i = \frac{v_i + \sum_{n \in \mathcal{N}} v_n}{|N| + 1} \,. \end{equation}

這個過濾器可以用來去噪網格,如下面的代碼所示。filter_smooth_simple函數中的number_of_iterations定義將過濾器應用於網格的迭代次數。

[9]:
print('create noisy mesh')
mesh_in = o3dtut.get_knot_mesh()
vertices = np.asarray(mesh_in.vertices)
noise = 5
vertices += np.random.uniform(0, noise, size=vertices.shape)
mesh_in.vertices = o3d.utility.Vector3dVector(vertices)
mesh_in.compute_vertex_normals()
o3d.visualization.draw_geometries([mesh_in])

print('filter with average with 1 iteration')
mesh_out = mesh_in.filter_smooth_simple(number_of_iterations=1)
mesh_out.compute_vertex_normals()
o3d.visualization.draw_geometries([mesh_out])

print('filter with average with 5 iterations')
mesh_out = mesh_in.filter_smooth_simple(number_of_iterations=5)
mesh_out.compute_vertex_normals()
o3d.visualization.draw_geometries([mesh_out])


create noisy mesh


filter with average with 1 iteration

filter with average with 5 iterations


拉普拉斯濾波

另一個重要的網格過濾器是定義為

其中,λ是濾波器的強度,wn是與相鄰頂點的距離相關的歸一化權重。

該濾波器由函數 filter_smooth_laplacian 實現,並帶有參數 number_of_iterations 和lambda。

[10]:
print('filter with Laplacian with 10 iterations')
mesh_out = mesh_in.filter_smooth_laplacian(number_of_iterations=10)
mesh_out.compute_vertex_normals()
o3d.visualization.draw_geometries([mesh_out])

print('filter with Laplacian with 50 iterations')
mesh_out = mesh_in.filter_smooth_laplacian(number_of_iterations=50)
mesh_out.compute_vertex_normals()
o3d.visualization.draw_geometries([mesh_out])


filter with Laplacian with 10 iterations

filter with Laplacian with 50 iterations

Taubin濾波器

均值濾波和拉普拉斯濾波的問題是它們導致三角形網格收縮。[Taubin1995] 表明,採用兩種不同λ參數的拉普拉斯濾波器可以防止網格收縮。該濾波器由函數 filter_smooth_taubin實現。

[11]:
print('filter with Taubin with 10 iterations')
mesh_out = mesh_in.filter_smooth_taubin(number_of_iterations=10)
mesh_out.compute_vertex_normals()
o3d.visualization.draw_geometries([mesh_out])

print('filter with Taubin with 100 iterations')
mesh_out = mesh_in.filter_smooth_taubin(number_of_iterations=100)
mesh_out.compute_vertex_normals()
o3d.visualization.draw_geometries([mesh_out])


filter with Taubin with 10 iterations

filter with Taubin with 100 iterations

採樣

Open3D包含從三角形網格中採樣點雲的函數。最簡單的方法sample_points_uniformly是基於三角形區域從三維曲面均勻採樣點。參數 number_of_points 定義從三角形曲面採樣的點數。

[12]:
mesh = o3d.geometry.TriangleMesh.create_sphere()
mesh.compute_vertex_normals()
o3d.visualization.draw_geometries([mesh])
pcd = mesh.sample_points_uniformly(number_of_points=500)
o3d.visualization.draw_geometries([pcd])

[13]:
mesh = o3dtut.get_bunny_mesh()
mesh.compute_vertex_normals()
o3d.visualization.draw_geometries([mesh])
pcd = mesh.sample_points_uniformly(number_of_points=500)
o3d.visualization.draw_geometries([pcd])

均勻採樣可以在曲面上生成點簇,而Poisson disk採樣方法可以均勻地分布曲面上的點。函數 sample_points_poisson_disk執行樣本消除。它從一個採樣點雲開始,去除點以滿足採樣條件。該方法支持兩個選項來提供初始點云:

默認情況下,通過參數init_factor:方法首先從網格中以init_factor x number_of_points 統一採樣一片點雲,並使用它進行消除。

可以提供一個點雲並將其傳遞給 sample_points_poisson_disk方法。然後,使用該點雲進行排除。

[14]:
mesh = o3d.geometry.TriangleMesh.create_sphere()
pcd = mesh.sample_points_poisson_disk(number_of_points=500, init_factor=5)
o3d.visualization.draw_geometries([pcd])

pcd = mesh.sample_points_uniformly(number_of_points=2500)
pcd = mesh.sample_points_poisson_disk(number_of_points=500, pcl=pcd)
o3d.visualization.draw_geometries([pcd])

[15]:
mesh = o3dtut.get_bunny_mesh()
pcd = mesh.sample_points_poisson_disk(number_of_points=500, init_factor=5)
o3d.visualization.draw_geometries([pcd])

pcd = mesh.sample_points_uniformly(number_of_points=2500)
pcd = mesh.sample_points_poisson_disk(number_of_points=500, pcl=pcd)
o3d.visualization.draw_geometries([pcd])

網格細分

在網格細分中,我們將每個三角形分成若干較小的三角形。最簡單的情況,就是我們計算每個三角形每邊的中點,然後將三角形分成四個較小的三角形。這是在subdivide_midpoint函數中實現的。三維曲面和區域保持不變,但頂點和三角形的數量會增加。參數number_of_iterations定義此過程應重複多少次。

[16]:
mesh = o3d.geometry.TriangleMesh.create_box()
mesh.compute_vertex_normals()
print(
f'The mesh has {len(mesh.vertices)} vertices and {len(mesh.triangles)} triangles'
)
o3d.visualization.draw_geometries([mesh], zoom=0.8, mesh_show_wireframe=True)
mesh = mesh.subdivide_midpoint(number_of_iterations=1)
print(
f'After subdivision it has {len(mesh.vertices)} vertices and {len(mesh.triangles)} triangles'
)
o3d.visualization.draw_geometries([mesh], zoom=0.8, mesh_show_wireframe=True)


The mesh has 8 vertices and 12 triangles

After subdivision it has 26 vertices and 48 triangles

Open3D 基於 [Loop1987] Open3D實現了另外一個細分方法。該方法基於 quartic box spline,它在任何地方生成連續的極限曲面 ,除非在非常頂點處,它們是 連續的。這將導致更平滑的角。

[17]:
mesh = o3d.geometry.TriangleMesh.create_sphere()
mesh.compute_vertex_normals()
print(
f'The mesh has {len(mesh.vertices)} vertices and {len(mesh.triangles)} triangles'
)
o3d.visualization.draw_geometries([mesh], zoom=0.8, mesh_show_wireframe=True)
mesh = mesh.subdivide_loop(number_of_iterations=2)
print(
f'After subdivision it has {len(mesh.vertices)} vertices and {len(mesh.triangles)} triangles'
)
o3d.visualization.draw_geometries([mesh], zoom=0.8, mesh_show_wireframe=True)


The mesh has 762 vertices and 1520 triangles

After subdivision it has 12162 vertices and 24320 triangles

[18]:
mesh = o3dtut.get_knot_mesh()
mesh.compute_vertex_normals()
print(
f'The mesh has {len(mesh.vertices)} vertices and {len(mesh.triangles)} triangles'
)
o3d.visualization.draw_geometries([mesh], zoom=0.8, mesh_show_wireframe=True)
mesh = mesh.subdivide_loop(number_of_iterations=1)
print(
f'After subdivision it has {len(mesh.vertices)} vertices and {len(mesh.triangles)} triangles'
)
o3d.visualization.draw_geometries([mesh], zoom=0.8, mesh_show_wireframe=True)


The mesh has 1440 vertices and 2880 triangles

After subdivision it has 5760 vertices and 11520 triangles

網格簡化

有時我們想用較少的三角形和頂點來表示高解析度網格,但是低解析度網格仍然應該接近高解析度網格。為此,Open3D實現了許多網格簡化方法。

頂點聚類

頂點聚類方法會池化所有頂點,將屬於給定大小的體素內的所有點簡化成單個頂點。

該方法在函數 simplify_vertex_clustering 中實現,有 voxel_size(定義體素網格的大小) 和 contraction (定義頂點集合的方式)作為參數。o3d.geometry.SimplificationContraction.Average 計算一個簡單的平均數。

[19]:
mesh_in = o3dtut.get_bunny_mesh()
print(
f'Input mesh has {len(mesh_in.vertices)} vertices and {len(mesh_in.triangles)} triangles'
)
o3d.visualization.draw_geometries([mesh_in])

voxel_size = max(mesh_in.get_max_bound() - mesh_in.get_min_bound()) / 32
print(f'voxel_size = {voxel_size:e}')
mesh_smp = mesh_in.simplify_vertex_clustering(
voxel_size=voxel_size,
contraction=o3d.geometry.SimplificationContraction.Average)
print(
f'Simplified mesh has {len(mesh_smp.vertices)} vertices and {len(mesh_smp.triangles)} triangles'
)
o3d.visualization.draw_geometries([mesh_smp])

voxel_size = max(mesh_in.get_max_bound() - mesh_in.get_min_bound()) / 16
print(f'voxel_size = {voxel_size:e}')
mesh_smp = mesh_in.simplify_vertex_clustering(
voxel_size=voxel_size,
contraction=o3d.geometry.SimplificationContraction.Average)
print(
f'Simplified mesh has {len(mesh_smp.vertices)} vertices and {len(mesh_smp.triangles)} triangles'
)
o3d.visualization.draw_geometries([mesh_smp])


Input mesh has 35947 vertices and 69451 triangles

voxel_size = 4.865594e-03
Simplified mesh has 3222 vertices and 6454 triangles

voxel_size = 9.731187e-03
Simplified mesh has 845 vertices and 1724 triangles

網格抽取

另一類網格簡化方法是網格抽取,它是以增量步驟操作的。我們選擇一個使誤差度量最小化的三角形並刪除它。重複此操作,直到達到所需數量的三角形。Open3D實現了simplify_quadric_decimation 它將誤差二次曲面(到相鄰平面的距離)最小化。參數 target_number_of_triangles 定義抽取算法的停止標準。

[20]:
mesh_smp = mesh_in.simplify_quadric_decimation(target_number_of_triangles=6500)
print(
f'Simplified mesh has {len(mesh_smp.vertices)} vertices and {len(mesh_smp.triangles)} triangles'
)
o3d.visualization.draw_geometries([mesh_smp])

mesh_smp = mesh_in.simplify_quadric_decimation(target_number_of_triangles=1700)
print(
f'Simplified mesh has {len(mesh_smp.vertices)} vertices and {len(mesh_smp.triangles)} triangles'
)
o3d.visualization.draw_geometries([mesh_smp])


Simplified mesh has 4405 vertices and 6499 triangles

Simplified mesh has 1979 vertices and 1700 triangles

連接的組件

各種重建方法的結果。Open3D實現了一個連接組件算法 cluster_connected_triangles 該算法將每個三角形分配給一組連接的三角形。它為每個三角形返回 triangle_clusters中的簇的索引,並為每個簇返回 cluster_n_triangles中的三角形數和 cluster_area中簇的表面積。

這在 RGBD Integration實例中很有用,它並不總是單個三角形網格,而是多個網格。一些較小的部件是由於噪音造成的,我們很可能希望將其移除。

下面的代碼顯示了函數cluster_connected_triangles 的應用以及如何使用它來刪除偽三角形。

[21]:
print("Generate data")
mesh = o3dtut.get_bunny_mesh().subdivide_midpoint(number_of_iterations=2)
vert = np.asarray(mesh.vertices)
min_vert, max_vert = vert.min(axis=0), vert.max(axis=0)
for _ in range(30):
cube = o3d.geometry.TriangleMesh.create_box()
cube.scale(0.005, center=cube.get_center())
cube.translate(
(
np.random.uniform(min_vert[0], max_vert[0]),
np.random.uniform(min_vert[1], max_vert[1]),
np.random.uniform(min_vert[2], max_vert[2]),
),
relative=False,
)
mesh += cube
mesh.compute_vertex_normals()
print("Show input mesh")
o3d.visualization.draw_geometries([mesh])


Generate data
Show input mesh

[22]:
print("Cluster connected triangles")
with o3d.utility.VerbosityContextManager(
o3d.utility.VerbosityLevel.Debug) as cm:
triangle_clusters, cluster_n_triangles, cluster_area = (
mesh.cluster_connected_triangles())
triangle_clusters = np.asarray(triangle_clusters)
cluster_n_triangles = np.asarray(cluster_n_triangles)
cluster_area = np.asarray(cluster_area)


Cluster connected triangles
[Open3D DEBUG] [ClusterConnectedTriangles] Compute triangle adjacency
[Open3D DEBUG] [ClusterConnectedTriangles] Done computing triangle adjacency
[Open3D DEBUG] [ClusterConnectedTriangles] Done clustering, #clusters=31
[23]:
print("Show mesh with small clusters removed")
mesh_0 = copy.deepcopy(mesh)
triangles_to_remove = cluster_n_triangles[triangle_clusters] < 100
mesh_0.remove_triangles_by_mask(triangles_to_remove)
o3d.visualization.draw_geometries([mesh_0])


Show mesh with small clusters removed

[24]:
print("Show largest cluster")
mesh_1 = copy.deepcopy(mesh)
largest_cluster_idx = cluster_n_triangles.argmax()
triangles_to_remove = triangle_clusters != largest_cluster_idx
mesh_1.remove_triangles_by_mask(triangles_to_remove)
o3d.visualization.draw_geometries([mesh_1])


Show largest cluster

 >>>>>>>>>>>> THE END <<<<<<<<<<<<

相關焦點

  • Open3D點雲操作
    本教程演示了對點雲的基本操作。顯示點雲[2]:print("Load a ply point cloud, print it, and render it")pcd = o3d.io.read_point_cloud("../..
  • Open3d學習計劃(4)網格
    各種重建算法的結果(比如RGBD Integration 並不是只有一個三角網格而是有多個網格。一些較小的部分(相比如主物體較小)是由於噪聲引起的,我們會想要移除它。Open3d實現了一個連通分量算法cluster_connected_triangles,他將每個三角形分配給一個連接的三角集群。
  • Open3D編譯源碼
    配置mkdir buildcd buildcmake -DCMAKE_INSTALL_PREFIX=<open3d_install_directory> ..CMAKE_INSTALL_PREFIX 參數是可選的,可用於將Open3D安裝到用戶指定位置。
  • Open3D中文教程-體素化
    體素網格是3D中定義在規則3D網格上的另一種幾何體類型,而體素可以看作是2D中像素的3D對應體。Open3D具有可用於處理體素網格的幾何體類型 VoxelGrid。從三角網格創建體素Open3D 提供了函數 create_from_triangle_mesh 從三角形網格創建體素柵格。
  • Open3d 學習計劃—13(Azure Kinect)
    你能夠通過下面的方式得到Open3d的Python模塊路徑:python -c "import open3d as o3d; import os; print(os.path.dirname(o3d.使用Open3d Python包對於Python版本的Open3d,運行pip install open3d_azure_kinect_ubuntu1604_fixopen3d_azure_kinect_ubuntu1604_fix包包含四個共享庫libstdc
  • Open3D中文教程-彩色點雲配準例程(c++版本)
    #include <Eigen/Dense>#include <iostream>#include <memory>#include "open3d/Open3D.h"#include "open3d/pipelines/registration/ColoredICP.h" using
  • Open3D中文教程-彩色點雲的配準
    它實現了 [[Park2017]] (http://www.open3d.org/docs/release/tutorial/reference.html#park2017) 裡的算法。顏色信息的對齊是沿切線平面的。與已有的點雲配準算法相比,該算法具有更高的精度和魯棒性,同時運行速度與ICP配準算法相當。本教程使用 Open3D中文教程-點雲ICP配準中的符號。
  • ​pen3D點雲操作手冊
    本教程演示了對點雲的基本操作。顯示點雲[2]:print("Load a ply point cloud, print it, and render it")pcd = o3d.io.read_point_cloud("../..
  • Unity編輯器擴展工具,輕鬆玩轉網格變換
    Mesh Materializer包含一系列用於改變場景風格的工具,該資源包就包含了上面介紹的Flat Mesh Generator及Ambient Occlusion And Indirect Lighting工具,另外還帶有用於將地形轉換為網格的Terrain To Mesh、調整頂點顏色的Vertex Color Adjustments、網格資源優化器以及計算網格厚度的烘焙工具
  • Open3d學習計劃(3)點雲
    open3d還支持使用RANSAC從點雲中分割幾何基元。要查找點雲中最有可能存在的平面,我們使用segement_plane函數。pcd = o3d.io.read_point_cloud("../..
  • 【流體】| ANSYS meshing 網格劃分之 - 上手1 - 3D tube網格劃分
    在之前的入門文章《ANSYS meshing 網格劃分之 - 入門1 - 3D幾何邊界命名》中,我們用中間放置有阻流器的tube作為例子學會邊界命名操作
  • Open3D中文教程-多方向點雲位置配準
    後面實現的技術發表於 [Choi2015] (http://www.open3d.org/docs/release/tutorial/reference.html#choi2015)。輸入教程代碼的第一部分從文件中讀取三個點雲。點雲被降採樣並一起可視化。如圖,它們是錯位了的。
  • ECCV 2018 | Pixel2Mesh:從單幀RGB圖像生成三維網格模型
    騰訊 AI Lab 與復旦大學、普林斯頓大學、Intel Labs 合作提出一種端對端的深度學習框架,可從單張彩色圖片直接生成三維網格(3d mesh)。該研究論文被頂級會議 ECCV 2018 收錄,以下是技術詳細解讀。
  • 開發者說丨網格地圖的動態加載
    要想實現在定位過程中動態加載相應的網格點雲,需要接收當前的GPS位置,確定當前位置的網格點雲,考慮當前位置在網格的邊界時,我們可以預定義一個margin距離,在當前網格周圍margin範圍內的網格點雲均為需要加載的區域
  • Open3d學習計劃—8(可視化)
    print("Let's draw a cubic using o3d.geometry.LineSet.")points = [ [0, 0, 0], [1, 0, 0], [0, 1, 0], [1, 1, 0], [0, 0, 1], [1, 0, 1],
  • 3D列印切片軟體
    說的簡單通俗易懂的比喻就是我們去醫院做CT檢查,這個CT就是(Computed Tomography),即電子計算機斷層掃描,把我們人體某一部分的截面按照順序掃描出來。先簡單說說怎麼使用吧,打開軟體後界面就是這樣的
  • Grasshopper網格基礎與應用實例
    網格是3D建模領域最有代表性的幾何形式,很多軟體的構架都是以網格為中心,但是由於Rhino主要是針對Nurbs的操作,導致網格在Rhino以及GH
  • 目前流行的CFD網格劃分軟體,你會選哪個?
    不同的求解器對於網格的需求存在差異。這不僅體現在網格類型上,有時候還體現在網格疏密變化、網格的形狀上。同時,CFD求解器對於網格也有其特殊的需求,因此選擇合適的網格工具,有利於提高工作效率。當前市面上有形形色色的網格生成軟體,這裡列舉一些最常見的網格軟體。
  • Unity3D 尋路系統
    Unity2019:打開window->AI->Navigation面板;如下圖點擊Bake完成網格路面的烘培。紅色Cube為目標物體,黃色Sphere為尋路物體,圖中淺藍色路線為烘培的網格路線。三、關於Navigation中屬性的介紹
  • Open3d學習計劃—6(RGBD圖像)
    Open3d提供圖像(images)數據結構。支持多種函數read_image,write_image,filter_image 和draw_geometries。Open3d的圖像能夠直接轉化為numpy或者從numpy轉化。一個Open3d的RGBDImage由兩幅圖像組成,分別是RGBDImage.depth & RGBDImage.color。