stuff
This commit is contained in:
		| @@ -3,6 +3,22 @@ import open3d as o3d | |||||||
| from sklearn.cluster import DBSCAN | from sklearn.cluster import DBSCAN | ||||||
|  |  | ||||||
|  |  | ||||||
|  | from pyod.models.knn import KNN | ||||||
|  | from pyod.models.sod import SOD | ||||||
|  | from pyod.models.abod import ABOD | ||||||
|  | from pyod.models.sos import SOS | ||||||
|  | from pyod.models.pca import PCA | ||||||
|  | from pyod.models.ocsvm import OCSVM | ||||||
|  | from pyod.models.mcd import MCD | ||||||
|  | from pyod.models.lof import LOF | ||||||
|  | from pyod.models.cof import COF | ||||||
|  | from pyod.models.cblof import CBLOF | ||||||
|  | from pyod.models.loci import LOCI | ||||||
|  | from pyod.models.hbos import HBOS | ||||||
|  | from pyod.models.lscp import LSCP | ||||||
|  | from pyod.models.feature_bagging import FeatureBagging | ||||||
|  |  | ||||||
|  |  | ||||||
| def mini_color_table(index, norm=True): | def mini_color_table(index, norm=True): | ||||||
|     colors = [ |     colors = [ | ||||||
|         [0.5000, 0.5400, 0.5300], [0.8900, 0.1500, 0.2100], [0.6400, 0.5800, 0.5000], |         [0.5000, 0.5400, 0.5300], [0.8900, 0.1500, 0.2100], [0.6400, 0.5800, 0.5000], | ||||||
| @@ -75,7 +91,11 @@ def cluster_per_column(pc, column): | |||||||
|     return clusters |     return clusters | ||||||
|  |  | ||||||
|  |  | ||||||
| def cluster_cubes(data, cluster_dims): | def cluster_cubes(data, cluster_dims, max_points_per_cluster=-1, min_points_per_cluster=-1): | ||||||
|  |  | ||||||
|  |     if cluster_dims[0] is 1 and cluster_dims[1] is 1 and cluster_dims[2] is 1: | ||||||
|  |         print("no need to cluster.") | ||||||
|  |         return [data] | ||||||
|  |  | ||||||
|     max = data[:,:3].max(axis=0) |     max = data[:,:3].max(axis=0) | ||||||
|     max += max * 0.01 |     max += max * 0.01 | ||||||
| @@ -100,19 +120,24 @@ def cluster_cubes(data, cluster_dims): | |||||||
|         cluster_idx = cluster_dims[0] * cluster_dims[2] * cluster_pos[1] + cluster_dims[0] * cluster_pos[2] + cluster_pos[0] |         cluster_idx = cluster_dims[0] * cluster_dims[2] * cluster_pos[1] + cluster_dims[0] * cluster_pos[2] + cluster_pos[0] | ||||||
|         clusters.setdefault(cluster_idx, []).append(row) |         clusters.setdefault(cluster_idx, []).append(row) | ||||||
|  |  | ||||||
|     # Apply farthest point sampling to each cluster |         # Apply farthest point sampling to each cluster | ||||||
|  |     final_clusters = [] | ||||||
|     for key, cluster in clusters.items(): |     for key, cluster in clusters.items(): | ||||||
|         c = np.vstack(cluster) |         c = np.vstack(cluster) | ||||||
|         clusters[key] = c # farthest_point_sampling(c, max_points_per_cluster) |         if c.shape[0] < min_points_per_cluster and -1 is not min_points_per_cluster: | ||||||
|  |             continue | ||||||
|  |  | ||||||
|     return clusters.values() |         if max_points_per_cluster is not -1: | ||||||
|  |             final_clusters.append(farthest_point_sampling(c, max_points_per_cluster)) | ||||||
|  |         else: | ||||||
|  |             final_clusters.append(c) | ||||||
|  |  | ||||||
|  |     return final_clusters | ||||||
|  |  | ||||||
|  |  | ||||||
| def cluster_dbscan(data, selected_indices, eps, min_samples, metric='euclidean', algo='auto'): | def cluster_dbscan(data, selected_indices, eps, min_samples=5, metric='euclidean', algo='auto'): | ||||||
|  |  | ||||||
|     min_samples = min_samples * len(data) |     # print('Clustering. Min Samples: ' + str(min_samples) + ' EPS: ' + str(eps) + "Selected Indices: " + str(selected_indices)) | ||||||
|  |  | ||||||
|     print('Clustering. Min Samples: ' + str(min_samples) + ' EPS: ' + str(eps) + "Selected Indices: " + str(selected_indices)) |  | ||||||
|  |  | ||||||
|     # 0,1,2 :   pos |     # 0,1,2 :   pos | ||||||
|     # 3,4,5 :   normal |     # 3,4,5 :   normal | ||||||
| @@ -120,13 +145,13 @@ def cluster_dbscan(data, selected_indices, eps, min_samples, metric='euclidean', | |||||||
|     # 7,8,9,10: type index one hot encoded |     # 7,8,9,10: type index one hot encoded | ||||||
|     # 11,12:    normal as angles |     # 11,12:    normal as angles | ||||||
|  |  | ||||||
|     db_res = DBSCAN(eps=eps, metric=metric, n_jobs=-1, algorithm=algo, min_samples=min_samples).fit(data[:, selected_indices]) |     db_res = DBSCAN(eps=eps, metric=metric, n_jobs=-1, min_samples=min_samples, algorithm=algo).fit(data[:, selected_indices]) | ||||||
|  |  | ||||||
|  |  | ||||||
|     labels = db_res.labels_ |     labels = db_res.labels_ | ||||||
|     n_clusters = len(set(labels)) - (1 if -1 in labels else 0) |     n_clusters = len(set(labels)) - (1 if -1 in labels else 0) | ||||||
|     n_noise = list(labels).count(-1) |     n_noise = list(labels).count(-1) | ||||||
|     print("Noise: " + str(n_noise) + " Clusters: " + str(n_clusters)) |     # print("Noise: " + str(n_noise) + " Clusters: " + str(n_clusters)) | ||||||
|  |  | ||||||
|     clusters = {} |     clusters = {} | ||||||
|     for idx, l in enumerate(labels): |     for idx, l in enumerate(labels): | ||||||
| @@ -167,3 +192,49 @@ def write_clusters(path, clusters, type_column=6): | |||||||
|  |  | ||||||
|         np.savetxt(file, types, header='', comments='') |         np.savetxt(file, types, header='', comments='') | ||||||
|         np.savetxt(file, cluster[:, :6], header=str(len(cluster)) + ' ' + str(6), comments='') |         np.savetxt(file, cluster[:, :6], header=str(len(cluster)) + ' ' + str(6), comments='') | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def normalize_pointcloud(pc, factor=1.0): | ||||||
|  |  | ||||||
|  |     max = pc.max(axis=0) | ||||||
|  |     min = pc.min(axis=0) | ||||||
|  |  | ||||||
|  |     f = np.max([abs(max[0] - min[0]), abs(max[1] - min[1]), abs(max[2] - min[2])]) | ||||||
|  |  | ||||||
|  |     pc[:, 0:3] /= (f * factor) | ||||||
|  |     pc[:, 3:6] /= (np.linalg.norm(pc[:, 3:6], ord=2, axis=1, keepdims=True)) | ||||||
|  |  | ||||||
|  |     return pc | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def hierarchical_clustering(data, selected_indices, eps, min_samples=5, metric='euclidean', algo='auto'): | ||||||
|  |  | ||||||
|  |     total_clusters = [] | ||||||
|  |  | ||||||
|  |     clusters = cluster_dbscan(data, selected_indices, eps, min_samples, metric=metric, algo=algo) | ||||||
|  |  | ||||||
|  |     for cluster in clusters: | ||||||
|  |         sub_clusters = cluster_dbscan(cluster, selected_indices, eps, min_samples, metric=metric, algo=algo) | ||||||
|  |         total_clusters.extend(sub_clusters) | ||||||
|  |  | ||||||
|  |     return total_clusters | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def filter_clusters(clusters, min_size): | ||||||
|  |  | ||||||
|  |     filtered_clusters = [] | ||||||
|  |  | ||||||
|  |     for c in clusters: | ||||||
|  |         if len(c) >= min_size: | ||||||
|  |             filtered_clusters.append(c) | ||||||
|  |  | ||||||
|  |     return filtered_clusters | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def split_outliers(pc, columns): | ||||||
|  |     clf = KNN()#FeatureBagging() # detector_list=[LOF(), KNN()] | ||||||
|  |     clf.fit(pc[:, columns]) | ||||||
|  |  | ||||||
|  |     # LOF, kNN | ||||||
|  |  | ||||||
|  |     return pc[clf.labels_ == 0], pc[clf.labels_ == 1] | ||||||
| @@ -85,18 +85,6 @@ def clusterToColor(cluster, cluster_idx): | |||||||
|     return colors |     return colors | ||||||
|  |  | ||||||
|  |  | ||||||
| def normalize_pointcloud(pc): |  | ||||||
|  |  | ||||||
|     max = pc.max(axis=0) |  | ||||||
|     min = pc.min(axis=0) |  | ||||||
|  |  | ||||||
|     f = np.max([abs(max[0] - min[0]), abs(max[1] - min[1]), abs(max[2] - min[2])]) |  | ||||||
|  |  | ||||||
|     pc[:, 0:3] /= f |  | ||||||
|     pc[:, 3:6] /= (np.linalg.norm(pc[:, 3:6], ord=2, axis=1, keepdims=True)) |  | ||||||
|  |  | ||||||
|     return pc |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def farthest_point_sampling(pts, K): | def farthest_point_sampling(pts, K): | ||||||
|  |  | ||||||
| @@ -139,43 +127,6 @@ def append_normal_angles(data): | |||||||
|     return np.column_stack((data, res)) |     return np.column_stack((data, res)) | ||||||
|  |  | ||||||
|  |  | ||||||
| def extract_cube_clusters(data, cluster_dims, max_points_per_cluster, min_points_per_cluster): |  | ||||||
|  |  | ||||||
|     max = data[:,:3].max(axis=0) |  | ||||||
|     max += max * 0.01 |  | ||||||
|  |  | ||||||
|     min = data[:,:3].min(axis=0) |  | ||||||
|     min -= min * 0.01 |  | ||||||
|  |  | ||||||
|     size = (max - min) |  | ||||||
|  |  | ||||||
|     clusters = {} |  | ||||||
|  |  | ||||||
|     cluster_size = size / np.array(cluster_dims, dtype=np.float32) |  | ||||||
|  |  | ||||||
|     print('Min: ' + str(min) + ' Max: ' + str(max)) |  | ||||||
|     print('Cluster Size: ' + str(cluster_size)) |  | ||||||
|  |  | ||||||
|     for row in data: |  | ||||||
|  |  | ||||||
|         # print('Row: ' + str(row)) |  | ||||||
|  |  | ||||||
|         cluster_pos = ((row[:3] - min) / cluster_size).astype(int) |  | ||||||
|         cluster_idx = cluster_dims[0] * cluster_dims[2] * cluster_pos[1] + cluster_dims[0] * cluster_pos[2] + cluster_pos[0] |  | ||||||
|         clusters.setdefault(cluster_idx, []).append(row) |  | ||||||
|  |  | ||||||
|     # Apply farthest point sampling to each cluster |  | ||||||
|     final_clusters = [] |  | ||||||
|     for key, cluster in clusters.items(): |  | ||||||
|         c = np.vstack(cluster) |  | ||||||
|         if c.shape[0] < min_points_per_cluster: |  | ||||||
|             continue |  | ||||||
|  |  | ||||||
|         final_clusters.append(farthest_point_sampling(c, max_points_per_cluster)) |  | ||||||
|  |  | ||||||
|     return final_clusters |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def extract_clusters(data, selected_indices, eps, min_samples, metric='euclidean', algo='auto'): | def extract_clusters(data, selected_indices, eps, min_samples, metric='euclidean', algo='auto'): | ||||||
|  |  | ||||||
|     min_samples = min_samples * len(data) |     min_samples = min_samples * len(data) | ||||||
| @@ -243,7 +194,7 @@ sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/../')  # add proj | |||||||
|  |  | ||||||
| parser = argparse.ArgumentParser() | parser = argparse.ArgumentParser() | ||||||
| parser.add_argument('--npoints', type=int, default=2048, help='resample points number') | parser.add_argument('--npoints', type=int, default=2048, help='resample points number') | ||||||
| parser.add_argument('--model', type=str, default='./checkpoint/seg_model_custom_30.pth', help='model path') | parser.add_argument('--model', type=str, default='./checkpoint/seg_model_custom_0.pth', help='model path') | ||||||
| parser.add_argument('--sample_idx', type=int, default=0, help='select a sample to segment and view result') | parser.add_argument('--sample_idx', type=int, default=0, help='select a sample to segment and view result') | ||||||
| parser.add_argument('--headers', type=strtobool, default=True, help='if raw files come with headers') | parser.add_argument('--headers', type=strtobool, default=True, help='if raw files come with headers') | ||||||
| parser.add_argument('--collate_per_segment', type=strtobool, default=True, help='whether to look at pointclouds or sub') | parser.add_argument('--collate_per_segment', type=strtobool, default=True, help='whether to look at pointclouds or sub') | ||||||
| @@ -260,41 +211,46 @@ if __name__ == '__main__': | |||||||
|     print('Create data set ..') |     print('Create data set ..') | ||||||
|  |  | ||||||
|     dataset_folder = './data/raw/predict/' |     dataset_folder = './data/raw/predict/' | ||||||
|     pointcloud_file = './pointclouds/0_pc.xyz' |     pointcloud_file = './pointclouds/0_0.xyz' | ||||||
|  |  | ||||||
|     # Load and pre-process point cloud |     # Load and pre-process point cloud | ||||||
|     pcloud = pc.read_pointcloud(pointcloud_file) |     pcloud = pc.read_pointcloud(pointcloud_file) | ||||||
|     pcloud = normalize_pointcloud(pcloud) |     pcloud = pc.normalize_pointcloud(pcloud, 1) | ||||||
|     # pcloud = append_normal_angles(pcloud) |  | ||||||
|     # pcloud = farthest_point_sampling(pcloud, opt.npoints) |  | ||||||
|  |  | ||||||
|     # Test: Pre-predict clustering |     #a, b = pc.split_outliers(pcloud, [3, 4, 5]) | ||||||
|     print("point cloud size: ", pcloud.shape) |     #draw_sample_data(a, True) | ||||||
|     clusters = extract_clusters(pcloud, [0, 1, 2, 3, 4, 5], eps=0.10, min_samples=0.005, |     #draw_sample_data(b, True) | ||||||
|                                 metric='euclidean', algo='auto') |     #pcloud = a | ||||||
|     #draw_clusters(clusters) |  | ||||||
|  |  | ||||||
|     # pc = StandardScaler().fit_transform(pc) |  | ||||||
|  |  | ||||||
|     recreate_folder(dataset_folder) |     # for 0_0.xyz: pc.hierarchical_clustering(pcloud, [0, 1, 2, 3, 4, 5], eps=0.1, min_samples=5) | ||||||
|  |  | ||||||
|     # Add full point cloud to prediction folder. |  | ||||||
|     # recreate_folder(dataset_folder + '0_0' + '/') |  | ||||||
|     # pc_fps = farthest_point_sampling(pcloud, opt.npoints) |  | ||||||
|     # pc.write_pointcloud(dataset_folder + '0_0' + '/pc.xyz', pc_fps) |  | ||||||
|  |  | ||||||
|     # Add cluster point clouds to prediction folder. |     # pc_clusters = pc.hierarchical_clustering(pcloud, [0, 1, 2, 3, 4, 5], eps=0.1, min_samples=5) | ||||||
|     pc_clusters = extract_cube_clusters(pcloud, [4, 4, 4], 2048, 100) |     # pc_clusters = pc.filter_clusters(pc_clusters, 100) | ||||||
|     # pc_clusters = extract_clusters(pc, [0, 1, 2, 3, 4, 5], eps=0.1, min_samples=0.0001, metric='euclidean', algo='auto') |  | ||||||
|  |     pc_clusters = [pcloud] | ||||||
|  |  | ||||||
|  |     print("NUM CLUSTERS: ", len(pc_clusters)) | ||||||
|  |  | ||||||
|     draw_clusters(pc_clusters) |     draw_clusters(pc_clusters) | ||||||
|  |     for c in pc_clusters: | ||||||
|  |         draw_sample_data(c, True) | ||||||
|  |         print("Cluster Size: ", len(c)) | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     # draw_sample_data(pcloud) | ||||||
|  |  | ||||||
|  |     pc_clusters = pc.cluster_cubes(pcloud, [1, 1, 1]) | ||||||
|  |  | ||||||
|  |     recreate_folder(dataset_folder) | ||||||
|     for idx, pcc in enumerate(pc_clusters): |     for idx, pcc in enumerate(pc_clusters): | ||||||
|         print("Cluster shape: ", pcc.shape) |  | ||||||
|         pcc = farthest_point_sampling(pcc, opt.npoints) |         pcc = farthest_point_sampling(pcc, opt.npoints) | ||||||
|         recreate_folder(dataset_folder + str(idx) + '/') |         recreate_folder(dataset_folder + str(idx) + '/') | ||||||
|         pc.write_pointcloud(dataset_folder + str(idx) + '/pc.xyz', pcc) |         pc.write_pointcloud(dataset_folder + str(idx) + '/pc.xyz', pcc) | ||||||
|         #draw_sample_data(pcc, False) |         # draw_sample_data(pcc, False) | ||||||
|  |  | ||||||
|     # Load dataset |     # Load dataset | ||||||
|     print('load dataset ..') |     print('load dataset ..') | ||||||
| @@ -317,7 +273,6 @@ if __name__ == '__main__': | |||||||
|     device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu') |     device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu') | ||||||
|     dtype = torch.float |     dtype = torch.float | ||||||
|  |  | ||||||
|     # net = PointNetPartSegmentNet(num_classes) |  | ||||||
|     net = PointNet2PartSegmentNet(num_classes) |     net = PointNet2PartSegmentNet(num_classes) | ||||||
|  |  | ||||||
|     net.load_state_dict(torch.load(opt.model, map_location=device.type)) |     net.load_state_dict(torch.load(opt.model, map_location=device.type)) | ||||||
| @@ -334,58 +289,18 @@ if __name__ == '__main__': | |||||||
|         pred_label, gt_label = eval_sample(net, sample) |         pred_label, gt_label = eval_sample(net, sample) | ||||||
|         sample_data = np.column_stack((sample["points"].numpy(), sample["normals"].numpy(), pred_label.numpy())) |         sample_data = np.column_stack((sample["points"].numpy(), sample["normals"].numpy(), pred_label.numpy())) | ||||||
|  |  | ||||||
|         draw_sample_data(sample_data, False) |  | ||||||
|  |  | ||||||
|         #print("Sample Datat: ", sample_data[:5, :]) |  | ||||||
|         #print('Eval done.') |  | ||||||
|         print("PRED LABEL: ", pred_label) |  | ||||||
|  |  | ||||||
|         #sample_data = normalize_pointcloud(sample_data) |  | ||||||
|         #sample_data = append_onehotencoded_type(sample_data, 1.0) |  | ||||||
|         #sample_data = append_normal_angles(sample_data) |  | ||||||
|  |  | ||||||
|         # print('Clustering ..') |  | ||||||
|         # print('Shape: ' + str(sample_data.shape)) |  | ||||||
|  |  | ||||||
|         # clusters = extract_clusters(sample_data, [0, 1, 2, 3, 4, 5, 7, 8, 9, 10], eps=0.1, min_samples=0.0001, metric='euclidean', algo='auto') |  | ||||||
|         # print('Clustering done. ' + str(len(clusters)) + " Clusters.") |  | ||||||
|         # print(sample_data[:, 6]) |  | ||||||
|  |  | ||||||
|         # draw_sample_data(sample_data, False) |  | ||||||
|  |  | ||||||
|         # result_clusters.extend(clusters) |  | ||||||
|         # result_clusters.append(sample_data) |  | ||||||
|  |  | ||||||
|         if labeled_dataset is None: |         if labeled_dataset is None: | ||||||
|             labeled_dataset = sample_data |             labeled_dataset = sample_data | ||||||
|         else: |         else: | ||||||
|             labeled_dataset = np.vstack((labeled_dataset, sample_data)) |             labeled_dataset = np.vstack((labeled_dataset, sample_data)) | ||||||
|  |  | ||||||
|     #draw_clusters(result_clusters) |         print("prediction done") | ||||||
|  |  | ||||||
|     draw_sample_data(labeled_dataset, False) |     draw_sample_data(labeled_dataset, False) | ||||||
|  |  | ||||||
|     print("point cloud size: ", labeled_dataset.shape) |     print("point cloud size: ", labeled_dataset.shape) | ||||||
|  |  | ||||||
|     print("Min: ", np.min(labeled_dataset[:, :3])) |     print("Min: ", np.min(labeled_dataset[:, :3])) | ||||||
|     print("Max: ", np.max(labeled_dataset[:, :3])) |     print("Max: ", np.max(labeled_dataset[:, :3])) | ||||||
|     print("Min: ", np.min(pcloud[:, :3])) |     print("Min: ", np.min(pcloud[:, :3])) | ||||||
|     print("Max: ", np.max(pcloud[:, :3])) |     print("Max: ", np.max(pcloud[:, :3])) | ||||||
|     #print("Data Set: ", labeled_dataset[:5, :]) |  | ||||||
|     labeled_dataset = normalize_pointcloud(labeled_dataset) |  | ||||||
|     labeled_dataset = append_normal_angles(labeled_dataset) |  | ||||||
|     #labeled_dataset = farthest_point_sampling(labeled_dataset, opt.npoints) |  | ||||||
|  |  | ||||||
|     labeled_dataset = append_onehotencoded_type(labeled_dataset, 1.0) |  | ||||||
|  |  | ||||||
|     clusters = extract_clusters(labeled_dataset, [0, 1, 2, 3, 4, 5], eps=0.10, min_samples=0.005, |  | ||||||
|                                 metric='euclidean', algo='auto') |  | ||||||
|  |  | ||||||
|     #total_clusters = [] |  | ||||||
|     #for cluster in clusters: |  | ||||||
|     #    sub_clusters = extract_clusters(cluster, [7,8,9], eps=0.10, min_samples=0.05, |  | ||||||
|     #                                metric='euclidean', algo='auto') |  | ||||||
|     #    total_clusters.extend(sub_clusters) |  | ||||||
|  |  | ||||||
|     draw_clusters(clusters) |  | ||||||
|  |  | ||||||
|     pc.write_clusters("clusters.txt", clusters) |  | ||||||
		Reference in New Issue
	
	Block a user
	 Markus Friedrich
					Markus Friedrich