def compute_normal_and_curvature(points, k = 30): """ Args: points: pointcloud-Nx3 k: number of pointset Returns: data = [x, y, z, nx, ny, nz, curvature] """ assert points.shape[1] == 3 points = pd.DataFrame(points) points.columns = ['x', 'y', 'z'] cloud = PyntCloud(points) k_neighbors = cloud.get_neighbors(k=k) cloud_normal = copy.copy(cloud) cloud_normal = cloud_normal.add_scalar_field("normals", k_neighbors=k_neighbors) ev = copy.copy(cloud) ev = cloud.add_scalar_field("eigen_values", k_neighbors=k_neighbors) cloud.add_scalar_field("curvature", ev=ev) points = cloud.points nx = "nx(" + (k + 1).__str__() + ")" ny = "ny(" + (k + 1).__str__() + ")" nz = "nz(" + (k + 1).__str__() + ")" curvature = "curvature(" + (k + 1).__str__() + ")" filter_columns = ['x', 'y', 'z', nx, ny, nz, curvature] data = points.reindex(columns=filter_columns) return data
def findPlane(points): indices = array([range(0, len(points.data.coordinate[0]))]) pointsWithIndices = concatenate((indices.T, points.data.coordinate[0]), axis=1) cloud = PyntCloud( DataFrame(pointsWithIndices, columns=['index', 'x', 'y', 'z'])) cloud.add_scalar_field('plane_fit', max_dist=1) plane = cloud.points.query('is_plane == 1').to_numpy() return plane.T[0].astype(int)
def find_plane(points): pointcloud = PyntCloud(points) pointcloud.add_scalar_field("plane_fit", max_dist=0.2, max_iterations=1000, n_inliers_to_stop=None) inliers = pointcloud.points[pointcloud.points.is_plane == 1] outliers = pointcloud.points[pointcloud.points.is_plane == 0] return pointcloud return inliers, outliers
def computeNormals(model): cloudable = pd.DataFrame(data=np.transpose(model), columns=['x', 'y', 'z']) # calculates a pointcloud of the input model using a pandas DataFrame cloud = PyntCloud(cloudable) # use neighbors to get normals from pointcloud neighbors = cloud.get_neighbors(k=10) cloud.add_scalar_field('normals', k_neighbors=neighbors) # extract normals from the altered DataFrame normals = np.transpose(np.asarray(cloudable.loc[:, 'nx(10)':'nz(10)'])) master = np.repeat(masterOrig, len(normals[0]), axis=1) # taking the dot product column-wise; the 'ij,ij->' notation is saying: # take dot product of ith row, jth column of normals and ith row, jth column of master # then, create boolean mask array for normal comparison I = np.einsum('ij,ij->j', normals, master) < 0 # flip all values in column if I is true at that column (dot prod < 0) normals[:, I] = -normals[:, I] return (normals)
def pyntcloud_and_eigenvalues(): cloud = PyntCloud(pd.DataFrame( data={ "x": np.array([0, 0, 1, -1, 0, 0], dtype=np.float32), "y": np.array([0, 1, 0, 0, -1, 0], dtype=np.float32), "z": np.array([0, 0, 0, 0, 0, 2], dtype=np.float32) })) k_neighbors = cloud.get_neighbors(k=4) ev = cloud.add_scalar_field("eigen_values", k_neighbors=k_neighbors) return cloud, ev
#Loading the point cloud as a Pandas DataFrame. Give Path in line 101 accordingly. data = pd.read_csv('cloud(rgb).txt',sep = " ") data.columns = ['x','y','z','red','green','blue','1','2','3','4','5'] #data = data.drop(['1','2','3','4','5'],axis = 1) cloud = PyntCloud(data) print(cloud) #Cloud.points is a Pandas Dataframe. #print(cloud.points.columns) # Calculating the best fit plane on the point cloud data and getting the equation of the plane in return _,eq = cloud.add_scalar_field(name = 'plane_fit',max_dist = 5*1e-2) print(eq) a = eq[0] b = eq[1] c = eq[2] d = eq[3] #dis = abs((a * x1 + b * y1 + c * z1 + d)) e = (math.sqrt(a * a + b * b + c * c)) # Making a mask over the points where the inliers of the best fit plane are selected mask = cloud.points['is_plane'] == 1 np.savetxt(r'Plane_inliers.txt',cloud.points[mask], fmt = '%f') #cloud.points[mask]