0

在投影 3D 数据的点云后,我试图获得前、后、左、右、上、下。但结果并不好。有没有更好的方法来获得所需的视图?我已经使用 numpy-stl 文档和一些投影研究完成了这项工作。

import numpy as np
import pandas as pd
import os
import time
import scipy
import math
from scipy import ndimage
from stl import mesh
from matplotlib import pyplot as plt
from mpl_toolkits import mplot3d
from matplotlib import cm
%matplotlib inline

# Load an existing stl file:
my_mesh = mesh.Mesh.from_file('Bolt.stl')

# Create a new plot
figure = pyplot.figure()
axes = mplot3d.Axes3D(figure)

# Load the STL files and add the vectors to the plot
axes.add_collection3d(mplot3d.art3d.Poly3DCollection(my_mesh.vectors))

# Auto scale to the mesh size
scale = my_mesh.points.flatten()
axes.auto_scale_xyz(scale, scale, scale)

# Show the plot to the screen
pyplot.show()

输入 bolt.stl 文件的 3D 视图

我已经从grabcad.com 下载了那个bolt.stl。

在那之后,我试图投射不同的观点,比如:

points = my_mesh.vectors
x = points[:,0].flatten()
y = points[:,1].flatten()
z = points[:,2].flatten()

fig= plt.figure()
ax= fig.add_subplot(111, projection= '3d')
ax.scatter(x,y,z)

ax.plot(x, z, 'r+', zdir='y', zs=100)
ax.plot(y, z, 'g+', zdir='x', zs=-100)
ax.plot(x, y, 'k+', zdir='z', zs=-100)

ax.set_xlabel('X')
ax.set_xlim([-100, 100])
ax.set_ylabel('Y')
ax.set_ylim([-100, 100])
ax.set_zlabel('Z')
ax.set_zlim([-100, 100])

plt.show()

使用 matplotlib 获取投影视图

结果太糟糕了,我什至不知道螺栓 3D 去哪儿了。

我也试过:

X = points[:,0]
Y = points[:,1]
Z = points[:,2]

fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot_surface(X, Y, Z, rstride=8, cstride=8, alpha=0.3)
cset = ax.contourf(X, Y, Z, zdir='z', offset=-100, cmap="gray")
cset = ax.contourf(X, Y, Z, zdir='x', offset=-100, cmap="gray")
cset = ax.contourf(X, Y, Z, zdir='y', offset=100, cmap="gray")

ax.set_xlabel('X')
ax.set_xlim(-100, 100)
ax.set_ylabel('Y')
ax.set_ylim(-100, 100)
ax.set_zlabel('Z')
ax.set_zlim(-100, 100)

plt.show()

使用轮廓

我也尝试过使用此代码,这是我从“ MVCNN for 3D shape recognition ”中找到的

def point_cloud_to_volume(points, size=32):
    vol = np.zeros((size,size,size))
    locations = np.copy(points)
    locations[:] *= (size-1)
    locations = locations.astype(int)
    locations[locations >= size] = 0.0
    locations[locations < 0] = 0.0
    vol[locations[:,0],locations[:,1],locations[:,2]] = 1.0
    return vol

def vol2depthmap(volume_array, bg_val=32):
    vol = volume_array.argmax(2)
    vol[vol == 0] = bg_val
    return vol
v = point_cloud_to_volume(points)
%matplotlib inline
from matplotlib import pyplot as plt
plt.imshow(vol2depthmap(v), interpolation='nearest', cmap='Greys')
plt.colorbar()

从点云转换为体积后的 Matplotlib 图

最后,我尝试过:

front_proj = points[:, :, :].sum(axis=1)
plt.plot(front_proj)
plt.show()

正视图

side_proj = points[:, :, :].sum(axis=0)
plt.plot(side_proj)
plt.show()

侧面图

top_proj = points[:, :, :].sum(axis=2)
plt.plot(top_proj)
plt.show()

顶视图

我尝试过使用切片,但正如您已经猜到结果会是什么一样。

front   = points[:,:,0] 
back   = points[:,:,-1] 
top    = points[0,:,:]  
bottom = points[-1,:,:] 
r_side = points[:,-1,:] 
l_side = points[:,0,:]

正视图

后视图

顶视图

底视图

右视图

左视图

如何获得 .stl 文件的正确视图,如下所示。请忽略绘图和尺寸。

示例视图

或者任何其他 cad 格式都可以。我在 .stl 文件中尝试过,因为到目前为止我没有找到 python 库来加载除 stl 之外的其他 cad 格式。

4

2 回答 2

0

你试过这个吗?

figure = plt.figure()
axes = mplot3d.Axes3D(figure)

axes.add_collection3d(mplot3d.art3d.Poly3DCollection(mymesh.vectors))
axes.view_init(90,270) # top view
scale = mymesh.points.flatten('F') #C, F, A, or K
axes.auto_scale_xyz(scale, scale, scale)

plt.show()

使用 0,90,180,270 的 view_init 组合来获得其他投影。

于 2021-02-23T17:52:16.113 回答
0

您可以执行以下操作:

vertices = my_mesh.vectors.reshape(3*len(my_mesh.vectors), 3)
vertices = np.unique(vertices, axis=0)
x, y, z = zip(*vertices)

figure = plt.figure()
axes = mplot3d.Axes3D(figure)
axes.scatter3D(x, y, z)
plt.show()
于 2021-08-16T05:19:08.443 回答