python
1コード 2import open3d as o3d 3import numpy as np 4import copy 5 6 7def draw_registration_result(source, target, transformation): 8 source_temp = copy.deepcopy(source) 9 target_temp = copy.deepcopy(target) 10 source_temp.paint_uniform_color([1, 0.706, 0]) 11 target_temp.paint_uniform_color([0, 0.651, 0.929]) 12 source_temp.transform(transformation) 13 o3d.visualization.draw_geometries([source_temp, target_temp]) 14 15 16def preprocess_point_cloud(pcd, voxel_size): 17 #print(":: Downsample with a voxel size %.3f." % voxel_size) 18 pcd_down = pcd.voxel_down_sample(voxel_size) 19 20 radius_normal = voxel_size * 2 21 #print(":: Estimate normal with search radius %.3f." % radius_normal) 22 pcd_down.estimate_normals( 23 o3d.geometry.KDTreeSearchParamHybrid(radius=radius_normal, max_nn=30)) 24 radius_feature = voxel_size * 5 25 #print(":: Compute FPFH feature with search radius %.3f." % radius_feature) 26 pcd_fpfh = o3d.registration.compute_fpfh_feature( 27 pcd_down, 28 o3d.geometry.KDTreeSearchParamHybrid(radius=radius_feature, max_nn=100)) 29 return pcd_down, pcd_fpfh 30 31 32def prepare_dataset(voxel_size): 33 #print(":: Load two point clouds and disturb initial pose.") 34 source = o3d.io.read_point_cloud("/Users/****/Desktop/pcd-0.ply") 35 target = o3d.io.read_point_cloud("/Users/****/Desktop/pcd-1.ply") 36 trans_init = np.asarray([[0.0, 0.0, 1.0, 0.0], [1.0, 0.0, 0.0, 0.0], 37 [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 0.0, 1.0]]) 38 source.transform(trans_init) 39 draw_registration_result(source, target, np.identity(4)) 40 41 source_down, source_fpfh = preprocess_point_cloud(source, voxel_size) 42 target_down, target_fpfh = preprocess_point_cloud(target, voxel_size) 43 return source, target, source_down, target_down, source_fpfh, target_fpfh 44 45 46def execute_global_registration(source_down, target_down, source_fpfh, 47 target_fpfh, voxel_size): 48 distance_threshold = voxel_size * 1.5 49 #print(":: RANSAC registration on downsampled point clouds.") 50 #print(" Since the downsampling voxel size is %.3f," % voxel_size) 51 #print(" we use a liberal distance threshold %.3f." % distance_threshold) 52 result = o3d.registration.registration_ransac_based_on_feature_matching( 53 source_down, target_down, source_fpfh, target_fpfh, distance_threshold, 54 o3d.registration.TransformationEstimationPointToPoint(False), 4, [ 55 o3d.registration.CorrespondenceCheckerBasedOnEdgeLength(0.9), 56 o3d.registration.CorrespondenceCheckerBasedOnDistance( 57 distance_threshold) 58 ], o3d.registration.RANSACConvergenceCriteria(4000000, 500)) 59 return result 60 61 62def refine_registration(source, target, source_fpfh, target_fpfh, voxel_size): 63 distance_threshold = voxel_size * 0.4 64 #print(":: Point-to-plane ICP registration is applied on original point") 65 #print(" clouds to refine the alignment. This time we use a strict") 66 #print(" distance threshold %.3f." % distance_threshold) 67 source.estimate_normals(search_param=o3d.geometry.KDTreeSearchParamHybrid(radius=0.1, max_nn=30)) 68 target.estimate_normals(search_param=o3d.geometry.KDTreeSearchParamHybrid(radius=0.1, max_nn=30)) 69 result = o3d.registration.registration_icp( 70 source, target, distance_threshold, result_ransac.transformation, 71 o3d.registration.TransformationEstimationPointToPlane()) 72 return result 73 74num =0 75if __name__ == "__main__": 76 voxel_size = 0.05 # means 5cm for the dataset 77 source, target, source_down, target_down, source_fpfh, target_fpfh = \ 78 prepare_dataset(voxel_size) 79 80 result_ransac = execute_global_registration(source_down, target_down, 81 source_fpfh, target_fpfh, 82 voxel_size) 83 84 85 #print(result_ransac) 86 draw_registration_result(source_down, target_down, 87 result_ransac.transformation) 88 89 result_icp = refine_registration(source, target, source_fpfh, target_fpfh, 90 voxel_size) 91 92 print(result_icp) 93 draw_registration_result(source, target, result_icp.transformation) 94 95 96 97 print("Saving to {0}.ply...") 98 pcd = o3d.geometry.PointCloud(result_icp) 99 o3d.io.write_point_cloud("/Users/****/Desktop/out.ply", pcd) 100 101 print("Done") 102 103```### 前提・実現したいこと 104realsenseL515 を用いて、対象物1つをさまざまな角度から撮影して3Dデータ(plyファイル)を取得した。 105それらの複数の3Dデータを一つに重ね合わせ、plyファイルまたはcsvファイルに出力したい。 106 107 108 1093Dデータを重ね合わせること自体は実行できます。 110しかし、データを保存する際エラーが出てしまいます。 111### 発生している問題・エラーメッセージ 112
エラーメッセージ
pcd = o3d.geometry.PointCloud(result_icp)
TypeError: init(): incompatible constructor arguments. The following argument types are supported:
1. open3d.open3d_pybind.geometry.PointCloud()
2. open3d.open3d_pybind.geometry.PointCloud(arg0: open3d.open3d_pybind.geometry.PointCloud)
3. open3d.open3d_pybind.geometry.PointCloud(points: open3d.open3d_pybind.utility.Vector3dVector)
Invoked with: registration::RegistrationResult with fitness=4.901549e-01, inlier_rmse=9.731451e-03, and correspondence_set size of 68357
Access transformation to get result.
python ### 試したこと エラーメッセージから保存するデータのタイプが違うとのことで、タイプを変換する関数などを探してみましたが、あまりヒットせず、詰まっています。 ### 補足情報(FW/ツールのバージョンなど) OS:Mac python3.7 を使用しています ここにより詳細な情報を記載してください。
あなたの回答
tips
プレビュー