open3d 點云數據處理
爆肝5萬字??Open3D 點云數據處理基礎(Python版)_python 點云 焊縫-CSDN博客
如何用NumPy讀取和保存點云數據 - 知乎
讀取并可視化點云
np.loadtxt 從txt中讀取點集,并open3d顯示單個點云
?txt內容:每行皆為一個點 xyz,逗號隔開,xy為圖像坐標,z為圖像序號,所有圖的點集皆存入一個txt
import open3d as o3d
import numpy as np# points_data = np.loadtxt("E:/vsproject/勛儀交接/標克艾芬達暖水管/測量主管尺寸/vp/11pnts.txt", delimiter=",", dtype=np.float32)
points_data = np.loadtxt("E:/vsproject/勛儀交接/標克艾芬達暖水管/測量主管尺寸/vp/11pnts.txt", delimiter=",")
print('shape: ', points_data.shape)
print('data type: ', points_data.dtype)points_data[:,2] = points_data[:,2] * 21 # 將所有行的第三列乘以 21# points_data = np.random.rand(100, 3) # 示例數據:100 個隨機 3D 點
colors_data = np.random.rand(100, 3) # 100 個隨機 RGB 顏色數組pcd = o3d.geometry.PointCloud() # 創建一個空的點云對象
pcd.points = o3d.utility.Vector3dVector(points_data[:, :3]) # 從NumPy數組points_data中分配3D點(取前3列作為 x,y,z 坐標)
pcd.colors = o3d.utility.Vector3dVector(colors_data) # 分配顏色信息
o3d.visualization.draw_geometries([pcd]) # 可視化點云
?
讀取.pcd文件
import open3d as o3d
import numpy as npprint("->正在加載點云... ")
pcd = o3d.io.read_point_cloud("test.pcd")
print(pcd)print("->正在可視化點云")
o3d.visualization.draw_geometries([pcd])
讀取.pts文件,并進行網格化 (Mesh化)
原始點云為.pts
文件,內容為x,y,z
的坐標
import open3d as o3d
import numpy as np# 讀取.pts文件
def read_pts_file(filename):with open(filename, 'r') as f:lines = f.readlines()pts = []for line in lines:data = line.strip().split()pts.append([float(data[0]), float(data[1]), float(data[2])])return np.array(pts)# 加載.pts文件
pts_filename = "E:\Airplane.pts" # 替換為.pts文件路徑
pts = read_pts_file(pts_filename)# 創建open3d格式的點云對象
pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(pts)# 創建alpha shape并進行mesh化
alpha = 0.015 # 設置alpha值
mesh = o3d.geometry.TriangleMesh.create_from_point_cloud_alpha_shape(pcd, alpha)# 可視化網格化后的結果
o3d.visualization.draw_geometries([mesh], window_name="網格化結果")
同一窗口可視化多個點云
o3d.visualization.draw_geometries([pcd1, pcd2, ... ,pcdn])
# 加載點云1
pcd1 = o3d.io.read_point_cloud("bunny.pcd")
print(pcd1)# 加載點云2
pcd2 = o3d.io.read_point_cloud("bunny0.pcd")
print(pcd2)# 可視化兩個點云
o3d.visualization.draw_geometries([pcd1, pcd2])
space = 2500
pnts_r = np.loadtxt("E:/vsproject/勛儀交接/標克艾芬達暖水管/測量主管尺寸/vpr/11pnts.txt", delimiter=",")
pnts_r[:,2] = pnts_r[:,2] * 36 # 將所有行的第三列乘以 21
pnts_r[:,1] = pnts_r[:,1] + space
pnts_r[:,0] = pnts_r[:,0] * 4
pnts_d = np.loadtxt("E:/vsproject/勛儀交接/標克艾芬達暖水管/測量主管尺寸/vpd/11pnts.txt", delimiter=",")
pnts_d[:,2] = pnts_d[:,2] * 36 # 將所有行的第三列乘以 21
pnts_d[:,1] = pnts_d[:,1] + space*2
pnts_d[:,0] = pnts_d[:,0] * 2
pnts_s = np.loadtxt("E:/vsproject/勛儀交接/標克艾芬達暖水管/測量主管尺寸/散熱片劃痕/11pnts.txt", delimiter=",")
pnts_s[:,2] = pnts_s[:,2] * 16 # 將所有行的第三列乘以 21
pnts_s[:,1] = pnts_s[:,1] + space*3
pnts_s[:,0] = pnts_s[:,0] * 2def get_pcd(points_data):pcd = o3d.geometry.PointCloud() # 創建一個空的點云對象pcd.points = o3d.utility.Vector3dVector(points_data[:, :3]) # 從NumPy數組points_data中分配3D點(取前3列作為 x,y,z 坐標)pcd.colors = o3d.utility.Vector3dVector(colors_data) # 分配顏色信息return pcdpcd_r = get_pcd(pnts_r)
pcd_d = get_pcd(pnts_d)
pcd_s = get_pcd(pnts_s)
o3d.visualization.draw_geometries([pcd_r,pcd_d,pcd_s]) # 可視化點云
下采樣,兩種去除離群點,均值濾波
# points_data = np.loadtxt("E:/vsproject/勛儀交接/標克艾芬達暖水管/測量主管尺寸/vp/11pnts.txt", delimiter=",", dtype=np.float32)
points_data = np.loadtxt("E:/vsproject/勛儀交接/標克艾芬達暖水管/測量主管尺寸/vpc/11pnts.txt", delimiter=",")
print('shape: ', points_data.shape)
print('data type: ', points_data.dtype)points_data[:,2] = points_data[:,2] * 36 # 將所有行的第三列乘以 21
points_data[:,0] = points_data[:,0] * 4# points_data = np.random.rand(100, 3) # 示例數據:100 個隨機 3D 點
colors_data = np.random.rand(100, 3) # 100 個隨機 RGB 顏色數組pcd = o3d.geometry.PointCloud() # 創建一個空的點云對象
pcd.points = o3d.utility.Vector3dVector(points_data[:, :3]) # 從NumPy數組points_data中分配3D點(取前3列作為 x,y,z 坐標)
pcd.colors = o3d.utility.Vector3dVector(colors_data) # 分配顏色信息# 1. 下采樣(降采樣)
down_pcd = pcd.voxel_down_sample(voxel_size=0.05)
print("下采樣后的點云數量:", len(np.asarray(down_pcd.points)))# 2. 去除離群點
# 統計離群點移除
cl, ind = down_pcd.remove_statistical_outlier(nb_neighbors=20, std_ratio=2.0)
statistical_outlier_removed = down_pcd.select_by_index(ind)
print("統計離群點移除后的點云數量:", len(np.asarray(statistical_outlier_removed.points)))# 半徑離群點移除
# cl, ind = statistical_outlier_removed.remove_radius_outlier(nb_points=16, radius=0.05)
cl, ind = statistical_outlier_removed.remove_radius_outlier(nb_points=6, radius=11)
radius_outlier_removed = statistical_outlier_removed.select_by_index(ind)
print("半徑離群點移除后的點云數量:", len(np.asarray(radius_outlier_removed.points)))# 3. 濾波(平滑) - 自定義均值濾波
def mean_filter(pcd, k=5):''' 對每個點找到其k個最近的鄰居并計算均值作為濾波后的點坐標 '''points = np.asarray(pcd.points)filtered_points = np.zeros_like(points)for i in range(len(points)):# 找到k個最近的鄰居(這里簡化處理,實際應用中可以使用KD樹等高效方法)distances = np.linalg.norm(points - points[i], axis=1)nearest_indices = np.argsort(distances)[:k]filtered_points[i] = np.mean(points[nearest_indices], axis=0)filtered_pcd = o3d.geometry.PointCloud()filtered_pcd.points = o3d.utility.Vector3dVector(filtered_points)return filtered_pcdfiltered_pcd = mean_filter(radius_outlier_removed, k=5)
print("均值濾波后的點云數量:", len(np.asarray(filtered_pcd.points)))# 可視化原始點云和處理后的點云
# o3d.visualization.draw_geometries([pcd]) # 可視化點云
o3d.visualization.draw_geometries([pcd], window_name="原始點云")
o3d.visualization.draw_geometries([down_pcd], window_name="下采樣后的點云")
o3d.visualization.draw_geometries([statistical_outlier_removed], window_name="統計離群點移除后的點云")
o3d.visualization.draw_geometries([radius_outlier_removed], window_name="半徑離群點移除后的點云")
o3d.visualization.draw_geometries([filtered_pcd], window_name="均值濾波后的點云")