From acce1c8d803d8bce6255fe8ee80e80d1aef2aa67 Mon Sep 17 00:00:00 2001 From: SVivdich02 Date: Sat, 13 Apr 2024 11:38:28 +0300 Subject: [PATCH 01/21] add scripts for processing the kitty dataset and for calculating result metrics from a csv file --- main_kitti_processing.py | 185 +++++++++++++++++++++++++++++++ main_kitti_processing_metrics.py | 132 ++++++++++++++++++++++ 2 files changed, 317 insertions(+) create mode 100644 main_kitti_processing.py create mode 100644 main_kitti_processing_metrics.py diff --git a/main_kitti_processing.py b/main_kitti_processing.py new file mode 100644 index 0000000..74036b1 --- /dev/null +++ b/main_kitti_processing.py @@ -0,0 +1,185 @@ +# Copyright (c) 2023, Sofia Vivdich and Anastasiia Kornilova +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import copy +import numpy as np +import pickle + +from scipy.spatial.distance import cdist + +from src.datasets.kitti_dataset import KittiDataset + +from src.services.distance.isolated import RemovingIsolatedPointsProcessor +from src.services.distance.connected_component import ExtractionLargestConnectedComponentProcessor +from src.services.normalized_cut_service import normalized_cut +from src.services.preprocessing.common.config import ConfigDTO +from src.services.preprocessing.init.map import InitMapProcessor +from src.services.preprocessing.init.instances_matrix import ( + InitInstancesMatrixProcessor, +) +from src.services.preprocessing.not_zero import SelectionNotZeroProcessor +from src.services.preprocessing.in_cube import SelectionInCubeProcessor +from src.services.preprocessing.statistical_outlier import StatisticalOutlierProcessor +from src.services.preprocessing.voxel_down import VoxelDownProcessor + +from src.utils.distances_utils import sam_label_distance +from src.utils.gt_utils import build_sem_inst_label_arrays + + +dataset_path = "dataset/" +sequence = "00" +image_instances_path = "pipeline/vfm-labelss/sam/00/" +gt_labels_path = "dataset/sequences/00/labels/" +kitti = KittiDataset(dataset_path, sequence, image_instances_path) + + +def build_tuple_bin_saving(config, pcd_for_clustering, trace, clusters, inst_label_array_for_clustering, sem_label_array_for_clustering): + params = {} + params['alpha_physical_distance'] = config.alpha_physical_distance + params['beta_instance_distance'] = config.beta_instance_distance + params['T_normalized_cut'] = config.T_normalized_cut + params['reduce_detail_int_to_union_threshold'] = config.reduce_detail_int_to_union_threshold + params['reduce_detail_int_to_mask_threshold'] = config.reduce_detail_int_to_mask_threshold + + trace_arrays = [] + for int_vector in (trace): + trace_arrays.append(np.asarray(int_vector)) + + return (params, np.asarray(pcd_for_clustering.points), trace_arrays, clusters, inst_label_array_for_clustering, sem_label_array_for_clustering) + + +def segment_pcds(config): + init_pcd = InitMapProcessor().process(config) + points2instances = InitInstancesMatrixProcessor().process(config, init_pcd) + + sem_label_array_src, inst_label_array_src = build_sem_inst_label_arrays(gt_labels_path, + config.start_index, + config.end_index) + + processors = [ + SelectionNotZeroProcessor(), + SelectionInCubeProcessor(), + StatisticalOutlierProcessor(), + ] + + pcd = copy.deepcopy(init_pcd) + for processor in processors: + pcd, points2instances, indices = processor.process(config, pcd, points2instances) + inst_label_array_src = inst_label_array_src[indices] + sem_label_array_src = sem_label_array_src[indices] + + pcd_for_clustering = copy.deepcopy(pcd) + points2instances_pcd_for_clustering = copy.deepcopy(points2instances) + inst_label_array_for_clustering = copy.deepcopy(inst_label_array_src) + sem_label_array_for_clustering = copy.deepcopy(sem_label_array_src) + + pcd, points2instances, trace = VoxelDownProcessor().process(config, pcd, points2instances) + + points = np.asarray(pcd.points) + spatial_distance = cdist(points, points) + + dist, masks = sam_label_distance(points2instances, spatial_distance, 3, config.beta_instance_distance, config.alpha_physical_distance) + + distance_processors = [ + RemovingIsolatedPointsProcessor(), + ExtractionLargestConnectedComponentProcessor(), + ] + + for processor in distance_processors: + dist, points, trace = processor.process(dist, points, trace) + + eigenval = 2 + clusters = normalized_cut( + dist, + np.array([i for i in range(len(points))], dtype=int), + config.T_normalized_cut, + eigenval + ) + + return build_tuple_bin_saving( + config, + copy.deepcopy(pcd_for_clustering), + copy.deepcopy(trace), + copy.deepcopy(clusters), + copy.deepcopy(inst_label_array_for_clustering), + copy.deepcopy(sem_label_array_for_clustering), + ) + + +def process_kitti(from_num, to_num, id_exec, alpha_physical_distance, beta_instance_distance): + T_normalized_cut = 0.03 + + reduce_detail_int_to_union_threshold = 0.5 + reduce_detail_int_to_mask_threshold = 0.6 + + current_from_num = from_num + + while (current_from_num < to_num): + start_index = current_from_num + end_index = start_index + 4 + config = ConfigDTO( + **{ + "dataset": kitti, + "start_index": start_index, + "end_index": end_index, + "start_image_index_offset": 0, + "alpha_physical_distance": alpha_physical_distance, + "beta_instance_distance": beta_instance_distance, + "T_normalized_cut": T_normalized_cut, + "reduce_detail_int_to_union_threshold": reduce_detail_int_to_union_threshold, + "reduce_detail_int_to_mask_threshold": reduce_detail_int_to_mask_threshold, + "cam_name": "cam2", + "R": 18, + "nb_neighbors": 25, + "std_ratio": 5.0, + "voxel_size": 0.25, + } + ) + + result_tuple = segment_pcds(config) + + file_name = "experiment_bin_0704_4_sem_offset0_T0l03/start{}_end{}.pickle".format(config.start_index, config.end_index) + new_file = open(file_name, 'w') + new_file.close() + + with open(file_name, 'wb') as file: + pickle.dump(result_tuple, file) + + print("start_index={}, end_index={} done".format(start_index, end_index)) + current_from_num = end_index + + +def main(): + + # alpha_physical_distance_1 = 5 + # beta_instance_distance_1 = 3 + # process_kitti(0, 4, 1, alpha_physical_distance_1, beta_instance_distance_1) + + # alpha_physical_distance_2 = 5 + # beta_instance_distance_2 = 5 + # process_kitti(0, 4, 2, alpha_physical_distance_2, beta_instance_distance_2) + + # alpha_physical_distance_3 = 3 + # beta_instance_distance_3 = 5 + # process_kitti(0, 4, 3, alpha_physical_distance_3, beta_instance_distance_3) + + alpha_physical_distance_4 = 5 + beta_instance_distance_4 = 5 + # T_4 = 0.025 + # offset = 0 + process_kitti(0, 4540, 4, alpha_physical_distance_4, beta_instance_distance_4) + + +if __name__ == "__main__": + main() diff --git a/main_kitti_processing_metrics.py b/main_kitti_processing_metrics.py new file mode 100644 index 0000000..4c44df8 --- /dev/null +++ b/main_kitti_processing_metrics.py @@ -0,0 +1,132 @@ +# Copyright (c) 2023, Sofia Vivdich and Anastasiia Kornilova +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import copy +import csv +import numpy as np +import pickle + +from evops.metrics import precision +from evops.metrics import recall +from evops.metrics import fScore + + +def find_num_in_inst_label_array(src_points, inst_label_array_for_clustering): + for point in src_points: + if inst_label_array_for_clustering[point] > 0: + return inst_label_array_for_clustering[point] + return -1 + + +def build_pred_inst_array(inst_label_array_for_clustering, clusters, trace, instance_threshold): + pred_inst_array = np.zeros(len(inst_label_array_for_clustering), dtype=int) + k = 0 + free_id = 1 + for cluster in clusters: + voxel_not_in_gt_cluster_count = 0 + for voxel in cluster: + src_points = trace[voxel] + id = find_num_in_inst_label_array(src_points, inst_label_array_for_clustering) + if id == -1: + voxel_not_in_gt_cluster_count += 1 + + cluster_in_gt_instance = ((len(cluster) - voxel_not_in_gt_cluster_count) / len(cluster)) * 100 + if cluster_in_gt_instance >= instance_threshold: + for voxel in cluster: + src_points = trace[voxel] + for src_point in src_points: + pred_inst_array[src_point] = free_id + free_id += 1 + k += 1 + return pred_inst_array + + +def main(): + + from_num = 0 + to_num = 4540 + + # execution_ids = [ 1, 2, 3, 4 ] + execution_ids = [ 4 ] + instance_thresholds = [ 5, 20, 30, 50 ] + + for execution_id in execution_ids: + + for instance_threshold in instance_thresholds: + print("Start to process instance_threshold={}".format(instance_threshold)) + + current_from_num = from_num + + skipped = 0 + while (current_from_num < to_num): + start_index = current_from_num + end_index = start_index + 4 + + file_name = "experiment_bin_0704_4_sem_offset0_T0l03/start{}_end{}.pickle".format(start_index, end_index) + + with open(file_name, 'rb') as file: + data = pickle.load(file) + + trace = data[2] + clusters = data[3] + inst_label_array_for_clustering = data[4] + + if inst_label_array_for_clustering.sum() == 0: # в облаке нет инстансов => скип + skipped += 1 + print("start_index={}, end_index={} skip".format(start_index, end_index)) + current_from_num = end_index + continue + + pred_inst_array = build_pred_inst_array( + copy.deepcopy(inst_label_array_for_clustering), + clusters, + copy.deepcopy(trace), + instance_threshold + ) + + pred_labels = pred_inst_array + gt_labels = inst_label_array_for_clustering + tp_condition = "iou" + precision_res = precision(pred_labels, gt_labels, tp_condition) + recall_res = recall(pred_labels, gt_labels, tp_condition) + fScore_res = fScore(pred_labels, gt_labels, tp_condition) + + gt_labels_unique = set(gt_labels) + gt_labels_unique.discard(0) + + pred_labels_unique = set(pred_labels) + pred_labels_unique.discard(0) + + with open("experiment_1004_{}_without0_sem_offset0_T0l03_{}.csv".format(execution_id, instance_threshold), "a", newline="") as file: + writer = csv.writer(file) + + writer.writerow([ + str(start_index), + str(end_index), + str(precision_res), + str(recall_res), + str(fScore_res), + len(gt_labels_unique), + len(pred_labels_unique), + len(clusters), + ]) + + current_from_num = end_index + + print(skipped) + print("Finish to process instance_threshold={}".format(instance_threshold)) + + +if __name__ == "__main__": + main() From eb703c8fb1fbee6f0913ca4ea5253af0c6d619ee Mon Sep 17 00:00:00 2001 From: SVivdich02 Date: Sat, 13 Apr 2024 17:01:48 +0300 Subject: [PATCH 02/21] refactoring --- main_kitti_processing.py | 93 +++++++++++++++++++------------- main_kitti_processing_metrics.py | 67 +++++++++++++++-------- 2 files changed, 101 insertions(+), 59 deletions(-) diff --git a/main_kitti_processing.py b/main_kitti_processing.py index 74036b1..4015394 100644 --- a/main_kitti_processing.py +++ b/main_kitti_processing.py @@ -21,7 +21,9 @@ from src.datasets.kitti_dataset import KittiDataset from src.services.distance.isolated import RemovingIsolatedPointsProcessor -from src.services.distance.connected_component import ExtractionLargestConnectedComponentProcessor +from src.services.distance.connected_component import ( + ExtractionLargestConnectedComponentProcessor, +) from src.services.normalized_cut_service import normalized_cut from src.services.preprocessing.common.config import ConfigDTO from src.services.preprocessing.init.map import InitMapProcessor @@ -44,28 +46,46 @@ kitti = KittiDataset(dataset_path, sequence, image_instances_path) -def build_tuple_bin_saving(config, pcd_for_clustering, trace, clusters, inst_label_array_for_clustering, sem_label_array_for_clustering): +def build_tuple_bin_saving( + config, + pcd_for_clustering, + trace, + clusters, + inst_label_array_for_clustering, + sem_label_array_for_clustering, +): params = {} - params['alpha_physical_distance'] = config.alpha_physical_distance - params['beta_instance_distance'] = config.beta_instance_distance - params['T_normalized_cut'] = config.T_normalized_cut - params['reduce_detail_int_to_union_threshold'] = config.reduce_detail_int_to_union_threshold - params['reduce_detail_int_to_mask_threshold'] = config.reduce_detail_int_to_mask_threshold + params["alpha_physical_distance"] = config.alpha_physical_distance + params["beta_instance_distance"] = config.beta_instance_distance + params["T_normalized_cut"] = config.T_normalized_cut + params["reduce_detail_int_to_union_threshold"] = ( + config.reduce_detail_int_to_union_threshold + ) + params["reduce_detail_int_to_mask_threshold"] = ( + config.reduce_detail_int_to_mask_threshold + ) trace_arrays = [] - for int_vector in (trace): + for int_vector in trace: trace_arrays.append(np.asarray(int_vector)) - return (params, np.asarray(pcd_for_clustering.points), trace_arrays, clusters, inst_label_array_for_clustering, sem_label_array_for_clustering) + return ( + params, + np.asarray(pcd_for_clustering.points), + trace_arrays, + clusters, + inst_label_array_for_clustering, + sem_label_array_for_clustering, + ) def segment_pcds(config): init_pcd = InitMapProcessor().process(config) points2instances = InitInstancesMatrixProcessor().process(config, init_pcd) - sem_label_array_src, inst_label_array_src = build_sem_inst_label_arrays(gt_labels_path, - config.start_index, - config.end_index) + sem_label_array_src, inst_label_array_src = build_sem_inst_label_arrays( + gt_labels_path, config.start_index, config.end_index + ) processors = [ SelectionNotZeroProcessor(), @@ -75,7 +95,9 @@ def segment_pcds(config): pcd = copy.deepcopy(init_pcd) for processor in processors: - pcd, points2instances, indices = processor.process(config, pcd, points2instances) + pcd, points2instances, indices = processor.process( + config, pcd, points2instances + ) inst_label_array_src = inst_label_array_src[indices] sem_label_array_src = sem_label_array_src[indices] @@ -84,12 +106,20 @@ def segment_pcds(config): inst_label_array_for_clustering = copy.deepcopy(inst_label_array_src) sem_label_array_for_clustering = copy.deepcopy(sem_label_array_src) - pcd, points2instances, trace = VoxelDownProcessor().process(config, pcd, points2instances) + pcd, points2instances, trace = VoxelDownProcessor().process( + config, pcd, points2instances + ) points = np.asarray(pcd.points) spatial_distance = cdist(points, points) - dist, masks = sam_label_distance(points2instances, spatial_distance, 3, config.beta_instance_distance, config.alpha_physical_distance) + dist, masks = sam_label_distance( + points2instances, + spatial_distance, + 3, + config.beta_instance_distance, + config.alpha_physical_distance, + ) distance_processors = [ RemovingIsolatedPointsProcessor(), @@ -104,7 +134,7 @@ def segment_pcds(config): dist, np.array([i for i in range(len(points))], dtype=int), config.T_normalized_cut, - eigenval + eigenval, ) return build_tuple_bin_saving( @@ -117,7 +147,9 @@ def segment_pcds(config): ) -def process_kitti(from_num, to_num, id_exec, alpha_physical_distance, beta_instance_distance): +def process_kitti( + from_num, to_num, id_exec, alpha_physical_distance, beta_instance_distance +): T_normalized_cut = 0.03 reduce_detail_int_to_union_threshold = 0.5 @@ -125,7 +157,7 @@ def process_kitti(from_num, to_num, id_exec, alpha_physical_distance, beta_insta current_from_num = from_num - while (current_from_num < to_num): + while current_from_num < to_num: start_index = current_from_num end_index = start_index + 4 config = ConfigDTO( @@ -149,11 +181,15 @@ def process_kitti(from_num, to_num, id_exec, alpha_physical_distance, beta_insta result_tuple = segment_pcds(config) - file_name = "experiment_bin_0704_4_sem_offset0_T0l03/start{}_end{}.pickle".format(config.start_index, config.end_index) - new_file = open(file_name, 'w') + file_name = ( + "experiment_bin_0704_{}_sem_offset0_T0l03/start{}_end{}.pickle".format( + id_exec, config.start_index, config.end_index + ) + ) + new_file = open(file_name, "w") new_file.close() - with open(file_name, 'wb') as file: + with open(file_name, "wb") as file: pickle.dump(result_tuple, file) print("start_index={}, end_index={} done".format(start_index, end_index)) @@ -161,23 +197,8 @@ def process_kitti(from_num, to_num, id_exec, alpha_physical_distance, beta_insta def main(): - - # alpha_physical_distance_1 = 5 - # beta_instance_distance_1 = 3 - # process_kitti(0, 4, 1, alpha_physical_distance_1, beta_instance_distance_1) - - # alpha_physical_distance_2 = 5 - # beta_instance_distance_2 = 5 - # process_kitti(0, 4, 2, alpha_physical_distance_2, beta_instance_distance_2) - - # alpha_physical_distance_3 = 3 - # beta_instance_distance_3 = 5 - # process_kitti(0, 4, 3, alpha_physical_distance_3, beta_instance_distance_3) - alpha_physical_distance_4 = 5 beta_instance_distance_4 = 5 - # T_4 = 0.025 - # offset = 0 process_kitti(0, 4540, 4, alpha_physical_distance_4, beta_instance_distance_4) diff --git a/main_kitti_processing_metrics.py b/main_kitti_processing_metrics.py index 4c44df8..794c7ba 100644 --- a/main_kitti_processing_metrics.py +++ b/main_kitti_processing_metrics.py @@ -29,7 +29,9 @@ def find_num_in_inst_label_array(src_points, inst_label_array_for_clustering): return -1 -def build_pred_inst_array(inst_label_array_for_clustering, clusters, trace, instance_threshold): +def build_pred_inst_array( + inst_label_array_for_clustering, clusters, trace, instance_threshold +): pred_inst_array = np.zeros(len(inst_label_array_for_clustering), dtype=int) k = 0 free_id = 1 @@ -37,11 +39,15 @@ def build_pred_inst_array(inst_label_array_for_clustering, clusters, trace, inst voxel_not_in_gt_cluster_count = 0 for voxel in cluster: src_points = trace[voxel] - id = find_num_in_inst_label_array(src_points, inst_label_array_for_clustering) + id = find_num_in_inst_label_array( + src_points, inst_label_array_for_clustering + ) if id == -1: voxel_not_in_gt_cluster_count += 1 - cluster_in_gt_instance = ((len(cluster) - voxel_not_in_gt_cluster_count) / len(cluster)) * 100 + cluster_in_gt_instance = ( + (len(cluster) - voxel_not_in_gt_cluster_count) / len(cluster) + ) * 100 if cluster_in_gt_instance >= instance_threshold: for voxel in cluster: src_points = trace[voxel] @@ -57,9 +63,8 @@ def main(): from_num = 0 to_num = 4540 - # execution_ids = [ 1, 2, 3, 4 ] - execution_ids = [ 4 ] - instance_thresholds = [ 5, 20, 30, 50 ] + execution_ids = [4] + instance_thresholds = [5, 20, 30, 50] for execution_id in execution_ids: @@ -69,22 +74,30 @@ def main(): current_from_num = from_num skipped = 0 - while (current_from_num < to_num): + while current_from_num < to_num: start_index = current_from_num end_index = start_index + 4 - file_name = "experiment_bin_0704_4_sem_offset0_T0l03/start{}_end{}.pickle".format(start_index, end_index) + file_name = "experiment_bin_0704_4_sem_offset0_T0l03/start{}_end{}.pickle".format( + start_index, end_index + ) - with open(file_name, 'rb') as file: + with open(file_name, "rb") as file: data = pickle.load(file) trace = data[2] clusters = data[3] inst_label_array_for_clustering = data[4] - if inst_label_array_for_clustering.sum() == 0: # в облаке нет инстансов => скип + if ( + inst_label_array_for_clustering.sum() == 0 + ): # в облаке нет инстансов => пропускаем skipped += 1 - print("start_index={}, end_index={} skip".format(start_index, end_index)) + print( + "start_index={}, end_index={} skip".format( + start_index, end_index + ) + ) current_from_num = end_index continue @@ -92,7 +105,7 @@ def main(): copy.deepcopy(inst_label_array_for_clustering), clusters, copy.deepcopy(trace), - instance_threshold + instance_threshold, ) pred_labels = pred_inst_array @@ -108,19 +121,27 @@ def main(): pred_labels_unique = set(pred_labels) pred_labels_unique.discard(0) - with open("experiment_1004_{}_without0_sem_offset0_T0l03_{}.csv".format(execution_id, instance_threshold), "a", newline="") as file: + with open( + "experiment_1004_{}_without0_sem_offset0_T0l03_{}.csv".format( + execution_id, instance_threshold + ), + "a", + newline="", + ) as file: writer = csv.writer(file) - writer.writerow([ - str(start_index), - str(end_index), - str(precision_res), - str(recall_res), - str(fScore_res), - len(gt_labels_unique), - len(pred_labels_unique), - len(clusters), - ]) + writer.writerow( + [ + str(start_index), + str(end_index), + str(precision_res), + str(recall_res), + str(fScore_res), + len(gt_labels_unique), + len(pred_labels_unique), + len(clusters), + ] + ) current_from_num = end_index From 95f951291a781295475dfef8080b9d45871a89f5 Mon Sep 17 00:00:00 2001 From: SVivdich02 Date: Sat, 13 Apr 2024 18:33:07 +0300 Subject: [PATCH 03/21] kitti processing with hdbscan notebook --- main_hdbscan_processing.ipynb | 342 ++++++++++++++++++++++++++++++++++ 1 file changed, 342 insertions(+) create mode 100644 main_hdbscan_processing.ipynb diff --git a/main_hdbscan_processing.ipynb b/main_hdbscan_processing.ipynb new file mode 100644 index 0000000..c4b9c69 --- /dev/null +++ b/main_hdbscan_processing.ipynb @@ -0,0 +1,342 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import copy\n", + "import numpy as np\n", + "import open3d as o3d\n", + "import random\n", + "\n", + "def generate_random_colors(N):\n", + " colors = [[0, 0, 0]]\n", + " for _ in range(N):\n", + " colors.append(\n", + " [random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)]\n", + " )\n", + "\n", + " colors = np.vstack(colors) / 255\n", + " return colors\n", + "\n", + "def color_pcd_by_labels1(pcd, labels):\n", + " colors = generate_random_colors(len(labels) + 1)\n", + " pcd_colored = copy.deepcopy(pcd)\n", + " pcd_colored.colors = o3d.utility.Vector3dVector(\n", + " np.zeros(np.asarray(pcd.points).shape)\n", + " )\n", + "\n", + " for i in range(len(pcd_colored.points)):\n", + " if labels[i] == 0 or labels[i] == -1:\n", + " continue\n", + " pcd_colored.colors[i] = colors[labels[i]]\n", + "\n", + " return pcd_colored" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import pickle\n", + "\n", + "start_num = 20\n", + "end_num = start_num + 4\n", + "\n", + "file_name = \"experiment_bin_0704_4_sem_offset0_T0l03/start{}_end{}.pickle\".format(start_num, end_num)\n", + "\n", + "with open(file_name, 'rb') as file:\n", + " data = pickle.load(file)\n", + "\n", + "print(data[0]) # значения гиперпараметров запуска" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from sklearn.cluster import HDBSCAN\n", + "\n", + "clusterer = HDBSCAN()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import open3d as o3d\n", + "\n", + "X = np.asarray(data[1]) # точки обработанного облака ДО вокселизации\n", + "pcd_hdbscan = o3d.geometry.PointCloud()\n", + "pcd_hdbscan.points = o3d.utility.Vector3dVector(X)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import copy\n", + "\n", + "# проведение точно такой же вокселизации, как и в моем алгоритме\n", + "\n", + "pcd_hdbscan_copy = copy.deepcopy(pcd_hdbscan)\n", + "\n", + "min_bound = pcd_hdbscan_copy.get_min_bound()\n", + "max_bound = pcd_hdbscan_copy.get_max_bound()\n", + "\n", + "downpcd_trace = pcd_hdbscan_copy.voxel_down_sample_and_trace(\n", + " 0.25, min_bound, max_bound, True\n", + ")\n", + "\n", + "downpcd = downpcd_trace[0]\n", + "trace_hdbscan = downpcd_trace[2]\n", + "\n", + "print(\"voxel_down_pcd_size={}\".format(len(downpcd.points)))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# проверяем, что вокселизация привела облако в то состояние,\n", + "# при котором проводилась сегментация моим алгоритмом\n", + "\n", + "trace_arrays = []\n", + "for int_vector in trace_hdbscan:\n", + " trace_arrays.append(np.asarray(int_vector))\n", + "\n", + "for ind, el in enumerate(trace_arrays):\n", + " if (el != data[2][ind]).any():\n", + " print(\"ERROR\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# сегментация HDBSCAN\n", + "\n", + "clusters = clusterer.fit_predict(np.asarray(downpcd.points))\n", + "print(set(clusters))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import copy\n", + "\n", + "from src.utils.pcd_utils import visualize_pcd\n", + "\n", + "colored_pcd = color_pcd_by_labels1(copy.deepcopy(downpcd), clusters)\n", + "visualize_pcd(colored_pcd)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# приводим результаты кластеризации к листу, элементы которого - массивы точек одного кластера\n", + "\n", + "clusters_list = []\n", + "\n", + "print(\"before set(clusters)={}\".format(set(clusters)))\n", + "# метки 0 и -1 означают шум, они для нас равны\n", + "for ind, label in enumerate(clusters):\n", + " if label == -1:\n", + " clusters[ind] = 0\n", + "print(\"after set(clusters)={}\".format(set(clusters)))\n", + "\n", + "# инициализация листа\n", + "for label in set(clusters):\n", + " clusters_list.append([])\n", + "\n", + "for ind, label in enumerate(clusters):\n", + " clusters_list[label].append(ind)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import copy\n", + "\n", + "from src.utils.pcd_utils import color_pcd_by_clusters_and_voxels\n", + "from src.utils.pcd_utils import visualize_pcd\n", + "\n", + "colored_pcd = color_pcd_by_clusters_and_voxels(\n", + " copy.deepcopy(pcd_hdbscan_copy), copy.deepcopy(trace_hdbscan), clusters_list\n", + ")\n", + "visualize_pcd(colored_pcd)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# выборка из кластеризации только инстансов\n", + "\n", + "def find_num_in_inst_label_array(src_points, inst_label_array_for_clustering):\n", + " for point in src_points:\n", + " if inst_label_array_for_clustering[point] > 0:\n", + " return inst_label_array_for_clustering[point]\n", + " return -1\n", + "\n", + "\n", + "def build_pred_inst_array(\n", + " inst_label_array_for_clustering, clusters, trace, instance_threshold\n", + "):\n", + " pred_inst_array = np.zeros(len(inst_label_array_for_clustering), dtype=int)\n", + " free_id = 1\n", + " for cluster in clusters:\n", + " voxel_not_in_gt_cluster_count = 0\n", + " for voxel in cluster:\n", + " src_points = trace[voxel]\n", + " id = find_num_in_inst_label_array(\n", + " src_points, inst_label_array_for_clustering\n", + " )\n", + " if id == -1:\n", + " voxel_not_in_gt_cluster_count += 1\n", + "\n", + " cluster_in_gt_instance = (\n", + " (len(cluster) - voxel_not_in_gt_cluster_count) / len(cluster)\n", + " ) * 100\n", + " if cluster_in_gt_instance >= instance_threshold:\n", + " for voxel in cluster:\n", + " src_points = trace[voxel]\n", + " for src_point in src_points:\n", + " pred_inst_array[src_point] = free_id\n", + " free_id += 1\n", + " return pred_inst_array" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "instance_threshold = 30\n", + "inst_label_array_for_clustering = data[4] # из pickle\n", + "\n", + "pred_inst_array = build_pred_inst_array(\n", + " copy.deepcopy(inst_label_array_for_clustering),\n", + " clusters_list,\n", + " copy.deepcopy(trace_hdbscan),\n", + " instance_threshold,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from evops.metrics import precision\n", + "from evops.metrics import recall\n", + "from evops.metrics import fScore\n", + "\n", + "pred_labels = pred_inst_array\n", + "gt_labels = inst_label_array_for_clustering\n", + "tp_condition = \"iou\"\n", + "print(\"precision={}\".format(precision(pred_labels, gt_labels, tp_condition)))\n", + "print(\"recall={}\".format(recall(pred_labels, gt_labels, tp_condition)))\n", + "print(\"fScore={}\".format(fScore(pred_labels, gt_labels, tp_condition)))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import copy\n", + "\n", + "from src.utils.pcd_utils import color_pcd_by_labels\n", + "from src.utils.pcd_utils import visualize_pcd\n", + "\n", + "colored_clusters_for_clustering = color_pcd_by_labels(\n", + " copy.deepcopy(pcd_hdbscan_copy), pred_labels\n", + ")\n", + "visualize_pcd(colored_clusters_for_clustering)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import copy\n", + "\n", + "from src.utils.pcd_utils import color_pcd_by_labels\n", + "from src.utils.pcd_utils import visualize_pcd\n", + "\n", + "colored_clusters_for_clustering = color_pcd_by_labels(\n", + " copy.deepcopy(pcd_hdbscan_copy), gt_labels\n", + ")\n", + "visualize_pcd(colored_clusters_for_clustering)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.6" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 4fc6aca4f6cd8a831080a50b513fede0d1912f95 Mon Sep 17 00:00:00 2001 From: SVivdich02 Date: Mon, 22 Apr 2024 13:04:31 +0300 Subject: [PATCH 04/21] fix scripts for processing kitti and eval metrics --- main_calc_metrics_by_csv.py | 75 ++++++++++++++++++++++++++++++++ main_kitti_processing.py | 71 +++++++++++++++++++++++++----- main_kitti_processing_metrics.py | 20 ++++----- 3 files changed, 143 insertions(+), 23 deletions(-) create mode 100644 main_calc_metrics_by_csv.py diff --git a/main_calc_metrics_by_csv.py b/main_calc_metrics_by_csv.py new file mode 100644 index 0000000..2c857e9 --- /dev/null +++ b/main_calc_metrics_by_csv.py @@ -0,0 +1,75 @@ +# Copyright (c) 2023, Sofia Vivdich and Anastasiia Kornilova +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import csv + + +def calculate_metrics(exec_id): + values_pres = [] + values_recall = [] + values_fScore = [] + with open("experiment_{}_sem_voxel_offset0_T0l02_50.csv".format(exec_id), "r") as file: + reader = csv.DictReader(file) + for row in reader: + values_pres.append(row['precision']) + values_recall.append(row['recall']) + values_fScore.append(row['fScore']) + + sum_pres = 0 + pres1 = 0 + pres0 = 0 + for value in values_pres: + sum_pres += float(value) + if float(value) == 1.0: + pres1 += 1 + if float(value) == 0.0: + pres0 += 1 + + sum_recall = 0 + recall1 = 0 + recall0 = 0 + for value in values_recall: + sum_recall += float(value) + if float(value) == 1.0: + recall1 += 1 + if float(value) == 0.0: + recall0 += 1 + + sum_fScore = 0 + fscore1 = 0 + fscore0 = 0 + for value in values_fScore: + sum_fScore += float(value) + if float(value) == 1.0: + fscore1 += 1 + if float(value) == 0.0: + fscore0 += 1 + + print("start exec_id={}".format(exec_id)) + print("precision={}, 1={}, 0={}".format(sum_pres/float(len(values_pres)), pres1, pres0)) + print("recall={}, 1={}, 0={}".format(sum_recall/float(len(values_recall)), recall1, recall0)) + print("fscore={}, 1={}, 0={}".format(sum_fScore/float(len(values_fScore)), fscore1, fscore0)) + print("finish exec_id={}".format(exec_id)) + + +def main(): + calculate_metrics(1) + calculate_metrics(2) + calculate_metrics(3) + calculate_metrics(4) + calculate_metrics(5) + + +if __name__ == "__main__": + main() diff --git a/main_kitti_processing.py b/main_kitti_processing.py index 4015394..e1b7b16 100644 --- a/main_kitti_processing.py +++ b/main_kitti_processing.py @@ -49,6 +49,8 @@ def build_tuple_bin_saving( config, pcd_for_clustering, + voxel_pcd, + voxel_src_trace, trace, clusters, inst_label_array_for_clustering, @@ -65,17 +67,23 @@ def build_tuple_bin_saving( config.reduce_detail_int_to_mask_threshold ) + src_trace_arrays = [] + for int_vector in voxel_src_trace: + src_trace_arrays.append(np.asarray(int_vector)) + trace_arrays = [] for int_vector in trace: trace_arrays.append(np.asarray(int_vector)) return ( - params, - np.asarray(pcd_for_clustering.points), - trace_arrays, - clusters, - inst_label_array_for_clustering, - sem_label_array_for_clustering, + {"config": params}, + {"pcd_for_clustering_before_voxelization_points": np.asarray(pcd_for_clustering.points)}, + {"voxel_pcd_original_points": np.asarray(voxel_pcd.points)}, + {"voxel_trace_original": src_trace_arrays}, + {"trace_graphcut": trace_arrays}, + {"clusters_graphcut": clusters}, + {"inst_label_array_for_clustering": inst_label_array_for_clustering}, + {"sem_label_array_for_clustering": sem_label_array_for_clustering}, ) @@ -109,6 +117,8 @@ def segment_pcds(config): pcd, points2instances, trace = VoxelDownProcessor().process( config, pcd, points2instances ) + voxel_pcd = copy.deepcopy(pcd) + voxel_src_trace = copy.deepcopy(trace) points = np.asarray(pcd.points) spatial_distance = cdist(points, points) @@ -140,6 +150,8 @@ def segment_pcds(config): return build_tuple_bin_saving( config, copy.deepcopy(pcd_for_clustering), + copy.deepcopy(voxel_pcd), + copy.deepcopy(voxel_src_trace), copy.deepcopy(trace), copy.deepcopy(clusters), copy.deepcopy(inst_label_array_for_clustering), @@ -148,9 +160,8 @@ def segment_pcds(config): def process_kitti( - from_num, to_num, id_exec, alpha_physical_distance, beta_instance_distance + from_num, to_num, id_exec, alpha_physical_distance, beta_instance_distance, T_normalized_cut ): - T_normalized_cut = 0.03 reduce_detail_int_to_union_threshold = 0.5 reduce_detail_int_to_mask_threshold = 0.6 @@ -182,7 +193,7 @@ def process_kitti( result_tuple = segment_pcds(config) file_name = ( - "experiment_bin_0704_{}_sem_offset0_T0l03/start{}_end{}.pickle".format( + "experiment_{}_sem_voxel_offset0_T0l02/start{}_end{}.pickle".format( id_exec, config.start_index, config.end_index ) ) @@ -197,9 +208,45 @@ def process_kitti( def main(): - alpha_physical_distance_4 = 5 - beta_instance_distance_4 = 5 - process_kitti(0, 4540, 4, alpha_physical_distance_4, beta_instance_distance_4) + exec_id_1 = 1 + alpha_physical_distance_1 = 5 + beta_instance_distance_1 = 3 + T_normalized_cut_1 = 0.02 + print("start exec_id={}".format(exec_id_1)) + process_kitti(1500, 4540, exec_id_1, alpha_physical_distance_1, beta_instance_distance_1, T_normalized_cut_1) + print("finish exec_id={}".format(exec_id_1)) + + exec_id_2 = 2 + alpha_physical_distance_2 = 5 + beta_instance_distance_2 = 5 + T_normalized_cut_2 = 0.02 + print("start exec_id={}".format(exec_id_2)) + process_kitti(1500, 4540, exec_id_2, alpha_physical_distance_2, beta_instance_distance_2, T_normalized_cut_2) + print("finish exec_id={}".format(exec_id_2)) + + exec_id_3 = 3 + alpha_physical_distance_3 = 3 + beta_instance_distance_3 = 5 + T_normalized_cut_3 = 0.02 + print("start exec_id={}".format(exec_id_3)) + process_kitti(1500, 4540, exec_id_3, alpha_physical_distance_3, beta_instance_distance_3, T_normalized_cut_3) + print("finish exec_id={}".format(exec_id_3)) + + exec_id_4 = 4 + alpha_physical_distance_4 = 3 + beta_instance_distance_4 = 3 + T_normalized_cut_4 = 0.02 + print("start exec_id={}".format(exec_id_4)) + process_kitti(1500, 4540, exec_id_4, alpha_physical_distance_4, beta_instance_distance_4, T_normalized_cut_4) + print("finish exec_id={}".format(exec_id_4)) + + exec_id_5 = 5 + alpha_physical_distance_5 = 7 + beta_instance_distance_5 = 7 + T_normalized_cut_5 = 0.02 + print("start exec_id={}".format(exec_id_5)) + process_kitti(1500, 4540, exec_id_5, alpha_physical_distance_5, beta_instance_distance_5, T_normalized_cut_5) + print("finish exec_id={}".format(exec_id_5)) if __name__ == "__main__": diff --git a/main_kitti_processing_metrics.py b/main_kitti_processing_metrics.py index 794c7ba..19edbc0 100644 --- a/main_kitti_processing_metrics.py +++ b/main_kitti_processing_metrics.py @@ -33,7 +33,6 @@ def build_pred_inst_array( inst_label_array_for_clustering, clusters, trace, instance_threshold ): pred_inst_array = np.zeros(len(inst_label_array_for_clustering), dtype=int) - k = 0 free_id = 1 for cluster in clusters: voxel_not_in_gt_cluster_count = 0 @@ -54,17 +53,16 @@ def build_pred_inst_array( for src_point in src_points: pred_inst_array[src_point] = free_id free_id += 1 - k += 1 return pred_inst_array def main(): from_num = 0 - to_num = 4540 + to_num = 1500 - execution_ids = [4] - instance_thresholds = [5, 20, 30, 50] + execution_ids = [1, 2, 3, 4, 5] + instance_thresholds = [50] for execution_id in execution_ids: @@ -78,16 +76,16 @@ def main(): start_index = current_from_num end_index = start_index + 4 - file_name = "experiment_bin_0704_4_sem_offset0_T0l03/start{}_end{}.pickle".format( - start_index, end_index + file_name = "experiment_{}_sem_voxel_offset0_T0l02/start{}_end{}.pickle".format( + execution_id, start_index, end_index ) with open(file_name, "rb") as file: data = pickle.load(file) - trace = data[2] - clusters = data[3] - inst_label_array_for_clustering = data[4] + trace = data[4]['trace_graphcut'] + clusters = data[5]['clusters_graphcut'] + inst_label_array_for_clustering = data[6]['inst_label_array_for_clustering'] if ( inst_label_array_for_clustering.sum() == 0 @@ -122,7 +120,7 @@ def main(): pred_labels_unique.discard(0) with open( - "experiment_1004_{}_without0_sem_offset0_T0l03_{}.csv".format( + "experiment_{}_sem_voxel_offset0_T0l02_{}.csv".format( execution_id, instance_threshold ), "a", From 7c80b214a145d7f5051d6842d28b0e4cf57beb3e Mon Sep 17 00:00:00 2001 From: SVivdich02 Date: Mon, 22 Apr 2024 13:18:23 +0300 Subject: [PATCH 05/21] fixes --- main_calc_metrics_by_csv.py | 28 +++++++++--- main_kitti_processing.py | 73 +++++++++++++++++++++++++------- main_kitti_processing_metrics.py | 12 +++--- 3 files changed, 85 insertions(+), 28 deletions(-) diff --git a/main_calc_metrics_by_csv.py b/main_calc_metrics_by_csv.py index 2c857e9..4234442 100644 --- a/main_calc_metrics_by_csv.py +++ b/main_calc_metrics_by_csv.py @@ -19,12 +19,14 @@ def calculate_metrics(exec_id): values_pres = [] values_recall = [] values_fScore = [] - with open("experiment_{}_sem_voxel_offset0_T0l02_50.csv".format(exec_id), "r") as file: + with open( + "experiment_{}_sem_voxel_offset0_T0l02_50.csv".format(exec_id), "r" + ) as file: reader = csv.DictReader(file) for row in reader: - values_pres.append(row['precision']) - values_recall.append(row['recall']) - values_fScore.append(row['fScore']) + values_pres.append(row["precision"]) + values_recall.append(row["recall"]) + values_fScore.append(row["fScore"]) sum_pres = 0 pres1 = 0 @@ -57,9 +59,21 @@ def calculate_metrics(exec_id): fscore0 += 1 print("start exec_id={}".format(exec_id)) - print("precision={}, 1={}, 0={}".format(sum_pres/float(len(values_pres)), pres1, pres0)) - print("recall={}, 1={}, 0={}".format(sum_recall/float(len(values_recall)), recall1, recall0)) - print("fscore={}, 1={}, 0={}".format(sum_fScore/float(len(values_fScore)), fscore1, fscore0)) + print( + "precision={}, 1={}, 0={}".format( + sum_pres/float(len(values_pres)), pres1, pres0 + ) + ) + print( + "recall={}, 1={}, 0={}".format( + sum_recall/float(len(values_recall)), recall1, recall0 + ) + ) + print( + "fscore={}, 1={}, 0={}".format( + sum_fScore/float(len(values_fScore)), fscore1, fscore0 + ) + ) print("finish exec_id={}".format(exec_id)) diff --git a/main_kitti_processing.py b/main_kitti_processing.py index e1b7b16..b8ccc5c 100644 --- a/main_kitti_processing.py +++ b/main_kitti_processing.py @@ -77,7 +77,11 @@ def build_tuple_bin_saving( return ( {"config": params}, - {"pcd_for_clustering_before_voxelization_points": np.asarray(pcd_for_clustering.points)}, + { + "pcd_for_clustering_before_voxelization_points": np.asarray( + pcd_for_clustering.points + ) + }, {"voxel_pcd_original_points": np.asarray(voxel_pcd.points)}, {"voxel_trace_original": src_trace_arrays}, {"trace_graphcut": trace_arrays}, @@ -160,7 +164,12 @@ def segment_pcds(config): def process_kitti( - from_num, to_num, id_exec, alpha_physical_distance, beta_instance_distance, T_normalized_cut + from_num, + to_num, + id_exec, + alpha_physical_distance, + beta_instance_distance, + T_normalized_cut, ): reduce_detail_int_to_union_threshold = 0.5 @@ -192,10 +201,8 @@ def process_kitti( result_tuple = segment_pcds(config) - file_name = ( - "experiment_{}_sem_voxel_offset0_T0l02/start{}_end{}.pickle".format( - id_exec, config.start_index, config.end_index - ) + file_name = "experiment_{}_sem_voxel_offset0_T0l02/start{}_end{}.pickle".format( + id_exec, config.start_index, config.end_index ) new_file = open(file_name, "w") new_file.close() @@ -208,44 +215,78 @@ def process_kitti( def main(): + start_pcd_num = 1500 + end_pcd_num = 4540 + T_normalized_cut_common = 0.02 + exec_id_1 = 1 alpha_physical_distance_1 = 5 beta_instance_distance_1 = 3 - T_normalized_cut_1 = 0.02 print("start exec_id={}".format(exec_id_1)) - process_kitti(1500, 4540, exec_id_1, alpha_physical_distance_1, beta_instance_distance_1, T_normalized_cut_1) + process_kitti( + start_pcd_num, + end_pcd_num, + exec_id_1, + alpha_physical_distance_1, + beta_instance_distance_1, + T_normalized_cut_common, + ) print("finish exec_id={}".format(exec_id_1)) exec_id_2 = 2 alpha_physical_distance_2 = 5 beta_instance_distance_2 = 5 - T_normalized_cut_2 = 0.02 print("start exec_id={}".format(exec_id_2)) - process_kitti(1500, 4540, exec_id_2, alpha_physical_distance_2, beta_instance_distance_2, T_normalized_cut_2) + process_kitti( + start_pcd_num, + end_pcd_num, + exec_id_2, + alpha_physical_distance_2, + beta_instance_distance_2, + T_normalized_cut_common, + ) print("finish exec_id={}".format(exec_id_2)) exec_id_3 = 3 alpha_physical_distance_3 = 3 beta_instance_distance_3 = 5 - T_normalized_cut_3 = 0.02 print("start exec_id={}".format(exec_id_3)) - process_kitti(1500, 4540, exec_id_3, alpha_physical_distance_3, beta_instance_distance_3, T_normalized_cut_3) + process_kitti( + start_pcd_num, + end_pcd_num, + exec_id_3, + alpha_physical_distance_3, + beta_instance_distance_3, + T_normalized_cut_common, + ) print("finish exec_id={}".format(exec_id_3)) exec_id_4 = 4 alpha_physical_distance_4 = 3 beta_instance_distance_4 = 3 - T_normalized_cut_4 = 0.02 print("start exec_id={}".format(exec_id_4)) - process_kitti(1500, 4540, exec_id_4, alpha_physical_distance_4, beta_instance_distance_4, T_normalized_cut_4) + process_kitti( + start_pcd_num, + end_pcd_num, + exec_id_4, + alpha_physical_distance_4, + beta_instance_distance_4, + T_normalized_cut_common + ) print("finish exec_id={}".format(exec_id_4)) exec_id_5 = 5 alpha_physical_distance_5 = 7 beta_instance_distance_5 = 7 - T_normalized_cut_5 = 0.02 print("start exec_id={}".format(exec_id_5)) - process_kitti(1500, 4540, exec_id_5, alpha_physical_distance_5, beta_instance_distance_5, T_normalized_cut_5) + process_kitti( + start_pcd_num, + end_pcd_num, + exec_id_5, + alpha_physical_distance_5, + beta_instance_distance_5, + T_normalized_cut_common, + ) print("finish exec_id={}".format(exec_id_5)) diff --git a/main_kitti_processing_metrics.py b/main_kitti_processing_metrics.py index 19edbc0..69a68e2 100644 --- a/main_kitti_processing_metrics.py +++ b/main_kitti_processing_metrics.py @@ -76,16 +76,18 @@ def main(): start_index = current_from_num end_index = start_index + 4 - file_name = "experiment_{}_sem_voxel_offset0_T0l02/start{}_end{}.pickle".format( - execution_id, start_index, end_index + file_name = ( + "experiment_{}_sem_voxel_offset0_T0l02/start{}_end{}.pickle".format( + execution_id, start_index, end_index + ) ) with open(file_name, "rb") as file: data = pickle.load(file) - trace = data[4]['trace_graphcut'] - clusters = data[5]['clusters_graphcut'] - inst_label_array_for_clustering = data[6]['inst_label_array_for_clustering'] + trace = data[4]["trace_graphcut"] + clusters = data[5]["clusters_graphcut"] + inst_label_array_for_clustering = data[6]["inst_label_array_for_clustering"] if ( inst_label_array_for_clustering.sum() == 0 From 66ed043100245799ad5d8c3beb85d1bdb1d049bc Mon Sep 17 00:00:00 2001 From: SVivdich02 Date: Wed, 15 May 2024 19:53:48 +0300 Subject: [PATCH 06/21] experiment files kitti processing --- main_calc_metrics_by_csv.py | 20 ++--- main_kitti_processing.py | 86 +++--------------- main_kitti_processing_metrics.py | 147 +++++++++++++++---------------- 3 files changed, 88 insertions(+), 165 deletions(-) diff --git a/main_calc_metrics_by_csv.py b/main_calc_metrics_by_csv.py index 4234442..e604b7c 100644 --- a/main_calc_metrics_by_csv.py +++ b/main_calc_metrics_by_csv.py @@ -15,13 +15,11 @@ import csv -def calculate_metrics(exec_id): +def calculate_metrics(file_name): values_pres = [] values_recall = [] values_fScore = [] - with open( - "experiment_{}_sem_voxel_offset0_T0l02_50.csv".format(exec_id), "r" - ) as file: + with open(file_name, "r") as file: reader = csv.DictReader(file) for row in reader: values_pres.append(row["precision"]) @@ -58,31 +56,25 @@ def calculate_metrics(exec_id): if float(value) == 0.0: fscore0 += 1 - print("start exec_id={}".format(exec_id)) print( "precision={}, 1={}, 0={}".format( - sum_pres/float(len(values_pres)), pres1, pres0 + sum_pres/float(len(values_pres)), pres1/float(len(values_pres)), pres0/float(len(values_pres)) ) ) print( "recall={}, 1={}, 0={}".format( - sum_recall/float(len(values_recall)), recall1, recall0 + sum_recall/float(len(values_recall)), recall1/float(len(values_recall)), recall0/float(len(values_recall)) ) ) print( "fscore={}, 1={}, 0={}".format( - sum_fScore/float(len(values_fScore)), fscore1, fscore0 + sum_fScore/float(len(values_fScore)), fscore1/float(len(values_fScore)), fscore0/float(len(values_fScore)) ) ) - print("finish exec_id={}".format(exec_id)) def main(): - calculate_metrics(1) - calculate_metrics(2) - calculate_metrics(3) - calculate_metrics(4) - calculate_metrics(5) + calculate_metrics("experiment_2_a5b5_sem_voxel_offset0_T0l025_50.csv") if __name__ == "__main__": diff --git a/main_kitti_processing.py b/main_kitti_processing.py index b8ccc5c..4dafba6 100644 --- a/main_kitti_processing.py +++ b/main_kitti_processing.py @@ -166,15 +166,10 @@ def segment_pcds(config): def process_kitti( from_num, to_num, - id_exec, alpha_physical_distance, beta_instance_distance, T_normalized_cut, ): - - reduce_detail_int_to_union_threshold = 0.5 - reduce_detail_int_to_mask_threshold = 0.6 - current_from_num = from_num while current_from_num < to_num: @@ -189,8 +184,8 @@ def process_kitti( "alpha_physical_distance": alpha_physical_distance, "beta_instance_distance": beta_instance_distance, "T_normalized_cut": T_normalized_cut, - "reduce_detail_int_to_union_threshold": reduce_detail_int_to_union_threshold, - "reduce_detail_int_to_mask_threshold": reduce_detail_int_to_mask_threshold, + "reduce_detail_int_to_union_threshold": 0.5, + "reduce_detail_int_to_mask_threshold": 0.6, "cam_name": "cam2", "R": 18, "nb_neighbors": 25, @@ -201,8 +196,8 @@ def process_kitti( result_tuple = segment_pcds(config) - file_name = "experiment_{}_sem_voxel_offset0_T0l02/start{}_end{}.pickle".format( - id_exec, config.start_index, config.end_index + file_name = "experiment_2_a5b5_sem_voxel_offset0_T0l025/start{}_end{}.pickle".format( + config.start_index, config.end_index ) new_file = open(file_name, "w") new_file.close() @@ -215,79 +210,20 @@ def process_kitti( def main(): - start_pcd_num = 1500 + start_pcd_num = 0 end_pcd_num = 4540 - T_normalized_cut_common = 0.02 - exec_id_1 = 1 - alpha_physical_distance_1 = 5 - beta_instance_distance_1 = 3 - print("start exec_id={}".format(exec_id_1)) - process_kitti( - start_pcd_num, - end_pcd_num, - exec_id_1, - alpha_physical_distance_1, - beta_instance_distance_1, - T_normalized_cut_common, - ) - print("finish exec_id={}".format(exec_id_1)) - - exec_id_2 = 2 - alpha_physical_distance_2 = 5 - beta_instance_distance_2 = 5 - print("start exec_id={}".format(exec_id_2)) - process_kitti( - start_pcd_num, - end_pcd_num, - exec_id_2, - alpha_physical_distance_2, - beta_instance_distance_2, - T_normalized_cut_common, - ) - print("finish exec_id={}".format(exec_id_2)) - - exec_id_3 = 3 - alpha_physical_distance_3 = 3 - beta_instance_distance_3 = 5 - print("start exec_id={}".format(exec_id_3)) - process_kitti( - start_pcd_num, - end_pcd_num, - exec_id_3, - alpha_physical_distance_3, - beta_instance_distance_3, - T_normalized_cut_common, - ) - print("finish exec_id={}".format(exec_id_3)) - - exec_id_4 = 4 - alpha_physical_distance_4 = 3 - beta_instance_distance_4 = 3 - print("start exec_id={}".format(exec_id_4)) - process_kitti( - start_pcd_num, - end_pcd_num, - exec_id_4, - alpha_physical_distance_4, - beta_instance_distance_4, - T_normalized_cut_common - ) - print("finish exec_id={}".format(exec_id_4)) + alpha_physical_distance = 5 + beta_instance_distance = 5 + T_normalized_cut = 0.025 - exec_id_5 = 5 - alpha_physical_distance_5 = 7 - beta_instance_distance_5 = 7 - print("start exec_id={}".format(exec_id_5)) process_kitti( start_pcd_num, end_pcd_num, - exec_id_5, - alpha_physical_distance_5, - beta_instance_distance_5, - T_normalized_cut_common, + alpha_physical_distance, + beta_instance_distance, + T_normalized_cut, ) - print("finish exec_id={}".format(exec_id_5)) if __name__ == "__main__": diff --git a/main_kitti_processing_metrics.py b/main_kitti_processing_metrics.py index 69a68e2..bf6fc72 100644 --- a/main_kitti_processing_metrics.py +++ b/main_kitti_processing_metrics.py @@ -59,94 +59,89 @@ def build_pred_inst_array( def main(): from_num = 0 - to_num = 1500 + to_num = 4540 - execution_ids = [1, 2, 3, 4, 5] - instance_thresholds = [50] + instance_thresholds = [5, 20, 30, 50] - for execution_id in execution_ids: + for instance_threshold in instance_thresholds: + print("Start to process instance_threshold={}".format(instance_threshold)) - for instance_threshold in instance_thresholds: - print("Start to process instance_threshold={}".format(instance_threshold)) + current_from_num = from_num - current_from_num = from_num + skipped = 0 + while current_from_num < to_num: + start_index = current_from_num + end_index = start_index + 4 - skipped = 0 - while current_from_num < to_num: - start_index = current_from_num - end_index = start_index + 4 - - file_name = ( - "experiment_{}_sem_voxel_offset0_T0l02/start{}_end{}.pickle".format( - execution_id, start_index, end_index - ) + file_name = ( + "experiment_2_a5b5_sem_voxel_offset0_T0l025/start{}_end{}.pickle".format( + start_index, end_index ) + ) - with open(file_name, "rb") as file: - data = pickle.load(file) - - trace = data[4]["trace_graphcut"] - clusters = data[5]["clusters_graphcut"] - inst_label_array_for_clustering = data[6]["inst_label_array_for_clustering"] - - if ( - inst_label_array_for_clustering.sum() == 0 - ): # в облаке нет инстансов => пропускаем - skipped += 1 - print( - "start_index={}, end_index={} skip".format( - start_index, end_index - ) + with open(file_name, "rb") as file: + data = pickle.load(file) + + trace = data[4]["trace_graphcut"] + clusters = data[5]["clusters_graphcut"] + inst_label_array_for_clustering = data[6]["inst_label_array_for_clustering"] + + if ( + inst_label_array_for_clustering.sum() == 0 + ): # в облаке нет инстансов => пропускаем + skipped += 1 + print( + "start_index={}, end_index={} skip".format( + start_index, end_index ) - current_from_num = end_index - continue - - pred_inst_array = build_pred_inst_array( - copy.deepcopy(inst_label_array_for_clustering), - clusters, - copy.deepcopy(trace), - instance_threshold, ) + current_from_num = end_index + continue - pred_labels = pred_inst_array - gt_labels = inst_label_array_for_clustering - tp_condition = "iou" - precision_res = precision(pred_labels, gt_labels, tp_condition) - recall_res = recall(pred_labels, gt_labels, tp_condition) - fScore_res = fScore(pred_labels, gt_labels, tp_condition) - - gt_labels_unique = set(gt_labels) - gt_labels_unique.discard(0) - - pred_labels_unique = set(pred_labels) - pred_labels_unique.discard(0) - - with open( - "experiment_{}_sem_voxel_offset0_T0l02_{}.csv".format( - execution_id, instance_threshold - ), - "a", - newline="", - ) as file: - writer = csv.writer(file) - - writer.writerow( - [ - str(start_index), - str(end_index), - str(precision_res), - str(recall_res), - str(fScore_res), - len(gt_labels_unique), - len(pred_labels_unique), - len(clusters), - ] - ) + pred_inst_array = build_pred_inst_array( + copy.deepcopy(inst_label_array_for_clustering), + clusters, + copy.deepcopy(trace), + instance_threshold, + ) - current_from_num = end_index + pred_labels = pred_inst_array + gt_labels = inst_label_array_for_clustering + tp_condition = "iou" + precision_res = precision(pred_labels, gt_labels, tp_condition) + recall_res = recall(pred_labels, gt_labels, tp_condition) + fScore_res = fScore(pred_labels, gt_labels, tp_condition) + + gt_labels_unique = set(gt_labels) + gt_labels_unique.discard(0) + + pred_labels_unique = set(pred_labels) + pred_labels_unique.discard(0) + + with open( + "experiment_2_a5b5_sem_voxel_offset0_T0l025_{}.csv".format(instance_threshold), + "a", + newline="", + ) as file: + writer = csv.writer(file) + + writer.writerow( + [ + str(start_index), + str(end_index), + str(precision_res), + str(recall_res), + str(fScore_res), + len(gt_labels_unique), + len(pred_labels_unique), + len(clusters), + ] + ) + + current_from_num = end_index - print(skipped) - print("Finish to process instance_threshold={}".format(instance_threshold)) + print(skipped) + print("Finish to process instance_threshold={}".format(instance_threshold)) if __name__ == "__main__": From 5f6a97bf01d08a9a1fb8f334dccd27111902b2fd Mon Sep 17 00:00:00 2001 From: SVivdich02 Date: Wed, 15 May 2024 20:56:50 +0300 Subject: [PATCH 07/21] add examples --- example.ipynb | 165 +++++++++++--- example_gt.ipynb | 201 ++++++++++++------ .../main_calc_metrics_by_csv.py | 0 .../main_kitti_processing.py | 0 .../main_kitti_processing_metrics.py | 0 5 files changed, 271 insertions(+), 95 deletions(-) rename main_calc_metrics_by_csv.py => experiment/main_calc_metrics_by_csv.py (100%) rename main_kitti_processing.py => experiment/main_kitti_processing.py (100%) rename main_kitti_processing_metrics.py => experiment/main_kitti_processing_metrics.py (100%) diff --git a/example.ipynb b/example.ipynb index eebe9b0..d4a0b93 100644 --- a/example.ipynb +++ b/example.ipynb @@ -2,24 +2,26 @@ "cells": [ { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "from src.datasets.kitti_dataset import KittiDataset\n", "\n", - "dataset_path = \"dataset/\"\n", + "dataset_path = \"dataset/\" # kitti\n", "sequence = \"00\"\n", - "image_instances_path = \"pipeline/vfm-labels/sam/00/\"\n", + "image_instances_path = \"pipeline/vfm-labelss/sam/00/\" # images processed by the SAM algorithm in npz format\n", "kitti = KittiDataset(dataset_path, sequence, image_instances_path)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ + "# setting parameter values\n", + "\n", "from src.services.preprocessing.common.config import ConfigDTO\n", "\n", "config = ConfigDTO(\n", @@ -27,10 +29,10 @@ " \"dataset\": kitti,\n", " \"start_index\": 20,\n", " \"end_index\": 24,\n", - " \"start_image_index_offset\": 3,\n", + " \"start_image_index_offset\": 0,\n", " \"alpha_physical_distance\": 5,\n", - " \"beta_instance_distance\": 3,\n", - " \"T_normalized_cut\": 0.02,\n", + " \"beta_instance_distance\": 5,\n", + " \"T_normalized_cut\": 0.025,\n", " \"reduce_detail_int_to_union_threshold\": 0.5,\n", " \"reduce_detail_int_to_mask_threshold\": 0.6,\n", " \"cam_name\": \"cam2\",\n", @@ -44,10 +46,12 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ + "# pcd initialisation and initial segmentation based on images\n", + "\n", "from src.services.preprocessing.init.map import InitMapProcessor\n", "from src.services.preprocessing.init.instances_matrix import InitInstancesMatrixProcessor\n", "\n", @@ -57,19 +61,32 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "(498379, 4)" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "points2instances.shape" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ + "# visualisation of the initial pcd segmentation masks for a particular image\n", + "\n", "import copy\n", "\n", "from src.utils.pcd_utils import color_pcd_by_labels\n", @@ -81,10 +98,12 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ + "# pcd handler initialisation\n", + "\n", "from src.services.preprocessing.not_zero import SelectionNotZeroProcessor\n", "from src.services.preprocessing.in_cube import SelectionInCubeProcessor\n", "from src.services.preprocessing.statistical_outlier import StatisticalOutlierProcessor\n", @@ -98,10 +117,12 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": {}, "outputs": [], "source": [ + "# pcd processing and saving the state\n", + "\n", "import copy\n", "\n", "pcd = copy.deepcopy(init_pcd)\n", @@ -114,25 +135,29 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ + "# visualisation of the processed pcd before voxelization\n", + "\n", "import copy\n", "\n", "from src.utils.pcd_utils import color_pcd_by_labels\n", "from src.utils.pcd_utils import visualize_pcd\n", "\n", - "colored_pcd_pcd_for_clustering = color_pcd_by_labels(copy.deepcopy(pcd_for_clustering), points2instances_pcd_for_clustering[:, 0])\n", - "visualize_pcd(colored_pcd_pcd_for_clustering)" + "colored_pcd_for_clustering = color_pcd_by_labels(copy.deepcopy(pcd_for_clustering), points2instances_pcd_for_clustering[:, 0])\n", + "visualize_pcd(colored_pcd_for_clustering)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": {}, "outputs": [], "source": [ + "# final processing step - voxelisation of the pcd\n", + "\n", "from src.services.preprocessing.voxel_down import VoxelDownProcessor\n", "\n", "pcd, points2instances, trace = VoxelDownProcessor().process(config, pcd, points2instances)" @@ -140,10 +165,29 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": {}, "outputs": [], "source": [ + "# visualisation of the voxelised pcd\n", + "\n", + "import copy\n", + "\n", + "from src.utils.pcd_utils import color_pcd_by_labels\n", + "from src.utils.pcd_utils import visualize_pcd\n", + "\n", + "colored_voxel_pcd_for_clustering = color_pcd_by_labels(copy.deepcopy(pcd), points2instances[:, 0])\n", + "visualize_pcd(colored_voxel_pcd_for_clustering)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "# calculation of distance matrix for voxelised pcd\n", + "\n", "import numpy as np\n", "\n", "from scipy.spatial.distance import cdist\n", @@ -163,19 +207,32 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 12, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "(3502, 3502)" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "dist.shape" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 13, "metadata": {}, "outputs": [], "source": [ + "# distance matrix processing\n", + "\n", "from src.services.distance.isolated import RemovingIsolatedPointsProcessor\n", "from src.services.distance.connected_component import ExtractionLargestConnectedComponentProcessor\n", "\n", @@ -190,9 +247,19 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 14, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(3502, 3502)\n", + "3502\n", + "3502\n" + ] + } + ], "source": [ "print(dist.shape)\n", "print(len(points))\n", @@ -201,14 +268,15 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 15, "metadata": {}, "outputs": [], "source": [ + "# pcd clustering using GraphCut algorithm\n", + "\n", "from src.services.normalized_cut_service import normalized_cut\n", "\n", "eigenval = 2\n", - "\n", "clusters = normalized_cut(\n", " dist,\n", " np.array([i for i in range(len(points))], dtype=int),\n", @@ -219,19 +287,53 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 16, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "22" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "len(clusters)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([ 206, 207, 456, 457, 496, 498, 1271, 1272, 1275, 1276, 1285,\n", + " 1390, 1450, 1451, 1559, 1560, 1596, 1597, 2310, 2311])" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "clusters[0]" + ] + }, + { + "cell_type": "code", + "execution_count": 18, "metadata": {}, "outputs": [], "source": [ + "# visualisation of segmentation results. masks will be drawn on the processed pcd before voxelisation\n", + "\n", "from src.utils.pcd_utils import color_pcd_by_clusters_and_voxels\n", "from src.utils.pcd_utils import visualize_pcd\n", "\n", @@ -244,12 +346,7 @@ "execution_count": null, "metadata": {}, "outputs": [], - "source": [ - "from src.utils.pcd_utils import color_pcd_by_labels\n", - "\n", - "pcd_src_colored = color_pcd_by_labels(pcd_for_clustering, points2instances_pcd_for_clustering[:, 2])\n", - "visualize_pcd(pcd_src_colored)" - ] + "source": [] } ], "metadata": { diff --git a/example_gt.ipynb b/example_gt.ipynb index 64b17bc..9ae87ae 100644 --- a/example_gt.ipynb +++ b/example_gt.ipynb @@ -8,10 +8,10 @@ "source": [ "from src.datasets.kitti_dataset import KittiDataset\n", "\n", - "dataset_path = \"dataset/\"\n", + "dataset_path = \"dataset/\" # kitti\n", "sequence = \"00\"\n", - "image_instances_path = \"pipeline/vfm-labelss/sam/00/\"\n", - "gt_labels_path = \"dataset/sequences/00/labels/\"\n", + "image_instances_path = \"pipeline/vfm-labelss/sam/00/\" # images processed by the SAM algorithm in npz format\n", + "gt_labels_path = \"dataset/sequences/00/labels/\" # ground true kitti cloud segmentation\n", "kitti = KittiDataset(dataset_path, sequence, image_instances_path)" ] }, @@ -21,17 +21,19 @@ "metadata": {}, "outputs": [], "source": [ + "# setting parameter values\n", + "\n", "from src.services.preprocessing.common.config import ConfigDTO\n", "\n", "config = ConfigDTO(\n", " **{\n", " \"dataset\": kitti,\n", - " \"start_index\": 20,\n", - " \"end_index\": 24,\n", - " \"start_image_index_offset\": 3,\n", + " \"start_index\": 2024,\n", + " \"end_index\": 2028,\n", + " \"start_image_index_offset\": 0,\n", " \"alpha_physical_distance\": 5,\n", - " \"beta_instance_distance\": 3,\n", - " \"T_normalized_cut\": 0.02,\n", + " \"beta_instance_distance\": 5,\n", + " \"T_normalized_cut\": 0.025,\n", " \"reduce_detail_int_to_union_threshold\": 0.5,\n", " \"reduce_detail_int_to_mask_threshold\": 0.6,\n", " \"cam_name\": \"cam2\",\n", @@ -49,6 +51,8 @@ "metadata": {}, "outputs": [], "source": [ + "# pcd initialisation and initial segmentation based on images\n", + "\n", "from src.services.preprocessing.init.map import InitMapProcessor\n", "from src.services.preprocessing.init.instances_matrix import InitInstancesMatrixProcessor\n", "\n", @@ -62,13 +66,13 @@ "metadata": {}, "outputs": [], "source": [ + "# building an array of gt instance segmentation for each sequence pcd\n", + "\n", "from src.utils.gt_utils import build_sem_inst_label_arrays\n", "\n", - "sem_label_array_src, inst_label_array_src = build_sem_inst_label_arrays(gt_labels_path,\n", - " config.start_index,\n", - " config.end_index)\n", - "print(len(sem_label_array_src) == len(init_pcd.points))\n", - "print(len(inst_label_array_src) == len(init_pcd.points))" + "_, inst_label_array_src = build_sem_inst_label_arrays(\n", + " gt_labels_path, config.start_index, config.end_index\n", + ")" ] }, { @@ -77,7 +81,15 @@ "metadata": {}, "outputs": [], "source": [ - "points2instances.shape" + "# visualisation of gt instance masks on the pcd\n", + "\n", + "import copy\n", + "\n", + "from src.utils.pcd_utils import color_pcd_by_labels\n", + "from src.utils.pcd_utils import visualize_pcd\n", + "\n", + "colored_pcd = color_pcd_by_labels(copy.deepcopy(init_pcd), inst_label_array_src)\n", + "visualize_pcd(colored_pcd)" ] }, { @@ -86,6 +98,8 @@ "metadata": {}, "outputs": [], "source": [ + "# visualisation of the initial pcd segmentation masks for a particular image\n", + "\n", "import copy\n", "\n", "from src.utils.pcd_utils import color_pcd_by_labels\n", @@ -101,6 +115,8 @@ "metadata": {}, "outputs": [], "source": [ + "# pcd handler initialisation\n", + "\n", "from src.services.preprocessing.not_zero import SelectionNotZeroProcessor\n", "from src.services.preprocessing.in_cube import SelectionInCubeProcessor\n", "from src.services.preprocessing.statistical_outlier import StatisticalOutlierProcessor\n", @@ -118,36 +134,18 @@ "metadata": {}, "outputs": [], "source": [ + "# pcd processing and saving the state\n", + "\n", "import copy\n", "\n", "pcd = copy.deepcopy(init_pcd)\n", "for processor in processors:\n", " pcd, points2instances, indices = processor.process(config, pcd, points2instances)\n", - " sem_label_array_src = sem_label_array_src[indices]\n", " inst_label_array_src = inst_label_array_src[indices]\n", "\n", "pcd_for_clustering = copy.deepcopy(pcd)\n", "points2instances_pcd_for_clustering = copy.deepcopy(points2instances)\n", - "inst_label_array_for_clustering = copy.deepcopy(inst_label_array_src)\n", - "sem_label_array_for_clustering = copy.deepcopy(sem_label_array_src)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "len(inst_label_array_for_clustering) == len(pcd_for_clustering.points)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "len(sem_label_array_for_clustering) == len(pcd_for_clustering.points)" + "inst_label_array_for_clustering = copy.deepcopy(inst_label_array_src)" ] }, { @@ -156,26 +154,16 @@ "metadata": {}, "outputs": [], "source": [ - "# from src.utils.gt_utils import combine_sem_inst_labels\n", + "# visualisation of gt instance masks on the processed pcd before voxelization\n", "\n", - "# combined_label_array = combine_sem_inst_labels(sem_label_array_for_clustering,\n", - "# inst_label_array_for_clustering)\n", - "# print(len(combined_label_array) == len(pcd_for_clustering.points))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ "import copy\n", "\n", "from src.utils.pcd_utils import color_pcd_by_labels\n", "from src.utils.pcd_utils import visualize_pcd\n", "\n", - "colored_pcd_for_clustering = color_pcd_by_labels(copy.deepcopy(pcd_for_clustering),\n", - " inst_label_array_for_clustering)\n", + "colored_pcd_for_clustering = color_pcd_by_labels(\n", + " copy.deepcopy(pcd_for_clustering), inst_label_array_for_clustering\n", + ")\n", "visualize_pcd(colored_pcd_for_clustering)" ] }, @@ -185,13 +173,16 @@ "metadata": {}, "outputs": [], "source": [ + "# visualisation of the initial pcd segmentation masks before voxelization\n", + "\n", "import copy\n", "\n", "from src.utils.pcd_utils import color_pcd_by_labels\n", "from src.utils.pcd_utils import visualize_pcd\n", "\n", - "colored_pcd_for_clustering = color_pcd_by_labels(copy.deepcopy(pcd_for_clustering),\n", - " points2instances_pcd_for_clustering[:, 0])\n", + "colored_pcd_for_clustering = color_pcd_by_labels(\n", + " copy.deepcopy(pcd_for_clustering), points2instances_pcd_for_clustering[:, 0]\n", + ")\n", "visualize_pcd(colored_pcd_for_clustering)" ] }, @@ -201,6 +192,8 @@ "metadata": {}, "outputs": [], "source": [ + "# final processing step - voxelisation of the pcd\n", + "\n", "from src.services.preprocessing.voxel_down import VoxelDownProcessor\n", "\n", "pcd, points2instances, trace = VoxelDownProcessor().process(config, pcd, points2instances)" @@ -212,6 +205,8 @@ "metadata": {}, "outputs": [], "source": [ + "# calculation of distance matrix for voxelised pcd\n", + "\n", "import numpy as np\n", "\n", "from scipy.spatial.distance import cdist\n", @@ -244,6 +239,8 @@ "metadata": {}, "outputs": [], "source": [ + "# distance matrix processing\n", + "\n", "from src.services.distance.isolated import RemovingIsolatedPointsProcessor\n", "from src.services.distance.connected_component import ExtractionLargestConnectedComponentProcessor\n", "\n", @@ -273,10 +270,11 @@ "metadata": {}, "outputs": [], "source": [ + "# pcd clustering using GraphCut algorithm\n", + "\n", "from src.services.normalized_cut_service import normalized_cut\n", "\n", "eigenval = 2\n", - "\n", "clusters = normalized_cut(\n", " dist,\n", " np.array([i for i in range(len(points))], dtype=int),\n", @@ -300,14 +298,25 @@ "metadata": {}, "outputs": [], "source": [ + "clusters[0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# visualisation of segmentation results. masks will be drawn on the processed pcd before voxelisation\n", + "\n", "import copy\n", "\n", "from src.utils.pcd_utils import color_pcd_by_clusters_and_voxels\n", "from src.utils.pcd_utils import visualize_pcd\n", "\n", - "colored_clusters_for_clustering = color_pcd_by_clusters_and_voxels(copy.deepcopy(pcd_for_clustering),\n", - " copy.deepcopy(trace),\n", - " clusters)\n", + "colored_clusters_for_clustering = color_pcd_by_clusters_and_voxels(\n", + " copy.deepcopy(pcd_for_clustering), copy.deepcopy(trace), clusters\n", + ")\n", "visualize_pcd(colored_clusters_for_clustering)" ] }, @@ -317,13 +326,16 @@ "metadata": {}, "outputs": [], "source": [ + "# visualisation of gt instance masks on the processed pcd before voxelization\n", + "\n", "import copy\n", "\n", "from src.utils.pcd_utils import color_pcd_by_labels\n", "from src.utils.pcd_utils import visualize_pcd\n", "\n", - "colored_pcd_for_clustering = color_pcd_by_labels(copy.deepcopy(pcd_for_clustering),\n", - " inst_label_array_for_clustering)\n", + "colored_pcd_for_clustering = color_pcd_by_labels(\n", + " copy.deepcopy(pcd_for_clustering), inst_label_array_for_clustering\n", + ")\n", "visualize_pcd(colored_pcd_for_clustering)" ] }, @@ -333,6 +345,9 @@ "metadata": {}, "outputs": [], "source": [ + "# auxiliary function for calculating metrics\n", + "# if a cluster-prediction point is in the gt label, return the mask id number in the gt label array\n", + "\n", "def find_num_in_inst_label_array(src_points, inst_label_array_for_clustering):\n", " for point in src_points:\n", " if inst_label_array_for_clustering[point] > 0:\n", @@ -346,18 +361,27 @@ "metadata": {}, "outputs": [], "source": [ - "def build_pred_inst_array(inst_label_array_for_clustering, clusters, trace, instance_threshold):\n", + "# building an array of predictions for comparison with gt instance label\n", + "# cell j stores the mask number for the j-th pcd point\n", + "\n", + "def build_pred_inst_array(\n", + " inst_label_array_for_clustering, clusters, trace, instance_threshold\n", + "):\n", " pred_inst_array = np.zeros(len(inst_label_array_for_clustering), dtype=int)\n", " free_id = 1\n", " for cluster in clusters:\n", " voxel_not_in_gt_cluster_count = 0\n", " for voxel in cluster:\n", " src_points = trace[voxel]\n", - " id = find_num_in_inst_label_array(src_points, inst_label_array_for_clustering)\n", + " id = find_num_in_inst_label_array(\n", + " src_points, inst_label_array_for_clustering\n", + " )\n", " if id == -1:\n", " voxel_not_in_gt_cluster_count += 1\n", "\n", - " cluster_in_gt_instance = ((len(cluster) - voxel_not_in_gt_cluster_count) / len(cluster)) * 100\n", + " cluster_in_gt_instance = (\n", + " (len(cluster) - voxel_not_in_gt_cluster_count) / len(cluster)\n", + " ) * 100\n", " if cluster_in_gt_instance >= instance_threshold:\n", " for voxel in cluster:\n", " src_points = trace[voxel]\n", @@ -373,7 +397,15 @@ "metadata": {}, "outputs": [], "source": [ - "pred_inst_array = build_pred_inst_array(copy.deepcopy(inst_label_array_for_clustering), clusters, copy.deepcopy(trace), 20)" + "# an array of predictions\n", + "# if instance_threshold percent or more of the cluster is in the gt instance, consider the cluster to be selected for comparison\n", + "\n", + "pred_inst_array = build_pred_inst_array(\n", + " copy.deepcopy(inst_label_array_for_clustering),\n", + " clusters,\n", + " copy.deepcopy(trace),\n", + " instance_threshold=30\n", + ")" ] }, { @@ -382,6 +414,8 @@ "metadata": {}, "outputs": [], "source": [ + "# metrics calculation\n", + "\n", "from evops.metrics import precision\n", "from evops.metrics import recall\n", "from evops.metrics import fScore\n", @@ -393,6 +427,51 @@ "print(\"recall={}\".format(recall(pred_labels, gt_labels, tp_condition)))\n", "print(\"fScore={}\".format(fScore(pred_labels, gt_labels, tp_condition)))" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# visualisation of prediction masks\n", + "\n", + "import copy\n", + "\n", + "from src.utils.pcd_utils import color_pcd_by_labels\n", + "from src.utils.pcd_utils import visualize_pcd\n", + "\n", + "colored_pcd_for_clustering = color_pcd_by_labels(\n", + " copy.deepcopy(pcd_for_clustering), pred_labels\n", + ")\n", + "visualize_pcd(colored_pcd_for_clustering)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# visualisation of gt instance label masks\n", + "\n", + "import copy\n", + "\n", + "from src.utils.pcd_utils import color_pcd_by_labels\n", + "from src.utils.pcd_utils import visualize_pcd\n", + "\n", + "colored_pcd_for_clustering = color_pcd_by_labels(\n", + " copy.deepcopy(pcd_for_clustering), gt_labels\n", + ")\n", + "visualize_pcd(colored_pcd_for_clustering)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { diff --git a/main_calc_metrics_by_csv.py b/experiment/main_calc_metrics_by_csv.py similarity index 100% rename from main_calc_metrics_by_csv.py rename to experiment/main_calc_metrics_by_csv.py diff --git a/main_kitti_processing.py b/experiment/main_kitti_processing.py similarity index 100% rename from main_kitti_processing.py rename to experiment/main_kitti_processing.py diff --git a/main_kitti_processing_metrics.py b/experiment/main_kitti_processing_metrics.py similarity index 100% rename from main_kitti_processing_metrics.py rename to experiment/main_kitti_processing_metrics.py From f207000db84bad0fdc9824436cfd454ba64eee72 Mon Sep 17 00:00:00 2001 From: SVivdich02 Date: Wed, 15 May 2024 21:01:36 +0300 Subject: [PATCH 08/21] fixes --- experiment/main_calc_metrics_by_csv.py | 12 +++++++++--- experiment/main_kitti_processing.py | 6 ++++-- experiment/main_kitti_processing_metrics.py | 14 ++++++-------- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/experiment/main_calc_metrics_by_csv.py b/experiment/main_calc_metrics_by_csv.py index e604b7c..598e136 100644 --- a/experiment/main_calc_metrics_by_csv.py +++ b/experiment/main_calc_metrics_by_csv.py @@ -58,17 +58,23 @@ def calculate_metrics(file_name): print( "precision={}, 1={}, 0={}".format( - sum_pres/float(len(values_pres)), pres1/float(len(values_pres)), pres0/float(len(values_pres)) + sum_pres/float(len(values_pres)), + pres1/float(len(values_pres)), + pres0/float(len(values_pres)), ) ) print( "recall={}, 1={}, 0={}".format( - sum_recall/float(len(values_recall)), recall1/float(len(values_recall)), recall0/float(len(values_recall)) + sum_recall/float(len(values_recall)), + recall1/float(len(values_recall)), + recall0/float(len(values_recall)), ) ) print( "fscore={}, 1={}, 0={}".format( - sum_fScore/float(len(values_fScore)), fscore1/float(len(values_fScore)), fscore0/float(len(values_fScore)) + sum_fScore/float(len(values_fScore)), + fscore1/float(len(values_fScore)), + fscore0/float(len(values_fScore)), ) ) diff --git a/experiment/main_kitti_processing.py b/experiment/main_kitti_processing.py index 4dafba6..9d358ba 100644 --- a/experiment/main_kitti_processing.py +++ b/experiment/main_kitti_processing.py @@ -196,8 +196,10 @@ def process_kitti( result_tuple = segment_pcds(config) - file_name = "experiment_2_a5b5_sem_voxel_offset0_T0l025/start{}_end{}.pickle".format( - config.start_index, config.end_index + file_name = ( + "experiment_2_a5b5_sem_voxel_offset0_T0l025/start{}_end{}.pickle".format( + config.start_index, config.end_index + ) ) new_file = open(file_name, "w") new_file.close() diff --git a/experiment/main_kitti_processing_metrics.py b/experiment/main_kitti_processing_metrics.py index bf6fc72..029ca88 100644 --- a/experiment/main_kitti_processing_metrics.py +++ b/experiment/main_kitti_processing_metrics.py @@ -73,10 +73,8 @@ def main(): start_index = current_from_num end_index = start_index + 4 - file_name = ( - "experiment_2_a5b5_sem_voxel_offset0_T0l025/start{}_end{}.pickle".format( - start_index, end_index - ) + file_name = "experiment_2_a5b5_sem_voxel_offset0_T0l025/start{}_end{}.pickle".format( + start_index, end_index ) with open(file_name, "rb") as file: @@ -91,9 +89,7 @@ def main(): ): # в облаке нет инстансов => пропускаем skipped += 1 print( - "start_index={}, end_index={} skip".format( - start_index, end_index - ) + "start_index={}, end_index={} skip".format(start_index, end_index) ) current_from_num = end_index continue @@ -119,7 +115,9 @@ def main(): pred_labels_unique.discard(0) with open( - "experiment_2_a5b5_sem_voxel_offset0_T0l025_{}.csv".format(instance_threshold), + "experiment_2_a5b5_sem_voxel_offset0_T0l025_{}.csv".format( + instance_threshold + ), "a", newline="", ) as file: From 20a0f6b95780212fce11f53426c1ae966e929cfe Mon Sep 17 00:00:00 2001 From: SVivdich02 Date: Wed, 15 May 2024 21:49:53 +0300 Subject: [PATCH 09/21] fixes --- experiment/main_calc_metrics_by_csv.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/experiment/main_calc_metrics_by_csv.py b/experiment/main_calc_metrics_by_csv.py index 598e136..a283a65 100644 --- a/experiment/main_calc_metrics_by_csv.py +++ b/experiment/main_calc_metrics_by_csv.py @@ -58,23 +58,23 @@ def calculate_metrics(file_name): print( "precision={}, 1={}, 0={}".format( - sum_pres/float(len(values_pres)), - pres1/float(len(values_pres)), - pres0/float(len(values_pres)), + sum_pres / float(len(values_pres)), + pres1 / float(len(values_pres)), + pres0 / float(len(values_pres)), ) ) print( "recall={}, 1={}, 0={}".format( - sum_recall/float(len(values_recall)), - recall1/float(len(values_recall)), - recall0/float(len(values_recall)), + sum_recall / float(len(values_recall)), + recall1 / float(len(values_recall)), + recall0 / float(len(values_recall)), ) ) print( "fscore={}, 1={}, 0={}".format( - sum_fScore/float(len(values_fScore)), - fscore1/float(len(values_fScore)), - fscore0/float(len(values_fScore)), + sum_fScore / float(len(values_fScore)), + fscore1 / float(len(values_fScore)), + fscore0 / float(len(values_fScore)), ) ) From aa54a6833ac654d67f4a2e9265d52ed5c9ea511e Mon Sep 17 00:00:00 2001 From: SVivdich02 Date: Wed, 15 May 2024 22:07:35 +0300 Subject: [PATCH 10/21] add hdbscan processing scripts --- ...ut0_sem_voxel_offset0_T0l03_hdbscan_50.csv | 1036 +++++++++++++++++ .../main_kitti_processing_hdbscan_voxel.py | 77 ++ .../main_kitti_processing_metrics_hdbscan.py | 172 +++ main_hdbscan_processing.ipynb | 342 ------ 4 files changed, 1285 insertions(+), 342 deletions(-) create mode 100644 experiment/hdbscan/experiment_1004_4_without0_sem_voxel_offset0_T0l03_hdbscan_50.csv create mode 100644 experiment/hdbscan/main_kitti_processing_hdbscan_voxel.py create mode 100644 experiment/hdbscan/main_kitti_processing_metrics_hdbscan.py delete mode 100644 main_hdbscan_processing.ipynb diff --git a/experiment/hdbscan/experiment_1004_4_without0_sem_voxel_offset0_T0l03_hdbscan_50.csv b/experiment/hdbscan/experiment_1004_4_without0_sem_voxel_offset0_T0l03_hdbscan_50.csv new file mode 100644 index 0000000..cbab34d --- /dev/null +++ b/experiment/hdbscan/experiment_1004_4_without0_sem_voxel_offset0_T0l03_hdbscan_50.csv @@ -0,0 +1,1036 @@ +start_index,end_index,precision,recall,fScore,gt_inst_count,pred_inst_count,pred_total_inst_count +0,4,0.0,0.0,0.0,1,0,7 +4,8,0.0,0.0,0.0,1,1,6 +8,12,0.0,0.0,0.0,2,0,3 +12,16,0.5,0.5,0.5,2,2,5 +16,20,1.0,0.3333333333333333,0.5,3,1,3 +20,24,1.0,0.25,0.4,4,1,4 +24,28,1.0,0.3333333333333333,0.5,3,1,7 +28,32,0.5,0.4,0.4444444444444445,5,4,9 +32,36,0.0,0.0,0.0,3,1,3 +36,40,0.0,0.0,0.0,3,0,7 +40,44,0.0,0.0,0.0,1,0,1 +44,48,0.0,0.0,0.0,2,0,2 +48,52,0.5,0.25,0.3333333333333333,4,2,11 +52,56,0.3333333333333333,0.25,0.28571428571428575,4,3,7 +56,60,1.0,0.16666666666666666,0.2857142857142857,6,1,4 +60,64,0.0,0.0,0.0,5,0,2 +64,68,0.0,0.0,0.0,5,1,6 +68,72,0.0,0.0,0.0,6,0,2 +72,76,0.5,0.2,0.28571428571428575,5,2,8 +76,80,0.0,0.0,0.0,3,0,1 +80,84,1.0,0.25,0.4,4,1,6 +84,88,1.0,0.3333333333333333,0.5,3,1,2 +88,92,0.0,0.0,0.0,1,0,1 +92,96,0.0,0.0,0.0,3,1,1 +96,100,0.0,0.0,0.0,5,2,9 +100,104,1.0,0.5,0.6666666666666666,6,3,12 +104,108,0.0,0.0,0.0,5,0,15 +108,112,0.04,0.14285714285714285,0.0625,7,25,124 +112,116,0.0,0.0,0.0,4,0,7 +116,120,0.0,0.0,0.0,3,0,7 +120,124,1.0,0.25,0.4,4,1,17 +124,128,1.0,0.2,0.33333333333333337,5,1,16 +128,132,0.0,0.0,0.0,5,0,12 +132,136,0.0,0.0,0.0,3,0,9 +136,140,0.0,0.0,0.0,2,0,10 +140,144,0.0,0.0,0.0,2,0,7 +144,148,0.0,0.0,0.0,1,1,2 +148,152,0.0,0.0,0.0,1,0,5 +152,156,0.0,0.0,0.0,1,0,1 +156,160,0.0,0.0,0.0,3,0,6 +160,164,0.0,0.0,0.0,3,0,3 +164,168,0.0,0.0,0.0,3,0,9 +168,172,0.0,0.0,0.0,3,1,7 +172,176,0.0,0.0,0.0,2,1,13 +176,180,1.0,0.5,0.6666666666666666,4,2,8 +180,184,0.0,0.0,0.0,2,1,3 +184,188,0.0,0.0,0.0,2,0,3 +188,192,0.0,0.0,0.0,2,0,4 +192,196,1.0,0.25,0.4,4,1,10 +196,200,0.0,0.0,0.0,4,0,28 +200,204,0.0,0.0,0.0,3,0,21 +204,208,0.0,0.0,0.0,4,2,31 +208,212,0.0,0.0,0.0,3,0,3 +212,216,0.0,0.0,0.0,3,0,6 +216,220,0.0,0.0,0.0,2,0,1 +220,224,0.0,0.0,0.0,3,0,1 +224,228,0.0,0.0,0.0,3,0,4 +228,232,0.0,0.0,0.0,3,0,4 +232,236,0.0,0.0,0.0,3,0,5 +236,240,0.0,0.0,0.0,3,0,4 +240,244,0.0,0.0,0.0,3,0,1 +244,248,0.0,0.0,0.0,2,0,2 +248,252,0.0,0.0,0.0,1,0,6 +252,256,0.0,0.0,0.0,2,1,4 +256,260,0.0,0.0,0.0,1,0,3 +260,264,0.0,0.0,0.0,2,0,2 +264,268,0.0,0.0,0.0,2,0,1 +268,272,0.0,0.0,0.0,4,0,3 +272,276,1.0,0.25,0.4,4,1,1 +276,280,0.0,0.0,0.0,3,0,4 +280,284,1.0,0.3333333333333333,0.5,3,1,3 +284,288,0.0,0.0,0.0,2,0,6 +288,292,0.0,0.0,0.0,3,1,6 +292,296,0.0,0.0,0.0,2,0,1 +296,300,0.0,0.0,0.0,3,1,4 +300,304,0.3333333333333333,0.25,0.28571428571428575,4,3,10 +304,308,0.6666666666666666,0.5,0.5714285714285715,4,3,5 +308,312,0.0,0.0,0.0,4,0,5 +312,316,0.0,0.0,0.0,4,1,6 +316,320,0.0,0.0,0.0,2,0,5 +320,324,0.0,0.0,0.0,1,0,3 +324,328,1.0,0.5,0.6666666666666666,2,1,3 +328,332,0.0,0.0,0.0,3,0,1 +332,336,0.08333333333333333,0.5,0.14285714285714285,2,12,131 +336,340,0.0,0.0,0.0,3,0,2 +340,344,0.0,0.0,0.0,3,0,2 +344,348,0.0,0.0,0.0,3,0,3 +348,352,0.5,0.25,0.3333333333333333,4,2,4 +352,356,0.0,0.0,0.0,2,1,1 +356,360,0.0,0.0,0.0,2,1,1 +360,364,0.0,0.0,0.0,2,1,5 +364,368,0.0,0.0,0.0,2,0,5 +368,372,0.0,0.0,0.0,2,0,4 +372,376,0.0,0.0,0.0,1,0,2 +376,380,0.0,0.0,0.0,2,0,5 +380,384,0.0,0.0,0.0,2,0,6 +384,388,1.0,0.5,0.6666666666666666,2,1,5 +388,392,0.0,0.0,0.0,1,0,2 +392,396,0.0,0.0,0.0,1,0,3 +396,400,1.0,0.3333333333333333,0.5,3,1,5 +400,404,1.0,1.0,1.0,1,1,1 +412,416,0.0,0.0,0.0,2,0,1 +416,420,0.0,0.0,0.0,2,0,4 +420,424,0.0,0.0,0.0,4,0,2 +424,428,0.0,0.0,0.0,3,0,2 +428,432,0.0,0.0,0.0,3,0,5 +432,436,0.0,0.0,0.0,3,0,2 +436,440,0.0,0.0,0.0,3,0,5 +440,444,0.0,0.0,0.0,3,1,9 +444,448,0.0,0.0,0.0,2,0,2 +448,452,0.0,0.0,0.0,1,0,2 +452,456,0.0,0.0,0.0,2,0,2 +456,460,0.0,0.0,0.0,1,0,1 +460,464,0.0,0.0,0.0,2,0,3 +464,468,0.0,0.0,0.0,3,0,5 +468,472,0.0,0.0,0.0,4,1,3 +472,476,0.0,0.0,0.0,4,2,7 +476,480,0.0,0.0,0.0,4,0,1 +480,484,0.0,0.0,0.0,4,0,6 +484,488,0.0,0.0,0.0,4,1,1 +488,492,0.0,0.0,0.0,2,0,2 +492,496,0.0,0.0,0.0,1,0,7 +496,500,0.0,0.0,0.0,2,0,4 +500,504,0.0,0.0,0.0,2,0,6 +504,508,1.0,0.3333333333333333,0.5,3,1,2 +508,512,0.0,0.0,0.0,2,0,3 +512,516,0.0,0.0,0.0,2,0,6 +516,520,0.0,0.0,0.0,2,0,2 +520,524,1.0,0.1111111111111111,0.19999999999999998,9,1,3 +524,528,0.5,0.1111111111111111,0.1818181818181818,9,2,3 +528,532,0.4,0.3333333333333333,0.3636363636363636,6,5,6 +532,536,0.6666666666666666,0.2857142857142857,0.4,7,3,7 +536,540,0.75,0.42857142857142855,0.5454545454545454,7,4,6 +540,544,0.46153846153846156,0.8571428571428571,0.6,7,13,41 +544,548,0.6666666666666666,0.3333333333333333,0.4444444444444444,6,3,6 +548,552,0.7142857142857143,0.8333333333333334,0.7692307692307692,6,7,48 +552,556,0.8333333333333334,0.8333333333333334,0.8333333333333334,6,6,52 +556,560,0.5,0.3333333333333333,0.4,6,4,10 +560,564,0.75,0.5,0.6,6,4,9 +564,568,0.6,0.5,0.5454545454545454,6,5,10 +568,572,0.5,0.16666666666666666,0.25,6,2,4 +572,576,0.0,0.0,0.0,7,2,10 +576,580,0.6666666666666666,0.25,0.36363636363636365,8,3,8 +580,584,0.375,0.8571428571428571,0.5217391304347825,7,16,110 +584,588,0.0,0.0,0.0,8,0,2 +588,592,0.0,0.0,0.0,8,0,7 +592,596,1.0,0.25,0.4,8,2,7 +596,600,1.0,0.42857142857142855,0.6,7,3,7 +600,604,0.5,0.2,0.28571428571428575,5,2,6 +604,608,0.0,0.0,0.0,4,0,3 +608,612,0.0,0.0,0.0,3,0,8 +612,616,1.0,0.25,0.4,4,1,2 +616,620,0.3333333333333333,0.3333333333333333,0.3333333333333333,3,3,6 +620,624,0.5,0.2,0.28571428571428575,5,2,4 +624,628,0.5,0.16666666666666666,0.25,6,2,4 +628,632,0.3333333333333333,0.2857142857142857,0.30769230769230765,7,6,8 +632,636,0.6666666666666666,0.3333333333333333,0.4444444444444444,6,3,9 +636,640,1.0,0.5714285714285714,0.7272727272727273,7,4,7 +640,644,0.5,0.2,0.28571428571428575,5,2,3 +644,648,0.0,0.0,0.0,6,0,2 +648,652,0.0,0.0,0.0,8,0,2 +652,656,0.0,0.0,0.0,7,0,4 +656,660,1.0,0.14285714285714285,0.25,7,1,1 +660,664,0.0,0.0,0.0,4,1,1 +664,668,0.0,0.0,0.0,7,0,4 +668,672,0.375,0.42857142857142855,0.39999999999999997,7,8,14 +672,676,0.6,0.42857142857142855,0.5,7,5,7 +676,680,0.75,0.42857142857142855,0.5454545454545454,7,4,9 +680,684,0.0,0.0,0.0,6,0,2 +684,688,0.5,0.25,0.3333333333333333,4,2,9 +688,692,0.0,0.0,0.0,4,0,1 +692,696,0.6666666666666666,0.5,0.5714285714285715,4,3,7 +696,700,0.0,0.0,0.0,5,0,1 +700,704,0.0,0.0,0.0,5,0,1 +704,708,0.0,0.0,0.0,4,0,1 +708,712,1.0,0.25,0.4,4,1,7 +712,716,0.0,0.0,0.0,1,0,2 +716,720,1.0,1.0,1.0,1,1,1 +724,728,0.0,0.0,0.0,1,0,1 +728,732,0.0,0.0,0.0,1,0,4 +732,736,0.0,0.0,0.0,1,0,4 +736,740,0.0,0.0,0.0,3,0,5 +740,744,0.0,0.0,0.0,1,0,1 +744,748,0.0,0.0,0.0,2,0,6 +748,752,0.0,0.0,0.0,2,0,10 +752,756,0.0,0.0,0.0,3,0,1 +756,760,0.0,0.0,0.0,2,1,4 +760,764,0.0,0.0,0.0,2,0,1 +764,768,0.0,0.0,0.0,2,0,8 +768,772,1.0,0.5,0.6666666666666666,2,1,6 +772,776,0.0,0.0,0.0,2,1,9 +776,780,0.0,0.0,0.0,3,0,2 +780,784,0.0,0.0,0.0,3,0,2 +784,788,0.0,0.0,0.0,4,0,1 +788,792,0.0,0.0,0.0,4,0,9 +792,796,1.0,0.25,0.4,4,1,8 +796,800,0.0,0.0,0.0,2,0,1 +800,804,0.0,0.0,0.0,2,1,2 +804,808,0.0,0.0,0.0,1,0,2 +808,812,1.0,0.5,0.6666666666666666,2,1,3 +812,816,0.0,0.0,0.0,1,0,2 +816,820,0.0,0.0,0.0,1,0,7 +820,824,0.0,0.0,0.0,1,0,1 +832,836,0.0,0.0,0.0,2,0,1 +836,840,0.0,0.0,0.0,2,0,6 +840,844,0.0,0.0,0.0,3,0,9 +844,848,0.0,0.0,0.0,1,0,2 +848,852,0.0,0.0,0.0,3,0,2 +852,856,0.0,0.0,0.0,3,0,3 +856,860,0.0,0.0,0.0,3,0,3 +860,864,0.0,0.0,0.0,2,0,2 +864,868,0.0,0.0,0.0,2,0,4 +868,872,0.0,0.0,0.0,1,0,3 +880,884,0.0,0.0,0.0,1,0,1 +884,888,0.0,0.0,0.0,1,0,5 +888,892,0.0,0.0,0.0,2,0,4 +892,896,0.0,0.0,0.0,2,0,7 +896,900,0.3333333333333333,0.25,0.28571428571428575,4,3,22 +900,904,0.0,0.0,0.0,3,0,7 +904,908,0.0,0.0,0.0,3,0,1 +908,912,0.0,0.0,0.0,2,0,5 +912,916,0.0,0.0,0.0,2,0,7 +916,920,0.0,0.0,0.0,2,0,8 +920,924,0.0,0.0,0.0,1,0,3 +924,928,0.0,0.0,0.0,2,0,1 +928,932,0.0,0.0,0.0,2,0,3 +932,936,0.0,0.0,0.0,3,0,3 +936,940,0.0,0.0,0.0,3,0,4 +940,944,0.0,0.0,0.0,2,0,2 +944,948,0.0,0.0,0.0,2,0,4 +952,956,0.0,0.0,0.0,1,0,6 +956,960,0.0,0.0,0.0,1,0,1 +960,964,1.0,1.0,1.0,1,1,2 +964,968,1.0,1.0,1.0,1,1,2 +968,972,0.0,0.0,0.0,1,0,6 +972,976,0.0,0.0,0.0,2,0,3 +976,980,0.0,0.0,0.0,2,0,7 +980,984,0.0,0.0,0.0,2,0,6 +984,988,0.0,0.0,0.0,2,0,1 +988,992,0.0,0.0,0.0,3,0,7 +992,996,0.0,0.0,0.0,3,1,6 +996,1000,0.0,0.0,0.0,1,0,3 +1000,1004,0.0,0.0,0.0,1,0,3 +1004,1008,0.0,0.0,0.0,1,0,5 +1008,1012,0.0,0.0,0.0,2,0,1 +1012,1016,0.0,0.0,0.0,2,0,1 +1016,1020,0.0,0.0,0.0,4,1,3 +1020,1024,0.0,0.0,0.0,4,0,4 +1024,1028,0.0,0.0,0.0,4,0,3 +1028,1032,0.0,0.0,0.0,4,0,2 +1032,1036,0.0,0.0,0.0,4,1,3 +1036,1040,0.0,0.0,0.0,4,1,4 +1040,1044,0.0,0.0,0.0,4,0,10 +1044,1048,0.0,0.0,0.0,5,0,2 +1048,1052,0.0,0.0,0.0,5,1,2 +1052,1056,0.0,0.0,0.0,3,1,5 +1056,1060,0.0,0.0,0.0,4,4,10 +1060,1064,0.0,0.0,0.0,5,1,4 +1064,1068,0.0,0.0,0.0,5,1,8 +1068,1072,0.0,0.0,0.0,3,0,5 +1072,1076,0.0,0.0,0.0,3,0,10 +1076,1080,0.0,0.0,0.0,2,0,4 +1080,1084,0.0,0.0,0.0,3,0,15 +1084,1088,0.0,0.0,0.0,2,0,12 +1088,1092,0.0,0.0,0.0,1,0,8 +1092,1096,0.0,0.0,0.0,1,0,11 +1096,1100,0.0,0.0,0.0,2,0,3 +1100,1104,0.0,0.0,0.0,2,0,8 +1104,1108,0.0,0.0,0.0,3,0,1 +1108,1112,0.16666666666666666,0.6,0.2608695652173913,5,18,101 +1112,1116,0.0,0.0,0.0,5,0,1 +1116,1120,1.0,0.2,0.33333333333333337,5,1,4 +1120,1124,0.0,0.0,0.0,4,0,1 +1124,1128,0.0,0.0,0.0,3,1,3 +1128,1132,0.0,0.0,0.0,3,0,2 +1132,1136,0.0,0.0,0.0,4,0,1 +1136,1140,0.0,0.0,0.0,1,0,4 +1140,1144,0.0,0.0,0.0,1,0,5 +1144,1148,0.5,1.0,0.6666666666666666,1,2,3 +1180,1184,0.0,0.0,0.0,1,0,7 +1184,1188,0.0,0.0,0.0,1,0,18 +1188,1192,0.0,0.0,0.0,2,0,6 +1192,1196,1.0,0.5,0.6666666666666666,2,1,19 +1196,1200,0.0,0.0,0.0,2,0,4 +1200,1204,0.0,0.0,0.0,1,0,12 +1204,1208,0.0,0.0,0.0,1,0,4 +1208,1212,0.0,0.0,0.0,1,0,2 +1212,1216,0.0,0.0,0.0,3,0,2 +1216,1220,0.0,0.0,0.0,3,1,7 +1220,1224,0.0,0.0,0.0,4,0,3 +1224,1228,0.0,0.0,0.0,4,0,7 +1228,1232,0.0,0.0,0.0,3,0,2 +1232,1236,0.0,0.0,0.0,4,0,6 +1236,1240,1.0,0.3333333333333333,0.5,3,1,4 +1240,1244,0.0,0.0,0.0,2,1,7 +1244,1248,1.0,0.25,0.4,4,1,9 +1248,1252,0.0,0.0,0.0,4,0,6 +1252,1256,0.0,0.0,0.0,3,0,10 +1256,1260,0.0,0.0,0.0,3,0,4 +1260,1264,0.0,0.0,0.0,4,0,9 +1264,1268,0.15384615384615385,0.5,0.23529411764705882,4,13,113 +1268,1272,1.0,0.2,0.33333333333333337,5,1,3 +1272,1276,0.0,0.0,0.0,5,0,5 +1276,1280,0.0,0.0,0.0,5,0,6 +1280,1284,0.5,0.4,0.4444444444444445,5,4,12 +1284,1288,1.0,0.5,0.6666666666666666,4,2,20 +1288,1292,0.0,0.0,0.0,4,0,1 +1292,1296,0.0,0.0,0.0,6,1,11 +1296,1300,0.0,0.0,0.0,4,15,104 +1300,1304,0.0,0.0,0.0,4,0,4 +1304,1308,0.0,0.0,0.0,4,0,6 +1308,1312,0.0,0.0,0.0,5,0,7 +1312,1316,0.0,0.0,0.0,5,0,6 +1316,1320,0.0,0.0,0.0,3,1,8 +1320,1324,0.0,0.0,0.0,4,1,2 +1324,1328,0.0,0.0,0.0,3,0,1 +1328,1332,0.0,0.0,0.0,3,0,7 +1332,1336,0.0,0.0,0.0,3,0,11 +1336,1340,0.0,0.0,0.0,3,0,7 +1340,1344,0.0,0.0,0.0,4,0,9 +1344,1348,0.0,0.0,0.0,3,0,6 +1348,1352,0.0,0.0,0.0,2,0,1 +1352,1356,0.0,0.0,0.0,2,0,1 +1356,1360,0.0,0.0,0.0,4,3,9 +1360,1364,0.2,0.2,0.20000000000000004,5,5,13 +1364,1368,0.0,0.0,0.0,3,0,4 +1368,1372,0.8,0.6666666666666666,0.7272727272727272,6,5,90 +1372,1376,0.0,0.0,0.0,4,1,1 +1376,1380,0.0,0.0,0.0,2,1,6 +1380,1384,0.0,0.0,0.0,3,0,2 +1384,1388,0.0,0.0,0.0,3,0,3 +1388,1392,0.0,0.0,0.0,2,0,6 +1392,1396,0.0,0.0,0.0,3,0,2 +1396,1400,0.0,0.0,0.0,3,0,1 +1400,1404,0.0,0.0,0.0,3,0,1 +1404,1408,0.0,0.0,0.0,2,0,3 +1408,1412,0.0,0.0,0.0,3,0,3 +1412,1416,0.0,0.0,0.0,5,0,1 +1416,1420,0.0,0.0,0.0,4,0,2 +1420,1424,1.0,0.3333333333333333,0.5,3,1,6 +1424,1428,0.0,0.0,0.0,3,0,3 +1428,1432,0.0,0.0,0.0,2,1,6 +1432,1436,0.0,0.0,0.0,4,1,7 +1436,1440,0.0,0.0,0.0,4,1,8 +1440,1444,0.0,0.0,0.0,6,2,8 +1444,1448,0.5,0.2,0.28571428571428575,5,2,10 +1448,1452,0.3333333333333333,0.16666666666666666,0.2222222222222222,6,3,7 +1452,1456,0.5,0.1111111111111111,0.1818181818181818,9,2,4 +1456,1460,0.0,0.0,0.0,12,0,5 +1460,1464,1.0,0.09090909090909091,0.16666666666666669,11,1,4 +1464,1468,0.3333333333333333,0.1111111111111111,0.16666666666666666,9,3,7 +1468,1472,0.5,0.1111111111111111,0.1818181818181818,9,2,6 +1472,1476,1.0,0.1,0.18181818181818182,10,1,5 +1476,1480,0.0,0.0,0.0,11,0,4 +1480,1484,0.0,0.0,0.0,9,0,3 +1484,1488,1.0,0.25,0.4,8,2,7 +1488,1492,1.0,0.2,0.33333333333333337,10,2,5 +1492,1496,0.0,0.0,0.0,8,0,2 +1496,1500,0.0,0.0,0.0,7,0,2 +1500,1504,0.0,0.0,0.0,7,0,2 +1504,1508,1.0,0.16666666666666666,0.2857142857142857,6,1,2 +1508,1512,0.0,0.0,0.0,3,0,2 +1512,1516,0.0,0.0,0.0,3,0,3 +1516,1520,0.0,0.0,0.0,4,0,4 +1520,1524,0.3333333333333333,0.16666666666666666,0.2222222222222222,6,3,7 +1524,1528,0.0,0.0,0.0,8,0,1 +1528,1532,0.0,0.0,0.0,7,0,3 +1532,1536,0.0,0.0,0.0,4,0,4 +1536,1540,1.0,0.2,0.33333333333333337,5,1,3 +1540,1544,0.0,0.0,0.0,2,0,1 +1544,1548,0.0,0.0,0.0,3,0,1 +1548,1552,0.0,0.0,0.0,5,0,1 +1552,1556,0.0,0.0,0.0,4,0,2 +1556,1560,1.0,0.2,0.33333333333333337,5,1,16 +1560,1564,0.0,0.0,0.0,4,0,13 +1564,1568,0.0,0.0,0.0,3,0,8 +1568,1572,0.0,0.0,0.0,4,0,13 +1572,1576,0.25,0.5,0.3333333333333333,4,8,86 +1576,1580,1.0,0.25,0.4,4,1,8 +1580,1584,0.0,0.0,0.0,2,0,1 +1584,1588,0.0,0.0,0.0,2,0,8 +1588,1592,0.0,0.0,0.0,1,0,1 +1592,1596,0.0,0.0,0.0,1,0,5 +1596,1600,0.0,0.0,0.0,1,0,1 +1600,1604,0.0,0.0,0.0,3,0,5 +1604,1608,0.0,0.0,0.0,3,0,1 +1608,1612,0.0,0.0,0.0,3,0,3 +1612,1616,0.0,0.0,0.0,3,1,7 +1616,1620,1.0,0.3333333333333333,0.5,3,1,9 +1620,1624,0.0,0.0,0.0,3,0,1 +1624,1628,0.0,0.0,0.0,2,0,2 +1628,1632,0.0,0.0,0.0,3,0,17 +1632,1636,1.0,0.5,0.6666666666666666,4,2,18 +1636,1640,0.6666666666666666,0.4,0.5,5,3,26 +1640,1644,0.0,0.0,0.0,5,0,12 +1644,1648,0.0,0.0,0.0,6,0,6 +1648,1652,1.0,0.16666666666666666,0.2857142857142857,6,1,4 +1652,1656,0.0,0.0,0.0,3,0,1 +1656,1660,0.0,0.0,0.0,3,0,7 +1660,1664,1.0,1.0,1.0,1,1,3 +1664,1668,0.0,0.0,0.0,1,0,1 +1668,1672,0.0,0.0,0.0,1,0,1 +1672,1676,0.0,0.0,0.0,1,0,5 +1676,1680,0.0,0.0,0.0,2,0,3 +1680,1684,0.0,0.0,0.0,2,0,7 +1684,1688,0.0,0.0,0.0,1,0,12 +1688,1692,0.0,0.0,0.0,1,0,12 +1692,1696,1.0,1.0,1.0,1,1,1 +1696,1700,0.0,0.0,0.0,1,0,3 +1700,1704,0.0,0.0,0.0,1,0,1 +1704,1708,0.0,0.0,0.0,1,1,7 +1708,1712,0.0,0.0,0.0,2,0,8 +1712,1716,0.0,0.0,0.0,1,0,12 +1716,1720,0.0,0.0,0.0,2,0,4 +1720,1724,0.0,0.0,0.0,2,0,13 +1724,1728,0.0,0.0,0.0,2,0,13 +1728,1732,1.0,0.25,0.4,4,1,11 +1732,1736,0.0,0.0,0.0,3,0,13 +1736,1740,0.0,0.0,0.0,2,1,4 +1740,1744,0.0,0.0,0.0,2,1,4 +1744,1748,0.0,0.0,0.0,1,0,1 +1748,1752,0.0,0.0,0.0,1,0,10 +1752,1756,0.0,0.0,0.0,2,0,17 +1756,1760,0.0,0.0,0.0,2,1,6 +1760,1764,0.0,0.0,0.0,1,0,6 +1764,1768,0.0,0.0,0.0,1,0,4 +1768,1772,0.0,0.0,0.0,2,2,29 +1772,1776,0.0,0.0,0.0,1,0,4 +1776,1780,0.0,0.0,0.0,1,0,5 +1780,1784,0.0,0.0,0.0,3,1,5 +1784,1788,0.0,0.0,0.0,2,0,6 +1788,1792,0.0,0.0,0.0,2,0,6 +1792,1796,0.0,0.0,0.0,2,1,10 +1796,1800,0.0,0.0,0.0,2,0,1 +1800,1804,1.0,0.25,0.4,4,1,7 +1804,1808,0.0,0.0,0.0,3,1,7 +1808,1812,0.0,0.0,0.0,3,2,4 +1812,1816,0.0,0.0,0.0,2,0,3 +1816,1820,0.0,0.0,0.0,2,0,2 +1820,1824,0.0,0.0,0.0,2,1,9 +1824,1828,0.3333333333333333,0.3333333333333333,0.3333333333333333,3,3,13 +1828,1832,0.0,0.0,0.0,2,0,12 +1832,1836,0.0,0.0,0.0,2,0,12 +1836,1840,0.0,0.0,0.0,2,0,8 +1840,1844,0.0,0.0,0.0,1,0,3 +1844,1848,0.0,0.0,0.0,2,0,2 +1848,1852,0.0,0.0,0.0,2,0,11 +1852,1856,0.0,0.0,0.0,2,1,4 +1856,1860,0.0,0.0,0.0,3,0,4 +1860,1864,0.0,0.0,0.0,2,4,6 +1864,1868,1.0,0.3333333333333333,0.5,3,1,1 +1868,1872,0.0,0.0,0.0,3,2,10 +1872,1876,0.0,0.0,0.0,3,0,4 +1876,1880,0.0,0.0,0.0,2,0,1 +1892,1896,0.0,0.0,0.0,1,0,11 +1896,1900,0.0,0.0,0.0,1,0,4 +1900,1904,0.0,0.0,0.0,1,0,3 +1904,1908,0.0,0.0,0.0,2,0,1 +1908,1912,0.0,0.0,0.0,2,1,1 +1912,1916,0.0,0.0,0.0,2,0,3 +1916,1920,0.0,0.0,0.0,1,0,3 +1920,1924,0.5,0.3333333333333333,0.4,3,2,13 +1924,1928,0.0,0.0,0.0,3,0,1 +1928,1932,0.0,0.0,0.0,2,0,5 +1932,1936,0.0,0.0,0.0,2,0,11 +1936,1940,0.5,0.3333333333333333,0.4,3,2,18 +1940,1944,0.0,0.0,0.0,2,0,20 +1944,1948,0.0,0.0,0.0,2,0,17 +1948,1952,0.0,0.0,0.0,1,0,18 +1952,1956,1.0,0.3333333333333333,0.5,3,1,10 +1956,1960,0.0,0.0,0.0,2,0,8 +1960,1964,1.0,0.3333333333333333,0.5,3,1,9 +1964,1968,0.6666666666666666,0.6666666666666666,0.6666666666666666,3,3,12 +1968,1972,0.0,0.0,0.0,1,0,3 +1972,1976,0.0,0.0,0.0,2,0,1 +1976,1980,0.0,0.0,0.0,2,0,2 +1980,1984,0.0,0.0,0.0,3,0,2 +1984,1988,1.0,0.3333333333333333,0.5,3,1,8 +1988,1992,0.0,0.0,0.0,2,0,7 +1992,1996,0.0,0.0,0.0,2,0,14 +1996,2000,1.0,0.5,0.6666666666666666,2,1,9 +2000,2004,0.0,0.0,0.0,2,0,16 +2004,2008,0.0,0.0,0.0,2,0,2 +2008,2012,0.0,0.0,0.0,3,0,10 +2012,2016,0.0,0.0,0.0,3,0,4 +2016,2020,0.0,0.0,0.0,2,0,6 +2020,2024,0.0,0.0,0.0,2,0,1 +2024,2028,0.0,0.0,0.0,2,1,10 +2028,2032,0.0,0.0,0.0,2,0,12 +2032,2036,0.0,0.0,0.0,3,0,8 +2036,2040,0.0,0.0,0.0,3,0,9 +2040,2044,0.0,0.0,0.0,3,0,3 +2044,2048,0.0,0.0,0.0,2,0,4 +2048,2052,1.0,0.5,0.6666666666666666,2,1,5 +2052,2056,0.0,0.0,0.0,1,2,17 +2076,2080,1.0,1.0,1.0,1,1,13 +2100,2104,0.0,0.0,0.0,1,0,3 +2104,2108,0.0,0.0,0.0,1,0,5 +2108,2112,0.0,0.0,0.0,1,0,19 +2112,2116,1.0,0.5,0.6666666666666666,2,1,23 +2116,2120,0.0,0.0,0.0,4,0,15 +2120,2124,0.0,0.0,0.0,3,0,11 +2124,2128,0.0,0.0,0.0,3,0,10 +2128,2132,0.0,0.0,0.0,3,0,2 +2132,2136,0.0,0.0,0.0,1,0,1 +2136,2140,0.0,0.0,0.0,1,0,4 +2140,2144,0.0,0.0,0.0,2,1,7 +2144,2148,0.0,0.0,0.0,1,0,4 +2148,2152,0.0,0.0,0.0,1,0,4 +2152,2156,0.0,0.0,0.0,1,0,3 +2156,2160,0.0,0.0,0.0,1,0,1 +2172,2176,0.0,0.0,0.0,1,0,3 +2176,2180,0.0,0.0,0.0,1,0,6 +2180,2184,0.0,0.0,0.0,1,1,7 +2184,2188,0.0,0.0,0.0,1,0,4 +2188,2192,0.0,0.0,0.0,1,0,10 +2192,2196,0.0,0.0,0.0,2,0,4 +2196,2200,0.0,0.0,0.0,3,0,1 +2200,2204,0.0,0.0,0.0,3,1,3 +2204,2208,0.0,0.0,0.0,4,0,4 +2208,2212,0.0,0.0,0.0,3,0,9 +2212,2216,0.0,0.0,0.0,2,0,5 +2216,2220,0.0,0.0,0.0,1,0,4 +2220,2224,0.5,0.6666666666666666,0.5714285714285715,3,4,9 +2224,2228,0.5,0.3333333333333333,0.4,3,2,10 +2228,2232,0.0,0.0,0.0,4,0,2 +2232,2236,0.0,0.0,0.0,1,0,2 +2236,2240,0.0,0.0,0.0,1,0,1 +2240,2244,0.0,0.0,0.0,1,0,4 +2244,2248,0.0,0.0,0.0,1,0,2 +2248,2252,0.0,0.0,0.0,1,1,6 +2252,2256,0.0,0.0,0.0,1,1,5 +2256,2260,0.0,0.0,0.0,1,1,3 +2260,2264,0.0,0.0,0.0,1,1,8 +2264,2268,0.0,0.0,0.0,1,2,7 +2268,2272,0.0,0.0,0.0,2,0,3 +2272,2276,0.0,0.0,0.0,2,0,6 +2276,2280,0.0,0.0,0.0,2,0,5 +2280,2284,1.0,0.5,0.6666666666666666,2,1,1 +2284,2288,1.0,0.6666666666666666,0.8,3,2,7 +2288,2292,1.0,0.3333333333333333,0.5,3,1,7 +2292,2296,0.5,0.25,0.3333333333333333,4,2,4 +2296,2300,0.0,0.0,0.0,3,2,8 +2300,2304,0.0,0.0,0.0,3,0,3 +2304,2308,0.0,0.0,0.0,3,0,6 +2308,2312,0.5,0.3333333333333333,0.4,3,2,11 +2312,2316,1.0,0.3333333333333333,0.5,3,1,15 +2316,2320,0.6666666666666666,0.5,0.5714285714285715,4,3,10 +2320,2324,0.0,0.0,0.0,5,0,6 +2324,2328,0.0,0.0,0.0,6,0,4 +2328,2332,0.0,0.0,0.0,5,0,3 +2332,2336,0.0,0.0,0.0,4,0,7 +2336,2340,0.0,0.0,0.0,4,0,6 +2340,2344,0.0,0.0,0.0,3,0,5 +2344,2348,0.5,0.3333333333333333,0.4,3,2,7 +2348,2352,0.0,0.0,0.0,2,0,4 +2352,2356,0.5,0.25,0.3333333333333333,4,2,10 +2356,2360,0.0,0.0,0.0,3,0,8 +2360,2364,0.0,0.0,0.0,4,1,9 +2364,2368,0.0,0.0,0.0,3,0,5 +2368,2372,0.0,0.0,0.0,2,1,3 +2372,2376,0.0,0.0,0.0,1,0,4 +2376,2380,0.0,0.0,0.0,2,0,3 +2380,2384,0.0,0.0,0.0,1,0,1 +2384,2388,0.0,0.0,0.0,2,0,3 +2388,2392,0.0,0.0,0.0,2,1,11 +2392,2396,0.0,0.0,0.0,2,0,6 +2396,2400,0.0,0.0,0.0,1,0,9 +2400,2404,0.0,0.0,0.0,2,0,5 +2404,2408,0.0,0.0,0.0,1,0,5 +2408,2412,0.0,0.0,0.0,1,0,1 +2412,2416,0.0,0.0,0.0,1,0,3 +2416,2420,0.0,0.0,0.0,3,0,5 +2420,2424,0.0,0.0,0.0,3,1,4 +2424,2428,0.0,0.0,0.0,2,0,1 +2428,2432,0.0,0.0,0.0,2,0,4 +2432,2436,0.0,0.0,0.0,2,1,6 +2436,2440,0.0,0.0,0.0,2,1,6 +2440,2444,1.0,0.5,0.6666666666666666,2,1,5 +2444,2448,0.0,0.0,0.0,1,0,9 +2448,2452,0.0,0.0,0.0,2,0,5 +2452,2456,1.0,0.5,0.6666666666666666,2,1,3 +2460,2464,0.0,0.0,0.0,1,0,2 +2464,2468,0.0,0.0,0.0,1,0,4 +2468,2472,0.0,0.0,0.0,2,0,5 +2472,2476,0.0,0.0,0.0,2,0,2 +2476,2480,0.0,0.0,0.0,3,0,4 +2480,2484,0.0,0.0,0.0,3,0,6 +2484,2488,0.0,0.0,0.0,3,0,6 +2488,2492,0.0,0.0,0.0,3,0,5 +2492,2496,0.0,0.0,0.0,3,0,4 +2496,2500,0.0,0.0,0.0,3,0,1 +2500,2504,1.0,0.3333333333333333,0.5,3,1,4 +2504,2508,0.0,0.0,0.0,3,0,4 +2508,2512,0.0,0.0,0.0,3,5,11 +2512,2516,0.5,0.5,0.5,4,4,7 +2516,2520,1.0,0.3333333333333333,0.5,3,1,1 +2520,2524,0.0,0.0,0.0,3,0,1 +2524,2528,0.0,0.0,0.0,4,3,5 +2528,2532,0.0,0.0,0.0,4,0,5 +2532,2536,0.6666666666666666,0.4,0.5,5,3,6 +2536,2540,0.3333333333333333,0.25,0.28571428571428575,4,3,7 +2540,2544,0.0,0.0,0.0,2,0,2 +2544,2548,0.0,0.0,0.0,3,0,1 +2548,2552,0.0,0.0,0.0,2,0,2 +2552,2556,0.0,0.0,0.0,2,0,5 +2556,2560,1.0,0.6666666666666666,0.8,3,2,12 +2560,2564,0.0,0.0,0.0,4,0,4 +2564,2568,0.0,0.0,0.0,4,0,4 +2568,2572,0.0,0.0,0.0,3,0,1 +2572,2576,0.0,0.0,0.0,3,0,7 +2576,2580,1.0,0.2,0.33333333333333337,5,1,3 +2580,2584,0.5,0.3333333333333333,0.4,3,2,6 +2584,2588,1.0,0.3333333333333333,0.5,3,1,2 +2588,2592,1.0,0.5,0.6666666666666666,4,2,6 +2592,2596,1.0,0.3333333333333333,0.5,3,1,1 +2596,2600,0.0,0.0,0.0,2,0,4 +2600,2604,0.0,0.0,0.0,2,0,2 +2604,2608,0.0,0.0,0.0,1,0,4 +2608,2612,0.0,0.0,0.0,1,0,6 +2612,2616,0.0,0.0,0.0,3,0,8 +2616,2620,1.0,0.25,0.4,4,1,9 +2620,2624,0.0,0.0,0.0,3,0,4 +2624,2628,0.0,0.0,0.0,3,0,6 +2628,2632,0.0,0.0,0.0,3,0,8 +2632,2636,0.0,0.0,0.0,3,1,6 +2636,2640,0.0,0.0,0.0,3,0,4 +2640,2644,1.0,0.3333333333333333,0.5,3,1,2 +2644,2648,0.5,0.5,0.5,2,2,5 +2648,2652,0.0,0.0,0.0,3,0,7 +2652,2656,0.0,0.0,0.0,4,0,5 +2656,2660,0.0,0.0,0.0,4,0,7 +2660,2664,0.0,0.0,0.0,4,0,4 +2664,2668,0.0,0.0,0.0,3,1,8 +2668,2672,0.0,0.0,0.0,3,0,8 +2672,2676,1.0,0.25,0.4,4,1,2 +2676,2680,0.0,0.0,0.0,2,0,2 +2680,2684,0.0,0.0,0.0,3,1,4 +2684,2688,0.0,0.0,0.0,3,0,2 +2688,2692,0.0,0.0,0.0,5,1,4 +2692,2696,0.0,0.0,0.0,6,2,12 +2696,2700,0.0,0.0,0.0,7,2,10 +2700,2704,0.0,0.0,0.0,7,1,12 +2704,2708,0.0,0.0,0.0,7,0,8 +2708,2712,1.0,0.14285714285714285,0.25,7,1,7 +2712,2716,0.0,0.0,0.0,6,1,6 +2716,2720,1.0,0.16666666666666666,0.2857142857142857,6,1,5 +2720,2724,0.0,0.0,0.0,6,0,7 +2724,2728,1.0,0.16666666666666666,0.2857142857142857,6,1,3 +2728,2732,0.0,0.0,0.0,4,0,2 +2732,2736,0.5,0.2,0.28571428571428575,5,2,5 +2736,2740,0.0,0.0,0.0,3,0,2 +2740,2744,0.0,0.0,0.0,3,0,2 +2744,2748,1.0,0.3333333333333333,0.5,3,1,3 +2748,2752,0.0,0.0,0.0,3,1,9 +2752,2756,0.0,0.0,0.0,3,1,21 +2756,2760,0.0,0.0,0.0,4,0,8 +2760,2764,0.0,0.0,0.0,4,0,16 +2764,2768,0.0,0.0,0.0,4,0,11 +2768,2772,0.3333333333333333,0.25,0.28571428571428575,4,3,16 +2772,2776,1.0,0.25,0.4,4,1,5 +2776,2780,0.0,0.0,0.0,4,0,2 +2780,2784,0.5,0.25,0.3333333333333333,4,2,6 +2784,2788,0.0,0.0,0.0,3,0,6 +2788,2792,0.0,0.0,0.0,4,1,3 +2792,2796,0.0,0.0,0.0,3,3,6 +2796,2800,0.0,0.0,0.0,2,1,4 +2800,2804,0.0,0.0,0.0,2,1,3 +2804,2808,0.0,0.0,0.0,3,0,4 +2808,2812,0.0,0.0,0.0,3,0,1 +2812,2816,0.0,0.0,0.0,2,0,3 +2816,2820,0.0,0.0,0.0,2,6,120 +2820,2824,0.0,0.0,0.0,1,1,4 +2824,2828,0.0,0.0,0.0,2,0,2 +2828,2832,0.0,0.0,0.0,2,0,2 +2832,2836,0.0,0.0,0.0,3,1,5 +2836,2840,0.0,0.0,0.0,3,2,4 +2840,2844,0.0,0.0,0.0,3,0,1 +2844,2848,0.0,0.0,0.0,3,0,4 +2848,2852,0.0,0.0,0.0,2,0,9 +2852,2856,0.0,0.0,0.0,1,0,8 +2872,2876,0.0,0.0,0.0,2,0,1 +2876,2880,1.0,0.5,0.6666666666666666,2,1,3 +2880,2884,0.0,0.0,0.0,1,0,1 +2884,2888,0.0,0.0,0.0,1,0,2 +2888,2892,1.0,1.0,1.0,1,1,1 +2896,2900,0.0,0.0,0.0,1,0,2 +2900,2904,0.0,0.0,0.0,2,0,2 +2904,2908,0.0,0.0,0.0,2,0,2 +2908,2912,0.0,0.0,0.0,2,0,1 +2912,2916,0.0,0.0,0.0,1,0,1 +2916,2920,0.0,0.0,0.0,2,0,5 +2920,2924,0.0,0.0,0.0,2,0,2 +2924,2928,0.0,0.0,0.0,2,0,4 +2928,2932,0.0,0.0,0.0,2,0,7 +2932,2936,0.0,0.0,0.0,3,0,2 +2936,2940,1.0,0.25,0.4,4,1,5 +2940,2944,0.0,0.0,0.0,4,2,8 +2944,2948,0.0,0.0,0.0,6,1,2 +2948,2952,0.25,0.14285714285714285,0.18181818181818182,7,4,5 +2952,2956,0.5,0.16666666666666666,0.25,6,2,2 +2956,2960,0.0,0.0,0.0,6,0,2 +2960,2964,0.5,0.16666666666666666,0.25,6,2,5 +2964,2968,0.5,0.6666666666666666,0.5714285714285715,6,8,13 +2968,2972,0.0,0.0,0.0,3,1,1 +2972,2976,0.0,0.0,0.0,3,0,3 +2976,2980,0.0,0.0,0.0,4,0,6 +2980,2984,0.0,0.0,0.0,1,0,12 +2984,2988,0.0,0.0,0.0,3,1,11 +2988,2992,0.0,0.0,0.0,3,1,18 +2992,2996,0.0,0.0,0.0,4,2,23 +2996,3000,0.5,0.25,0.3333333333333333,4,2,6 +3000,3004,0.0,0.0,0.0,2,0,3 +3004,3008,1.0,0.3333333333333333,0.5,3,1,4 +3008,3012,0.0,0.0,0.0,2,0,4 +3012,3016,0.5,0.5,0.5,2,2,7 +3016,3020,0.0,0.0,0.0,1,1,6 +3020,3024,0.0,0.0,0.0,1,0,1 +3024,3028,1.0,1.0,1.0,1,1,1 +3040,3044,0.0,0.0,0.0,2,0,3 +3044,3048,0.0,0.0,0.0,2,1,4 +3048,3052,1.0,0.25,0.4,4,1,5 +3052,3056,1.0,0.2,0.33333333333333337,5,1,3 +3056,3060,0.0,0.0,0.0,3,0,1 +3060,3064,0.0,0.0,0.0,2,0,1 +3064,3068,0.0,0.0,0.0,3,0,2 +3068,3072,0.0,0.0,0.0,2,0,1 +3072,3076,0.0,0.0,0.0,3,0,9 +3076,3080,0.0,0.0,0.0,2,3,10 +3080,3084,0.0,0.0,0.0,2,0,3 +3084,3088,0.0,0.0,0.0,3,2,10 +3088,3092,1.0,0.3333333333333333,0.5,3,1,1 +3092,3096,0.0,0.0,0.0,3,0,3 +3096,3100,0.0,0.0,0.0,3,0,7 +3100,3104,0.0,0.0,0.0,4,0,6 +3104,3108,0.0,0.0,0.0,4,1,15 +3108,3112,0.0,0.0,0.0,3,0,7 +3112,3116,0.0,0.0,0.0,3,0,4 +3116,3120,0.0,0.0,0.0,3,0,5 +3120,3124,0.0,0.0,0.0,3,0,3 +3124,3128,0.0,0.0,0.0,2,0,1 +3128,3132,0.0,0.0,0.0,3,1,4 +3132,3136,0.0,0.0,0.0,3,0,1 +3136,3140,0.0,0.0,0.0,3,0,3 +3140,3144,0.0,0.0,0.0,4,0,3 +3144,3148,1.0,0.25,0.4,4,1,9 +3148,3152,0.0,0.0,0.0,4,0,2 +3152,3156,0.0,0.0,0.0,3,0,7 +3156,3160,0.0,0.0,0.0,4,1,4 +3160,3164,0.0,0.0,0.0,4,2,9 +3164,3168,0.0,0.0,0.0,3,0,1 +3168,3172,0.0,0.0,0.0,2,0,1 +3172,3176,0.5,0.5,0.5,2,2,7 +3176,3180,0.0,0.0,0.0,1,0,4 +3188,3192,0.0,0.0,0.0,1,0,2 +3192,3196,0.0,0.0,0.0,3,0,2 +3196,3200,0.0,0.0,0.0,3,0,3 +3200,3204,1.0,0.25,0.4,4,1,4 +3204,3208,0.0,0.0,0.0,3,0,1 +3208,3212,0.0,0.0,0.0,3,0,2 +3212,3216,1.0,0.25,0.4,4,1,2 +3216,3220,0.0,0.0,0.0,4,0,2 +3220,3224,0.0,0.0,0.0,4,1,4 +3224,3228,0.0,0.0,0.0,4,1,9 +3228,3232,0.0,0.0,0.0,4,1,3 +3232,3236,0.0,0.0,0.0,3,2,7 +3236,3240,0.0,0.0,0.0,4,0,2 +3240,3244,0.0,0.0,0.0,5,0,2 +3244,3248,0.0,0.0,0.0,4,1,11 +3248,3252,0.0,0.0,0.0,2,0,5 +3252,3256,0.0,0.0,0.0,2,0,11 +3256,3260,1.0,0.14285714285714285,0.25,7,1,3 +3260,3264,0.0,0.0,0.0,6,0,5 +3264,3268,1.0,0.16666666666666666,0.2857142857142857,6,1,2 +3268,3272,0.0,0.0,0.0,4,0,2 +3272,3276,1.0,0.2,0.33333333333333337,5,1,5 +3276,3280,0.0,0.0,0.0,6,1,10 +3280,3284,0.5,0.16666666666666666,0.25,6,2,8 +3284,3288,1.0,0.25,0.4,4,1,9 +3288,3292,0.0,0.0,0.0,2,1,10 +3292,3296,0.0,0.0,0.0,3,1,6 +3296,3300,0.25,0.3333333333333333,0.28571428571428575,3,4,24 +3300,3304,1.0,0.3333333333333333,0.5,3,1,6 +3304,3308,0.0,0.0,0.0,2,0,13 +3308,3312,0.0,0.0,0.0,3,0,5 +3312,3316,0.0,0.0,0.0,2,1,3 +3316,3320,0.0,0.0,0.0,1,0,4 +3320,3324,0.0,0.0,0.0,2,0,3 +3324,3328,0.0,0.0,0.0,1,0,2 +3328,3332,0.0,0.0,0.0,2,0,3 +3332,3336,0.0,0.0,0.0,2,0,4 +3336,3340,0.5,0.5,0.5,2,2,5 +3340,3344,0.0,0.0,0.0,1,0,9 +3344,3348,0.0,0.0,0.0,2,0,6 +3348,3352,0.0,0.0,0.0,1,0,13 +3352,3356,0.0,0.0,0.0,1,0,6 +3356,3360,0.0,0.0,0.0,1,0,7 +3360,3364,0.0,0.0,0.0,3,0,4 +3364,3368,0.0,0.0,0.0,2,0,1 +3368,3372,1.0,0.3333333333333333,0.5,3,1,3 +3372,3376,0.0,0.0,0.0,2,0,1 +3376,3380,0.0,0.0,0.0,2,0,5 +3380,3384,0.0,0.0,0.0,2,0,5 +3384,3388,0.0,0.0,0.0,2,0,2 +3388,3392,0.0,0.0,0.0,2,0,2 +3392,3396,0.0,0.0,0.0,1,0,3 +3396,3400,0.0,0.0,0.0,1,0,2 +3400,3404,0.0,0.0,0.0,1,0,4 +3404,3408,0.0,0.0,0.0,3,0,1 +3420,3424,0.0,0.0,0.0,2,0,2 +3424,3428,0.0,0.0,0.0,3,0,5 +3428,3432,0.0,0.0,0.0,4,0,3 +3432,3436,0.0,0.0,0.0,3,0,4 +3436,3440,0.0,0.0,0.0,3,0,2 +3440,3444,0.0,0.0,0.0,3,1,7 +3444,3448,0.0,0.0,0.0,3,0,9 +3448,3452,0.0,0.0,0.0,2,0,6 +3452,3456,0.0,0.0,0.0,1,0,1 +3456,3460,0.0,0.0,0.0,1,0,3 +3460,3464,0.0,0.0,0.0,1,0,1 +3464,3468,0.0,0.0,0.0,2,0,5 +3468,3472,0.0,0.0,0.0,4,1,9 +3472,3476,0.0,0.0,0.0,5,0,1 +3476,3480,0.0,0.0,0.0,4,0,4 +3480,3484,0.0,0.0,0.0,3,1,7 +3484,3488,0.0,0.0,0.0,3,0,4 +3488,3492,0.0,0.0,0.0,2,0,11 +3492,3496,0.0,0.0,0.0,2,0,4 +3496,3500,0.0,0.0,0.0,2,2,9 +3500,3504,0.0,0.0,0.0,2,0,9 +3504,3508,0.0,0.0,0.0,2,0,6 +3508,3512,1.0,0.25,0.4,4,1,4 +3512,3516,1.0,0.09090909090909091,0.16666666666666669,11,1,3 +3516,3520,0.3333333333333333,0.14285714285714285,0.2,7,3,4 +3520,3524,0.0,0.0,0.0,7,0,1 +3524,3528,0.6666666666666666,0.25,0.36363636363636365,8,3,8 +3528,3532,0.0,0.0,0.0,7,2,6 +3532,3536,0.0,0.0,0.0,8,1,4 +3536,3540,0.5,0.6666666666666666,0.5714285714285715,9,12,24 +3540,3544,0.75,0.6666666666666666,0.7058823529411765,9,8,19 +3544,3548,0.0,0.0,0.0,7,1,6 +3548,3552,0.75,0.3333333333333333,0.46153846153846156,9,4,12 +3552,3556,1.0,0.25,0.4,8,2,7 +3556,3560,0.75,0.42857142857142855,0.5454545454545454,7,4,7 +3560,3564,0.6,0.6,0.6,5,5,8 +3564,3568,0.0,0.0,0.0,4,0,7 +3568,3572,0.0,0.0,0.0,4,0,1 +3572,3576,0.0,0.0,0.0,3,0,2 +3576,3580,0.0,0.0,0.0,4,0,2 +3580,3584,0.6666666666666666,0.3333333333333333,0.4444444444444444,6,3,6 +3584,3588,0.5,0.42857142857142855,0.4615384615384615,7,6,9 +3588,3592,1.0,0.16666666666666666,0.2857142857142857,6,1,4 +3592,3596,0.6666666666666666,0.3333333333333333,0.4444444444444444,6,3,6 +3596,3600,0.0,0.0,0.0,7,0,1 +3600,3604,0.0,0.0,0.0,6,0,2 +3604,3608,0.0,0.0,0.0,5,0,4 +3608,3612,1.0,0.2,0.33333333333333337,5,1,4 +3612,3616,0.0,0.0,0.0,8,2,4 +3616,3620,0.2857142857142857,0.25,0.26666666666666666,8,7,10 +3620,3624,0.25,0.2222222222222222,0.23529411764705882,9,8,10 +3624,3628,0.0,0.0,0.0,8,1,7 +3628,3632,0.75,0.5,0.6,6,4,7 +3632,3636,1.0,0.6666666666666666,0.8,3,2,13 +3636,3640,0.0,0.0,0.0,5,0,1 +3640,3644,0.0,0.0,0.0,4,0,1 +3644,3648,0.6666666666666666,0.4,0.5,5,3,5 +3648,3652,0.0,0.0,0.0,4,0,1 +3652,3656,0.0,0.0,0.0,5,1,2 +3656,3660,0.0,0.0,0.0,3,0,2 +3660,3664,0.0,0.0,0.0,2,0,4 +3664,3668,0.0,0.0,0.0,3,0,4 +3668,3672,0.0,0.0,0.0,2,0,2 +3672,3676,0.0,0.0,0.0,3,0,1 +3676,3680,0.0,0.0,0.0,3,0,1 +3680,3684,0.0,0.0,0.0,1,0,2 +3684,3688,0.0,0.0,0.0,2,0,2 +3688,3692,0.0,0.0,0.0,3,0,1 +3692,3696,0.0,0.0,0.0,3,0,1 +3696,3700,0.0,0.0,0.0,2,0,1 +3700,3704,0.0,0.0,0.0,2,0,1 +3704,3708,0.0,0.0,0.0,2,0,4 +3708,3712,0.5,0.5,0.5,2,2,6 +3712,3716,0.0,0.0,0.0,4,0,2 +3716,3720,0.0,0.0,0.0,3,0,1 +3720,3724,0.0,0.0,0.0,4,0,1 +3724,3728,0.0,0.0,0.0,4,0,2 +3728,3732,0.0,0.0,0.0,4,1,7 +3732,3736,0.0,0.0,0.0,2,0,5 +3736,3740,1.0,0.5,0.6666666666666666,2,1,4 +3740,3744,0.0,0.0,0.0,1,0,2 +3760,3764,1.0,0.5,0.6666666666666666,2,1,10 +3764,3768,0.0,0.0,0.0,2,0,1 +3768,3772,0.0,0.0,0.0,1,0,1 +3772,3776,0.0,0.0,0.0,2,0,1 +3776,3780,0.0,0.0,0.0,3,0,4 +3780,3784,0.0,0.0,0.0,2,0,6 +3784,3788,0.0,0.0,0.0,2,0,4 +3788,3792,0.0,0.0,0.0,1,0,5 +3800,3804,0.0,0.0,0.0,1,0,4 +3804,3808,0.0,0.0,0.0,2,0,2 +3808,3812,0.0,0.0,0.0,2,1,16 +3812,3816,1.0,0.25,0.4,4,1,9 +3816,3820,1.0,0.3333333333333333,0.5,3,1,5 +3820,3824,0.0,0.0,0.0,2,0,6 +3824,3828,0.0,0.0,0.0,2,0,6 +3828,3832,0.0,0.0,0.0,1,0,5 +3832,3836,0.0,0.0,0.0,1,0,1 +3836,3840,0.0,0.0,0.0,2,0,2 +3840,3844,0.0,0.0,0.0,3,0,10 +3844,3848,0.0,0.0,0.0,3,0,1 +3848,3852,0.0,0.0,0.0,3,1,6 +3852,3856,0.0,0.0,0.0,2,0,3 +3856,3860,0.0,0.0,0.0,3,0,5 +3860,3864,0.0,0.0,0.0,3,0,11 +3864,3868,0.0,0.0,0.0,4,0,7 +3868,3872,0.5,0.14285714285714285,0.22222222222222224,7,2,9 +3872,3876,1.0,0.16666666666666666,0.2857142857142857,6,1,1 +3876,3880,0.0,0.0,0.0,5,3,14 +3880,3884,1.0,0.16666666666666666,0.2857142857142857,6,1,9 +3884,3888,0.0,0.0,0.0,5,4,6 +3888,3892,0.0,0.0,0.0,4,3,8 +3892,3896,0.0,0.0,0.0,3,2,9 +3896,3900,1.0,0.2,0.33333333333333337,5,1,7 +3900,3904,0.0,0.0,0.0,6,0,3 +3904,3908,0.0,0.0,0.0,5,0,3 +3908,3912,0.0,0.0,0.0,4,0,3 +3912,3916,1.0,0.25,0.4,4,1,5 +3916,3920,0.5,0.3333333333333333,0.4,3,2,6 +3920,3924,0.0,0.0,0.0,2,0,5 +3924,3928,0.0,0.0,0.0,2,1,9 +3928,3932,0.0,0.0,0.0,2,2,8 +3932,3936,0.0,0.0,0.0,2,1,11 +3936,3940,0.0,0.0,0.0,1,0,1 +3968,3972,1.0,0.5,0.6666666666666666,2,1,1 +3972,3976,0.0,0.0,0.0,1,0,1 +3976,3980,0.0,0.0,0.0,1,0,2 +3980,3984,0.0,0.0,0.0,2,0,1 +3984,3988,0.0,0.0,0.0,2,0,8 +3988,3992,0.0,0.0,0.0,1,0,2 +3992,3996,0.0,0.0,0.0,2,1,3 +3996,4000,0.0,0.0,0.0,1,0,3 +4000,4004,0.0,0.0,0.0,3,0,3 +4004,4008,0.0,0.0,0.0,2,0,2 +4008,4012,0.0,0.0,0.0,2,0,2 +4012,4016,0.0,0.0,0.0,3,0,4 +4016,4020,0.0,0.0,0.0,2,0,1 +4020,4024,0.0,0.0,0.0,2,1,6 +4024,4028,0.0,0.0,0.0,2,0,4 +4028,4032,0.0,0.0,0.0,1,0,1 +4044,4048,0.0,0.0,0.0,1,0,2 +4048,4052,0.0,0.0,0.0,2,0,1 +4052,4056,0.0,0.0,0.0,2,0,4 +4056,4060,0.0,0.0,0.0,2,0,2 +4060,4064,1.0,0.5,0.6666666666666666,2,1,4 +4064,4068,0.0,0.0,0.0,2,0,3 +4068,4072,0.0,0.0,0.0,2,0,1 +4072,4076,1.0,0.5,0.6666666666666666,2,1,5 +4076,4080,0.0,0.0,0.0,1,0,3 +4100,4104,0.0,0.0,0.0,1,0,1 +4104,4108,0.0,0.0,0.0,1,0,3 +4108,4112,0.0,0.0,0.0,2,0,2 +4112,4116,0.0,0.0,0.0,2,0,5 +4116,4120,0.0,0.0,0.0,1,0,1 +4128,4132,0.0,0.0,0.0,1,0,3 +4132,4136,0.0,0.0,0.0,1,0,2 +4136,4140,0.0,0.0,0.0,2,0,4 +4140,4144,0.0,0.0,0.0,2,0,1 +4144,4148,0.0,0.0,0.0,2,0,8 +4148,4152,1.0,0.5,0.6666666666666666,2,1,6 +4152,4156,0.0,0.0,0.0,1,0,2 +4160,4164,0.0,0.0,0.0,1,0,2 +4164,4168,0.0,0.0,0.0,1,0,7 +4168,4172,1.0,0.3333333333333333,0.5,3,1,16 +4172,4176,0.0,0.0,0.0,3,0,2 +4176,4180,0.0,0.0,0.0,1,0,10 +4180,4184,1.0,1.0,1.0,1,1,4 +4184,4188,0.0,0.0,0.0,1,0,4 +4188,4192,0.0,0.0,0.0,2,0,3 +4192,4196,0.0,0.0,0.0,2,1,12 +4196,4200,1.0,0.5,0.6666666666666666,2,1,1 +4204,4208,0.0,0.0,0.0,1,0,7 +4208,4212,0.0,0.0,0.0,1,0,2 +4212,4216,0.5,0.5,0.5,2,2,4 +4216,4220,0.0,0.0,0.0,1,0,4 +4236,4240,0.0,0.0,0.0,1,0,3 +4240,4244,0.0,0.0,0.0,1,0,4 +4284,4288,0.0,0.0,0.0,1,0,6 +4288,4292,0.0,0.0,0.0,1,0,3 +4292,4296,0.0,0.0,0.0,1,1,10 +4296,4300,0.0,0.0,0.0,1,0,1 +4356,4360,1.0,1.0,1.0,1,1,6 +4360,4364,0.0,0.0,0.0,3,0,2 +4364,4368,1.0,0.4,0.5714285714285715,5,2,7 +4368,4372,1.0,0.5,0.6666666666666666,6,3,19 +4372,4376,0.5,0.16666666666666666,0.25,6,2,14 +4376,4380,0.3333333333333333,0.2,0.25,5,3,18 +4380,4384,0.0,0.0,0.0,3,0,1 +4384,4388,0.0,0.0,0.0,2,0,3 +4388,4392,1.0,0.5,0.6666666666666666,2,1,7 +4392,4396,0.0,0.0,0.0,2,0,2 +4396,4400,0.0,0.0,0.0,2,0,4 +4400,4404,0.0,0.0,0.0,2,2,5 +4404,4408,0.0,0.0,0.0,1,0,3 +4412,4416,0.0,0.0,0.0,1,0,1 +4416,4420,0.0,0.0,0.0,1,0,1 +4420,4424,0.0,0.0,0.0,1,0,7 +4424,4428,0.0,0.0,0.0,1,0,2 +4428,4432,0.0,0.0,0.0,1,0,4 +4432,4436,0.0,0.0,0.0,1,0,11 +4436,4440,0.0,0.0,0.0,1,0,11 +4440,4444,0.0,0.0,0.0,1,0,5 +4444,4448,0.0,0.0,0.0,1,0,3 +4448,4452,0.0,0.0,0.0,1,0,1 +4452,4456,0.0,0.0,0.0,1,0,1 +4456,4460,0.0,0.0,0.0,1,0,13 +4460,4464,0.0,0.0,0.0,3,0,5 +4464,4468,1.0,0.25,0.4,4,1,1 +4468,4472,0.5,0.25,0.3333333333333333,4,2,6 +4472,4476,1.0,0.25,0.4,4,1,6 +4476,4480,0.5,0.4,0.4444444444444445,5,4,6 +4480,4484,0.0,0.0,0.0,3,1,5 +4484,4488,0.0,0.0,0.0,3,0,6 +4488,4492,1.0,0.5,0.6666666666666666,2,1,15 +4492,4496,0.0,0.0,0.0,4,0,1 +4496,4500,0.25,0.25,0.25,4,4,11 +4500,4504,0.0,0.0,0.0,4,1,4 +4504,4508,0.4,0.4,0.4000000000000001,5,5,10 +4508,4512,0.0,0.0,0.0,6,0,3 +4512,4516,0.0,0.0,0.0,6,0,2 +4516,4520,0.0,0.0,0.0,4,0,4 +4520,4524,1.0,0.25,0.4,4,1,1 +4524,4528,0.0,0.0,0.0,2,0,1 +4528,4532,0.5,0.2,0.28571428571428575,5,2,6 +4532,4536,0.3333333333333333,0.14285714285714285,0.2,7,3,5 +4536,4540,0.0,0.0,0.0,9,0,2 diff --git a/experiment/hdbscan/main_kitti_processing_hdbscan_voxel.py b/experiment/hdbscan/main_kitti_processing_hdbscan_voxel.py new file mode 100644 index 0000000..e97dd09 --- /dev/null +++ b/experiment/hdbscan/main_kitti_processing_hdbscan_voxel.py @@ -0,0 +1,77 @@ +# Copyright (c) 2023, Sofia Vivdich and Anastasiia Kornilova +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import numpy as np +import open3d as o3d +import pickle + +from sklearn.cluster import HDBSCAN + + +def segment_pcds_by_hdbscan(start_index, end_index): + + file_name = "experiment_bin_0704_4_sem_voxel_offset0_T0l03/start{}_end{}.pickle".format( + start_index, end_index + ) + + with open(file_name, 'rb') as file: + data = pickle.load(file) + + pcd_hdbscan_voxel_down_points = np.asarray(data[2]["voxel_pcd_original_points"]) + pcd_hdbscan_voxel_down = o3d.geometry.PointCloud() + pcd_hdbscan_voxel_down.points = o3d.utility.Vector3dVector(pcd_hdbscan_voxel_down_points) + + clusterer = HDBSCAN() + clusters = clusterer.fit_predict(np.asarray(pcd_hdbscan_voxel_down.points)) + + return ( + {"hdbscan_clustered_voxel_pcd_original_points": np.asarray(pcd_hdbscan_voxel_down.points)}, + {"hdbscan_voxel_trace_original": data[3]["voxel_trace_original"]}, + {"hdbscan_clusters": clusters}, + {"inst_label_array_for_clustering": data[6]["inst_label_array_for_clustering"]}, + ) + + +def process_kitti_hdbscan(from_num, to_num): + + current_from_num = from_num + step = 4 + + while current_from_num < to_num: + start_index = current_from_num + end_index = start_index + step + + result_tuple = segment_pcds_by_hdbscan(start_index, end_index) + + file_name = ( + "experiment_bin_0704_4_sem_voxel_offset0_T0l03_hdbscan/start{}_end{}.pickle".format( + start_index, end_index + ) + ) + new_file = open(file_name, "w") + new_file.close() + + with open(file_name, "wb") as file: + pickle.dump(result_tuple, file) + + print("start_index={}, end_index={} done".format(start_index, end_index)) + current_from_num = end_index + + +def main(): + process_kitti_hdbscan(from_num=0, to_num=4540) + + +if __name__ == "__main__": + main() diff --git a/experiment/hdbscan/main_kitti_processing_metrics_hdbscan.py b/experiment/hdbscan/main_kitti_processing_metrics_hdbscan.py new file mode 100644 index 0000000..203f22d --- /dev/null +++ b/experiment/hdbscan/main_kitti_processing_metrics_hdbscan.py @@ -0,0 +1,172 @@ +# Copyright (c) 2023, Sofia Vivdich and Anastasiia Kornilova +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import copy +import csv +import numpy as np +import pickle + +from evops.metrics import precision +from evops.metrics import recall +from evops.metrics import fScore + + +def find_num_in_inst_label_array(src_points, inst_label_array_for_clustering): + for point in src_points: + if inst_label_array_for_clustering[point] > 0: + return inst_label_array_for_clustering[point] + return -1 + + +def build_pred_inst_array( + inst_label_array_for_clustering, clusters, trace, instance_threshold +): + pred_inst_array = np.zeros(len(inst_label_array_for_clustering), dtype=int) + free_id = 1 + for cluster in clusters: + voxel_not_in_gt_cluster_count = 0 + for voxel in cluster: + src_points = trace[voxel] + id = find_num_in_inst_label_array( + src_points, inst_label_array_for_clustering + ) + if id == -1: + voxel_not_in_gt_cluster_count += 1 + + cluster_in_gt_instance = ( + (len(cluster) - voxel_not_in_gt_cluster_count) / len(cluster) + ) * 100 + if cluster_in_gt_instance >= instance_threshold: + for voxel in cluster: + src_points = trace[voxel] + for src_point in src_points: + pred_inst_array[src_point] = free_id + free_id += 1 + return pred_inst_array + + +def convert_clusters_to_list_of_point_arrays(clusters_arr): + # labels 0 and -1 mean noise, they are equal for us + for ind, label in enumerate(clusters_arr): + if label == -1: + clusters_arr[ind] = 0 + + # initializing a list by the number of unique clusters + clusters_list = [] + for label in set(clusters_arr): + clusters_list.append([]) + + for ind, label in enumerate(clusters_arr): + clusters_list[label].append(ind) + + # converting internal lists to arrays + for i in range(len(clusters_list)): + clusters_list[i] = np.asarray(clusters_list[i]) + return clusters_list + + +def main(): + + from_num = 0 + to_num = 4540 + + instance_thresholds = [5, 20, 30, 50] + + for instance_threshold in instance_thresholds: + print("Start to process instance_threshold={}".format(instance_threshold)) + + current_from_num = from_num + + skipped = 0 + while current_from_num < to_num: + start_index = current_from_num + end_index = start_index + 4 + + file_name = "experiment_bin_0704_4_sem_voxel_offset0_T0l03_hdbscan/start{}_end{}.pickle".format( + start_index, end_index + ) + + with open(file_name, "rb") as file: + data = pickle.load(file) + + trace = data[1]["hdbscan_voxel_trace_original"] + clusters_array = data[2]["hdbscan_clusters"] + inst_label_array_for_clustering = data[3]["inst_label_array_for_clustering"] + + if ( + inst_label_array_for_clustering.sum() == 0 + ): # в облаке нет инстансов => пропускаем + skipped += 1 + print( + "start_index={}, end_index={} skip".format( + start_index, end_index + ) + ) + current_from_num = end_index + continue + + clusters_list_without_noise = convert_clusters_to_list_of_point_arrays(clusters_array)[1:] + + pred_inst_array = build_pred_inst_array( + copy.deepcopy(inst_label_array_for_clustering), + copy.deepcopy(clusters_list_without_noise), + copy.deepcopy(trace), + instance_threshold, + ) + + pred_labels = pred_inst_array + gt_labels = inst_label_array_for_clustering + tp_condition = "iou" + precision_res = precision(pred_labels, gt_labels, tp_condition) + recall_res = recall(pred_labels, gt_labels, tp_condition) + fScore_res = fScore(pred_labels, gt_labels, tp_condition) + + gt_labels_unique = set(gt_labels) + gt_labels_unique.discard(0) + + pred_labels_unique = set(pred_labels) + pred_labels_unique.discard(0) + + with open( + "experiment_1004_4_without0_sem_voxel_offset0_T0l03_hdbscan_{}.csv".format( + instance_threshold + ), + "a", + newline="", + ) as file: + writer = csv.writer(file) + + writer.writerow( + [ + str(start_index), + str(end_index), + str(precision_res), + str(recall_res), + str(fScore_res), + len(gt_labels_unique), + len(pred_labels_unique), + len(clusters_list_without_noise), + ] + ) + + print("start_index={}, end_index={} done".format(start_index, end_index)) + + current_from_num = end_index + + print(skipped) + print("Finish to process instance_threshold={}".format(instance_threshold)) + + +if __name__ == "__main__": + main() diff --git a/main_hdbscan_processing.ipynb b/main_hdbscan_processing.ipynb deleted file mode 100644 index c4b9c69..0000000 --- a/main_hdbscan_processing.ipynb +++ /dev/null @@ -1,342 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import copy\n", - "import numpy as np\n", - "import open3d as o3d\n", - "import random\n", - "\n", - "def generate_random_colors(N):\n", - " colors = [[0, 0, 0]]\n", - " for _ in range(N):\n", - " colors.append(\n", - " [random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)]\n", - " )\n", - "\n", - " colors = np.vstack(colors) / 255\n", - " return colors\n", - "\n", - "def color_pcd_by_labels1(pcd, labels):\n", - " colors = generate_random_colors(len(labels) + 1)\n", - " pcd_colored = copy.deepcopy(pcd)\n", - " pcd_colored.colors = o3d.utility.Vector3dVector(\n", - " np.zeros(np.asarray(pcd.points).shape)\n", - " )\n", - "\n", - " for i in range(len(pcd_colored.points)):\n", - " if labels[i] == 0 or labels[i] == -1:\n", - " continue\n", - " pcd_colored.colors[i] = colors[labels[i]]\n", - "\n", - " return pcd_colored" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import pickle\n", - "\n", - "start_num = 20\n", - "end_num = start_num + 4\n", - "\n", - "file_name = \"experiment_bin_0704_4_sem_offset0_T0l03/start{}_end{}.pickle\".format(start_num, end_num)\n", - "\n", - "with open(file_name, 'rb') as file:\n", - " data = pickle.load(file)\n", - "\n", - "print(data[0]) # значения гиперпараметров запуска" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from sklearn.cluster import HDBSCAN\n", - "\n", - "clusterer = HDBSCAN()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "import open3d as o3d\n", - "\n", - "X = np.asarray(data[1]) # точки обработанного облака ДО вокселизации\n", - "pcd_hdbscan = o3d.geometry.PointCloud()\n", - "pcd_hdbscan.points = o3d.utility.Vector3dVector(X)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import copy\n", - "\n", - "# проведение точно такой же вокселизации, как и в моем алгоритме\n", - "\n", - "pcd_hdbscan_copy = copy.deepcopy(pcd_hdbscan)\n", - "\n", - "min_bound = pcd_hdbscan_copy.get_min_bound()\n", - "max_bound = pcd_hdbscan_copy.get_max_bound()\n", - "\n", - "downpcd_trace = pcd_hdbscan_copy.voxel_down_sample_and_trace(\n", - " 0.25, min_bound, max_bound, True\n", - ")\n", - "\n", - "downpcd = downpcd_trace[0]\n", - "trace_hdbscan = downpcd_trace[2]\n", - "\n", - "print(\"voxel_down_pcd_size={}\".format(len(downpcd.points)))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# проверяем, что вокселизация привела облако в то состояние,\n", - "# при котором проводилась сегментация моим алгоритмом\n", - "\n", - "trace_arrays = []\n", - "for int_vector in trace_hdbscan:\n", - " trace_arrays.append(np.asarray(int_vector))\n", - "\n", - "for ind, el in enumerate(trace_arrays):\n", - " if (el != data[2][ind]).any():\n", - " print(\"ERROR\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# сегментация HDBSCAN\n", - "\n", - "clusters = clusterer.fit_predict(np.asarray(downpcd.points))\n", - "print(set(clusters))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import copy\n", - "\n", - "from src.utils.pcd_utils import visualize_pcd\n", - "\n", - "colored_pcd = color_pcd_by_labels1(copy.deepcopy(downpcd), clusters)\n", - "visualize_pcd(colored_pcd)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# приводим результаты кластеризации к листу, элементы которого - массивы точек одного кластера\n", - "\n", - "clusters_list = []\n", - "\n", - "print(\"before set(clusters)={}\".format(set(clusters)))\n", - "# метки 0 и -1 означают шум, они для нас равны\n", - "for ind, label in enumerate(clusters):\n", - " if label == -1:\n", - " clusters[ind] = 0\n", - "print(\"after set(clusters)={}\".format(set(clusters)))\n", - "\n", - "# инициализация листа\n", - "for label in set(clusters):\n", - " clusters_list.append([])\n", - "\n", - "for ind, label in enumerate(clusters):\n", - " clusters_list[label].append(ind)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import copy\n", - "\n", - "from src.utils.pcd_utils import color_pcd_by_clusters_and_voxels\n", - "from src.utils.pcd_utils import visualize_pcd\n", - "\n", - "colored_pcd = color_pcd_by_clusters_and_voxels(\n", - " copy.deepcopy(pcd_hdbscan_copy), copy.deepcopy(trace_hdbscan), clusters_list\n", - ")\n", - "visualize_pcd(colored_pcd)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# выборка из кластеризации только инстансов\n", - "\n", - "def find_num_in_inst_label_array(src_points, inst_label_array_for_clustering):\n", - " for point in src_points:\n", - " if inst_label_array_for_clustering[point] > 0:\n", - " return inst_label_array_for_clustering[point]\n", - " return -1\n", - "\n", - "\n", - "def build_pred_inst_array(\n", - " inst_label_array_for_clustering, clusters, trace, instance_threshold\n", - "):\n", - " pred_inst_array = np.zeros(len(inst_label_array_for_clustering), dtype=int)\n", - " free_id = 1\n", - " for cluster in clusters:\n", - " voxel_not_in_gt_cluster_count = 0\n", - " for voxel in cluster:\n", - " src_points = trace[voxel]\n", - " id = find_num_in_inst_label_array(\n", - " src_points, inst_label_array_for_clustering\n", - " )\n", - " if id == -1:\n", - " voxel_not_in_gt_cluster_count += 1\n", - "\n", - " cluster_in_gt_instance = (\n", - " (len(cluster) - voxel_not_in_gt_cluster_count) / len(cluster)\n", - " ) * 100\n", - " if cluster_in_gt_instance >= instance_threshold:\n", - " for voxel in cluster:\n", - " src_points = trace[voxel]\n", - " for src_point in src_points:\n", - " pred_inst_array[src_point] = free_id\n", - " free_id += 1\n", - " return pred_inst_array" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "instance_threshold = 30\n", - "inst_label_array_for_clustering = data[4] # из pickle\n", - "\n", - "pred_inst_array = build_pred_inst_array(\n", - " copy.deepcopy(inst_label_array_for_clustering),\n", - " clusters_list,\n", - " copy.deepcopy(trace_hdbscan),\n", - " instance_threshold,\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from evops.metrics import precision\n", - "from evops.metrics import recall\n", - "from evops.metrics import fScore\n", - "\n", - "pred_labels = pred_inst_array\n", - "gt_labels = inst_label_array_for_clustering\n", - "tp_condition = \"iou\"\n", - "print(\"precision={}\".format(precision(pred_labels, gt_labels, tp_condition)))\n", - "print(\"recall={}\".format(recall(pred_labels, gt_labels, tp_condition)))\n", - "print(\"fScore={}\".format(fScore(pred_labels, gt_labels, tp_condition)))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import copy\n", - "\n", - "from src.utils.pcd_utils import color_pcd_by_labels\n", - "from src.utils.pcd_utils import visualize_pcd\n", - "\n", - "colored_clusters_for_clustering = color_pcd_by_labels(\n", - " copy.deepcopy(pcd_hdbscan_copy), pred_labels\n", - ")\n", - "visualize_pcd(colored_clusters_for_clustering)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import copy\n", - "\n", - "from src.utils.pcd_utils import color_pcd_by_labels\n", - "from src.utils.pcd_utils import visualize_pcd\n", - "\n", - "colored_clusters_for_clustering = color_pcd_by_labels(\n", - " copy.deepcopy(pcd_hdbscan_copy), gt_labels\n", - ")\n", - "visualize_pcd(colored_clusters_for_clustering)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.6" - }, - "orig_nbformat": 4 - }, - "nbformat": 4, - "nbformat_minor": 2 -} From 061199293da6d123d4eaad556b2d256be5454c0b Mon Sep 17 00:00:00 2001 From: SVivdich02 Date: Wed, 15 May 2024 22:19:42 +0300 Subject: [PATCH 11/21] refactoring --- .../main_kitti_processing_hdbscan_voxel.py | 24 +++++++---- .../main_kitti_processing_metrics_hdbscan.py | 8 ++-- experiment/main_calc_metrics_by_csv.py | 43 ++++++------------- 3 files changed, 33 insertions(+), 42 deletions(-) diff --git a/experiment/hdbscan/main_kitti_processing_hdbscan_voxel.py b/experiment/hdbscan/main_kitti_processing_hdbscan_voxel.py index e97dd09..149b0f8 100644 --- a/experiment/hdbscan/main_kitti_processing_hdbscan_voxel.py +++ b/experiment/hdbscan/main_kitti_processing_hdbscan_voxel.py @@ -21,22 +21,30 @@ def segment_pcds_by_hdbscan(start_index, end_index): - file_name = "experiment_bin_0704_4_sem_voxel_offset0_T0l03/start{}_end{}.pickle".format( - start_index, end_index + file_name = ( + "experiment_bin_0704_4_sem_voxel_offset0_T0l03/start{}_end{}.pickle".format( + start_index, end_index + ) ) - with open(file_name, 'rb') as file: + with open(file_name, "rb") as file: data = pickle.load(file) pcd_hdbscan_voxel_down_points = np.asarray(data[2]["voxel_pcd_original_points"]) pcd_hdbscan_voxel_down = o3d.geometry.PointCloud() - pcd_hdbscan_voxel_down.points = o3d.utility.Vector3dVector(pcd_hdbscan_voxel_down_points) + pcd_hdbscan_voxel_down.points = o3d.utility.Vector3dVector( + pcd_hdbscan_voxel_down_points + ) clusterer = HDBSCAN() clusters = clusterer.fit_predict(np.asarray(pcd_hdbscan_voxel_down.points)) return ( - {"hdbscan_clustered_voxel_pcd_original_points": np.asarray(pcd_hdbscan_voxel_down.points)}, + { + "hdbscan_clustered_voxel_pcd_original_points": np.asarray( + pcd_hdbscan_voxel_down.points + ) + }, {"hdbscan_voxel_trace_original": data[3]["voxel_trace_original"]}, {"hdbscan_clusters": clusters}, {"inst_label_array_for_clustering": data[6]["inst_label_array_for_clustering"]}, @@ -54,10 +62,8 @@ def process_kitti_hdbscan(from_num, to_num): result_tuple = segment_pcds_by_hdbscan(start_index, end_index) - file_name = ( - "experiment_bin_0704_4_sem_voxel_offset0_T0l03_hdbscan/start{}_end{}.pickle".format( - start_index, end_index - ) + file_name = "experiment_bin_0704_4_sem_voxel_offset0_T0l03_hdbscan/start{}_end{}.pickle".format( + start_index, end_index ) new_file = open(file_name, "w") new_file.close() diff --git a/experiment/hdbscan/main_kitti_processing_metrics_hdbscan.py b/experiment/hdbscan/main_kitti_processing_metrics_hdbscan.py index 203f22d..40cbfde 100644 --- a/experiment/hdbscan/main_kitti_processing_metrics_hdbscan.py +++ b/experiment/hdbscan/main_kitti_processing_metrics_hdbscan.py @@ -109,14 +109,14 @@ def main(): ): # в облаке нет инстансов => пропускаем skipped += 1 print( - "start_index={}, end_index={} skip".format( - start_index, end_index - ) + "start_index={}, end_index={} skip".format(start_index, end_index) ) current_from_num = end_index continue - clusters_list_without_noise = convert_clusters_to_list_of_point_arrays(clusters_array)[1:] + clusters_list_without_noise = convert_clusters_to_list_of_point_arrays( + clusters_array + )[1:] pred_inst_array = build_pred_inst_array( copy.deepcopy(inst_label_array_for_clustering), diff --git a/experiment/main_calc_metrics_by_csv.py b/experiment/main_calc_metrics_by_csv.py index a283a65..2c7d855 100644 --- a/experiment/main_calc_metrics_by_csv.py +++ b/experiment/main_calc_metrics_by_csv.py @@ -15,6 +15,17 @@ import csv +def calculate_sum_ones_zeros(values): + sum, ones, zeros = 0, 0, 0 + for value in values: + sum += float(value) + if float(value) == 1.0: + ones += 1 + elif float(value) == 0.0: + zeros += 1 + return sum, ones, zeros + + def calculate_metrics(file_name): values_pres = [] values_recall = [] @@ -26,35 +37,9 @@ def calculate_metrics(file_name): values_recall.append(row["recall"]) values_fScore.append(row["fScore"]) - sum_pres = 0 - pres1 = 0 - pres0 = 0 - for value in values_pres: - sum_pres += float(value) - if float(value) == 1.0: - pres1 += 1 - if float(value) == 0.0: - pres0 += 1 - - sum_recall = 0 - recall1 = 0 - recall0 = 0 - for value in values_recall: - sum_recall += float(value) - if float(value) == 1.0: - recall1 += 1 - if float(value) == 0.0: - recall0 += 1 - - sum_fScore = 0 - fscore1 = 0 - fscore0 = 0 - for value in values_fScore: - sum_fScore += float(value) - if float(value) == 1.0: - fscore1 += 1 - if float(value) == 0.0: - fscore0 += 1 + sum_pres, pres1, pres0 = calculate_sum_ones_zeros(values_pres) + sum_recall, recall1, recall0 = calculate_sum_ones_zeros(values_recall) + sum_fScore, fscore1, fscore0 = calculate_sum_ones_zeros(values_fScore) print( "precision={}, 1={}, 0={}".format( From d0ce0a6b7796a6de111a692a6165fab558b26ca5 Mon Sep 17 00:00:00 2001 From: SVivdich02 Date: Thu, 30 May 2024 10:22:30 +0300 Subject: [PATCH 12/21] refactoring experiment files --- ...ut0_sem_voxel_offset0_T0l03_hdbscan_50.csv | 1036 ----------------- .../main_kitti_processing_hdbscan_voxel.py | 12 +- .../main_kitti_processing_metrics_hdbscan.py | 10 +- experiment/main_calc_metrics_by_csv.py | 2 +- experiment/main_kitti_processing.py | 4 +- experiment/main_kitti_processing_metrics.py | 10 +- 6 files changed, 15 insertions(+), 1059 deletions(-) delete mode 100644 experiment/hdbscan/experiment_1004_4_without0_sem_voxel_offset0_T0l03_hdbscan_50.csv diff --git a/experiment/hdbscan/experiment_1004_4_without0_sem_voxel_offset0_T0l03_hdbscan_50.csv b/experiment/hdbscan/experiment_1004_4_without0_sem_voxel_offset0_T0l03_hdbscan_50.csv deleted file mode 100644 index cbab34d..0000000 --- a/experiment/hdbscan/experiment_1004_4_without0_sem_voxel_offset0_T0l03_hdbscan_50.csv +++ /dev/null @@ -1,1036 +0,0 @@ -start_index,end_index,precision,recall,fScore,gt_inst_count,pred_inst_count,pred_total_inst_count -0,4,0.0,0.0,0.0,1,0,7 -4,8,0.0,0.0,0.0,1,1,6 -8,12,0.0,0.0,0.0,2,0,3 -12,16,0.5,0.5,0.5,2,2,5 -16,20,1.0,0.3333333333333333,0.5,3,1,3 -20,24,1.0,0.25,0.4,4,1,4 -24,28,1.0,0.3333333333333333,0.5,3,1,7 -28,32,0.5,0.4,0.4444444444444445,5,4,9 -32,36,0.0,0.0,0.0,3,1,3 -36,40,0.0,0.0,0.0,3,0,7 -40,44,0.0,0.0,0.0,1,0,1 -44,48,0.0,0.0,0.0,2,0,2 -48,52,0.5,0.25,0.3333333333333333,4,2,11 -52,56,0.3333333333333333,0.25,0.28571428571428575,4,3,7 -56,60,1.0,0.16666666666666666,0.2857142857142857,6,1,4 -60,64,0.0,0.0,0.0,5,0,2 -64,68,0.0,0.0,0.0,5,1,6 -68,72,0.0,0.0,0.0,6,0,2 -72,76,0.5,0.2,0.28571428571428575,5,2,8 -76,80,0.0,0.0,0.0,3,0,1 -80,84,1.0,0.25,0.4,4,1,6 -84,88,1.0,0.3333333333333333,0.5,3,1,2 -88,92,0.0,0.0,0.0,1,0,1 -92,96,0.0,0.0,0.0,3,1,1 -96,100,0.0,0.0,0.0,5,2,9 -100,104,1.0,0.5,0.6666666666666666,6,3,12 -104,108,0.0,0.0,0.0,5,0,15 -108,112,0.04,0.14285714285714285,0.0625,7,25,124 -112,116,0.0,0.0,0.0,4,0,7 -116,120,0.0,0.0,0.0,3,0,7 -120,124,1.0,0.25,0.4,4,1,17 -124,128,1.0,0.2,0.33333333333333337,5,1,16 -128,132,0.0,0.0,0.0,5,0,12 -132,136,0.0,0.0,0.0,3,0,9 -136,140,0.0,0.0,0.0,2,0,10 -140,144,0.0,0.0,0.0,2,0,7 -144,148,0.0,0.0,0.0,1,1,2 -148,152,0.0,0.0,0.0,1,0,5 -152,156,0.0,0.0,0.0,1,0,1 -156,160,0.0,0.0,0.0,3,0,6 -160,164,0.0,0.0,0.0,3,0,3 -164,168,0.0,0.0,0.0,3,0,9 -168,172,0.0,0.0,0.0,3,1,7 -172,176,0.0,0.0,0.0,2,1,13 -176,180,1.0,0.5,0.6666666666666666,4,2,8 -180,184,0.0,0.0,0.0,2,1,3 -184,188,0.0,0.0,0.0,2,0,3 -188,192,0.0,0.0,0.0,2,0,4 -192,196,1.0,0.25,0.4,4,1,10 -196,200,0.0,0.0,0.0,4,0,28 -200,204,0.0,0.0,0.0,3,0,21 -204,208,0.0,0.0,0.0,4,2,31 -208,212,0.0,0.0,0.0,3,0,3 -212,216,0.0,0.0,0.0,3,0,6 -216,220,0.0,0.0,0.0,2,0,1 -220,224,0.0,0.0,0.0,3,0,1 -224,228,0.0,0.0,0.0,3,0,4 -228,232,0.0,0.0,0.0,3,0,4 -232,236,0.0,0.0,0.0,3,0,5 -236,240,0.0,0.0,0.0,3,0,4 -240,244,0.0,0.0,0.0,3,0,1 -244,248,0.0,0.0,0.0,2,0,2 -248,252,0.0,0.0,0.0,1,0,6 -252,256,0.0,0.0,0.0,2,1,4 -256,260,0.0,0.0,0.0,1,0,3 -260,264,0.0,0.0,0.0,2,0,2 -264,268,0.0,0.0,0.0,2,0,1 -268,272,0.0,0.0,0.0,4,0,3 -272,276,1.0,0.25,0.4,4,1,1 -276,280,0.0,0.0,0.0,3,0,4 -280,284,1.0,0.3333333333333333,0.5,3,1,3 -284,288,0.0,0.0,0.0,2,0,6 -288,292,0.0,0.0,0.0,3,1,6 -292,296,0.0,0.0,0.0,2,0,1 -296,300,0.0,0.0,0.0,3,1,4 -300,304,0.3333333333333333,0.25,0.28571428571428575,4,3,10 -304,308,0.6666666666666666,0.5,0.5714285714285715,4,3,5 -308,312,0.0,0.0,0.0,4,0,5 -312,316,0.0,0.0,0.0,4,1,6 -316,320,0.0,0.0,0.0,2,0,5 -320,324,0.0,0.0,0.0,1,0,3 -324,328,1.0,0.5,0.6666666666666666,2,1,3 -328,332,0.0,0.0,0.0,3,0,1 -332,336,0.08333333333333333,0.5,0.14285714285714285,2,12,131 -336,340,0.0,0.0,0.0,3,0,2 -340,344,0.0,0.0,0.0,3,0,2 -344,348,0.0,0.0,0.0,3,0,3 -348,352,0.5,0.25,0.3333333333333333,4,2,4 -352,356,0.0,0.0,0.0,2,1,1 -356,360,0.0,0.0,0.0,2,1,1 -360,364,0.0,0.0,0.0,2,1,5 -364,368,0.0,0.0,0.0,2,0,5 -368,372,0.0,0.0,0.0,2,0,4 -372,376,0.0,0.0,0.0,1,0,2 -376,380,0.0,0.0,0.0,2,0,5 -380,384,0.0,0.0,0.0,2,0,6 -384,388,1.0,0.5,0.6666666666666666,2,1,5 -388,392,0.0,0.0,0.0,1,0,2 -392,396,0.0,0.0,0.0,1,0,3 -396,400,1.0,0.3333333333333333,0.5,3,1,5 -400,404,1.0,1.0,1.0,1,1,1 -412,416,0.0,0.0,0.0,2,0,1 -416,420,0.0,0.0,0.0,2,0,4 -420,424,0.0,0.0,0.0,4,0,2 -424,428,0.0,0.0,0.0,3,0,2 -428,432,0.0,0.0,0.0,3,0,5 -432,436,0.0,0.0,0.0,3,0,2 -436,440,0.0,0.0,0.0,3,0,5 -440,444,0.0,0.0,0.0,3,1,9 -444,448,0.0,0.0,0.0,2,0,2 -448,452,0.0,0.0,0.0,1,0,2 -452,456,0.0,0.0,0.0,2,0,2 -456,460,0.0,0.0,0.0,1,0,1 -460,464,0.0,0.0,0.0,2,0,3 -464,468,0.0,0.0,0.0,3,0,5 -468,472,0.0,0.0,0.0,4,1,3 -472,476,0.0,0.0,0.0,4,2,7 -476,480,0.0,0.0,0.0,4,0,1 -480,484,0.0,0.0,0.0,4,0,6 -484,488,0.0,0.0,0.0,4,1,1 -488,492,0.0,0.0,0.0,2,0,2 -492,496,0.0,0.0,0.0,1,0,7 -496,500,0.0,0.0,0.0,2,0,4 -500,504,0.0,0.0,0.0,2,0,6 -504,508,1.0,0.3333333333333333,0.5,3,1,2 -508,512,0.0,0.0,0.0,2,0,3 -512,516,0.0,0.0,0.0,2,0,6 -516,520,0.0,0.0,0.0,2,0,2 -520,524,1.0,0.1111111111111111,0.19999999999999998,9,1,3 -524,528,0.5,0.1111111111111111,0.1818181818181818,9,2,3 -528,532,0.4,0.3333333333333333,0.3636363636363636,6,5,6 -532,536,0.6666666666666666,0.2857142857142857,0.4,7,3,7 -536,540,0.75,0.42857142857142855,0.5454545454545454,7,4,6 -540,544,0.46153846153846156,0.8571428571428571,0.6,7,13,41 -544,548,0.6666666666666666,0.3333333333333333,0.4444444444444444,6,3,6 -548,552,0.7142857142857143,0.8333333333333334,0.7692307692307692,6,7,48 -552,556,0.8333333333333334,0.8333333333333334,0.8333333333333334,6,6,52 -556,560,0.5,0.3333333333333333,0.4,6,4,10 -560,564,0.75,0.5,0.6,6,4,9 -564,568,0.6,0.5,0.5454545454545454,6,5,10 -568,572,0.5,0.16666666666666666,0.25,6,2,4 -572,576,0.0,0.0,0.0,7,2,10 -576,580,0.6666666666666666,0.25,0.36363636363636365,8,3,8 -580,584,0.375,0.8571428571428571,0.5217391304347825,7,16,110 -584,588,0.0,0.0,0.0,8,0,2 -588,592,0.0,0.0,0.0,8,0,7 -592,596,1.0,0.25,0.4,8,2,7 -596,600,1.0,0.42857142857142855,0.6,7,3,7 -600,604,0.5,0.2,0.28571428571428575,5,2,6 -604,608,0.0,0.0,0.0,4,0,3 -608,612,0.0,0.0,0.0,3,0,8 -612,616,1.0,0.25,0.4,4,1,2 -616,620,0.3333333333333333,0.3333333333333333,0.3333333333333333,3,3,6 -620,624,0.5,0.2,0.28571428571428575,5,2,4 -624,628,0.5,0.16666666666666666,0.25,6,2,4 -628,632,0.3333333333333333,0.2857142857142857,0.30769230769230765,7,6,8 -632,636,0.6666666666666666,0.3333333333333333,0.4444444444444444,6,3,9 -636,640,1.0,0.5714285714285714,0.7272727272727273,7,4,7 -640,644,0.5,0.2,0.28571428571428575,5,2,3 -644,648,0.0,0.0,0.0,6,0,2 -648,652,0.0,0.0,0.0,8,0,2 -652,656,0.0,0.0,0.0,7,0,4 -656,660,1.0,0.14285714285714285,0.25,7,1,1 -660,664,0.0,0.0,0.0,4,1,1 -664,668,0.0,0.0,0.0,7,0,4 -668,672,0.375,0.42857142857142855,0.39999999999999997,7,8,14 -672,676,0.6,0.42857142857142855,0.5,7,5,7 -676,680,0.75,0.42857142857142855,0.5454545454545454,7,4,9 -680,684,0.0,0.0,0.0,6,0,2 -684,688,0.5,0.25,0.3333333333333333,4,2,9 -688,692,0.0,0.0,0.0,4,0,1 -692,696,0.6666666666666666,0.5,0.5714285714285715,4,3,7 -696,700,0.0,0.0,0.0,5,0,1 -700,704,0.0,0.0,0.0,5,0,1 -704,708,0.0,0.0,0.0,4,0,1 -708,712,1.0,0.25,0.4,4,1,7 -712,716,0.0,0.0,0.0,1,0,2 -716,720,1.0,1.0,1.0,1,1,1 -724,728,0.0,0.0,0.0,1,0,1 -728,732,0.0,0.0,0.0,1,0,4 -732,736,0.0,0.0,0.0,1,0,4 -736,740,0.0,0.0,0.0,3,0,5 -740,744,0.0,0.0,0.0,1,0,1 -744,748,0.0,0.0,0.0,2,0,6 -748,752,0.0,0.0,0.0,2,0,10 -752,756,0.0,0.0,0.0,3,0,1 -756,760,0.0,0.0,0.0,2,1,4 -760,764,0.0,0.0,0.0,2,0,1 -764,768,0.0,0.0,0.0,2,0,8 -768,772,1.0,0.5,0.6666666666666666,2,1,6 -772,776,0.0,0.0,0.0,2,1,9 -776,780,0.0,0.0,0.0,3,0,2 -780,784,0.0,0.0,0.0,3,0,2 -784,788,0.0,0.0,0.0,4,0,1 -788,792,0.0,0.0,0.0,4,0,9 -792,796,1.0,0.25,0.4,4,1,8 -796,800,0.0,0.0,0.0,2,0,1 -800,804,0.0,0.0,0.0,2,1,2 -804,808,0.0,0.0,0.0,1,0,2 -808,812,1.0,0.5,0.6666666666666666,2,1,3 -812,816,0.0,0.0,0.0,1,0,2 -816,820,0.0,0.0,0.0,1,0,7 -820,824,0.0,0.0,0.0,1,0,1 -832,836,0.0,0.0,0.0,2,0,1 -836,840,0.0,0.0,0.0,2,0,6 -840,844,0.0,0.0,0.0,3,0,9 -844,848,0.0,0.0,0.0,1,0,2 -848,852,0.0,0.0,0.0,3,0,2 -852,856,0.0,0.0,0.0,3,0,3 -856,860,0.0,0.0,0.0,3,0,3 -860,864,0.0,0.0,0.0,2,0,2 -864,868,0.0,0.0,0.0,2,0,4 -868,872,0.0,0.0,0.0,1,0,3 -880,884,0.0,0.0,0.0,1,0,1 -884,888,0.0,0.0,0.0,1,0,5 -888,892,0.0,0.0,0.0,2,0,4 -892,896,0.0,0.0,0.0,2,0,7 -896,900,0.3333333333333333,0.25,0.28571428571428575,4,3,22 -900,904,0.0,0.0,0.0,3,0,7 -904,908,0.0,0.0,0.0,3,0,1 -908,912,0.0,0.0,0.0,2,0,5 -912,916,0.0,0.0,0.0,2,0,7 -916,920,0.0,0.0,0.0,2,0,8 -920,924,0.0,0.0,0.0,1,0,3 -924,928,0.0,0.0,0.0,2,0,1 -928,932,0.0,0.0,0.0,2,0,3 -932,936,0.0,0.0,0.0,3,0,3 -936,940,0.0,0.0,0.0,3,0,4 -940,944,0.0,0.0,0.0,2,0,2 -944,948,0.0,0.0,0.0,2,0,4 -952,956,0.0,0.0,0.0,1,0,6 -956,960,0.0,0.0,0.0,1,0,1 -960,964,1.0,1.0,1.0,1,1,2 -964,968,1.0,1.0,1.0,1,1,2 -968,972,0.0,0.0,0.0,1,0,6 -972,976,0.0,0.0,0.0,2,0,3 -976,980,0.0,0.0,0.0,2,0,7 -980,984,0.0,0.0,0.0,2,0,6 -984,988,0.0,0.0,0.0,2,0,1 -988,992,0.0,0.0,0.0,3,0,7 -992,996,0.0,0.0,0.0,3,1,6 -996,1000,0.0,0.0,0.0,1,0,3 -1000,1004,0.0,0.0,0.0,1,0,3 -1004,1008,0.0,0.0,0.0,1,0,5 -1008,1012,0.0,0.0,0.0,2,0,1 -1012,1016,0.0,0.0,0.0,2,0,1 -1016,1020,0.0,0.0,0.0,4,1,3 -1020,1024,0.0,0.0,0.0,4,0,4 -1024,1028,0.0,0.0,0.0,4,0,3 -1028,1032,0.0,0.0,0.0,4,0,2 -1032,1036,0.0,0.0,0.0,4,1,3 -1036,1040,0.0,0.0,0.0,4,1,4 -1040,1044,0.0,0.0,0.0,4,0,10 -1044,1048,0.0,0.0,0.0,5,0,2 -1048,1052,0.0,0.0,0.0,5,1,2 -1052,1056,0.0,0.0,0.0,3,1,5 -1056,1060,0.0,0.0,0.0,4,4,10 -1060,1064,0.0,0.0,0.0,5,1,4 -1064,1068,0.0,0.0,0.0,5,1,8 -1068,1072,0.0,0.0,0.0,3,0,5 -1072,1076,0.0,0.0,0.0,3,0,10 -1076,1080,0.0,0.0,0.0,2,0,4 -1080,1084,0.0,0.0,0.0,3,0,15 -1084,1088,0.0,0.0,0.0,2,0,12 -1088,1092,0.0,0.0,0.0,1,0,8 -1092,1096,0.0,0.0,0.0,1,0,11 -1096,1100,0.0,0.0,0.0,2,0,3 -1100,1104,0.0,0.0,0.0,2,0,8 -1104,1108,0.0,0.0,0.0,3,0,1 -1108,1112,0.16666666666666666,0.6,0.2608695652173913,5,18,101 -1112,1116,0.0,0.0,0.0,5,0,1 -1116,1120,1.0,0.2,0.33333333333333337,5,1,4 -1120,1124,0.0,0.0,0.0,4,0,1 -1124,1128,0.0,0.0,0.0,3,1,3 -1128,1132,0.0,0.0,0.0,3,0,2 -1132,1136,0.0,0.0,0.0,4,0,1 -1136,1140,0.0,0.0,0.0,1,0,4 -1140,1144,0.0,0.0,0.0,1,0,5 -1144,1148,0.5,1.0,0.6666666666666666,1,2,3 -1180,1184,0.0,0.0,0.0,1,0,7 -1184,1188,0.0,0.0,0.0,1,0,18 -1188,1192,0.0,0.0,0.0,2,0,6 -1192,1196,1.0,0.5,0.6666666666666666,2,1,19 -1196,1200,0.0,0.0,0.0,2,0,4 -1200,1204,0.0,0.0,0.0,1,0,12 -1204,1208,0.0,0.0,0.0,1,0,4 -1208,1212,0.0,0.0,0.0,1,0,2 -1212,1216,0.0,0.0,0.0,3,0,2 -1216,1220,0.0,0.0,0.0,3,1,7 -1220,1224,0.0,0.0,0.0,4,0,3 -1224,1228,0.0,0.0,0.0,4,0,7 -1228,1232,0.0,0.0,0.0,3,0,2 -1232,1236,0.0,0.0,0.0,4,0,6 -1236,1240,1.0,0.3333333333333333,0.5,3,1,4 -1240,1244,0.0,0.0,0.0,2,1,7 -1244,1248,1.0,0.25,0.4,4,1,9 -1248,1252,0.0,0.0,0.0,4,0,6 -1252,1256,0.0,0.0,0.0,3,0,10 -1256,1260,0.0,0.0,0.0,3,0,4 -1260,1264,0.0,0.0,0.0,4,0,9 -1264,1268,0.15384615384615385,0.5,0.23529411764705882,4,13,113 -1268,1272,1.0,0.2,0.33333333333333337,5,1,3 -1272,1276,0.0,0.0,0.0,5,0,5 -1276,1280,0.0,0.0,0.0,5,0,6 -1280,1284,0.5,0.4,0.4444444444444445,5,4,12 -1284,1288,1.0,0.5,0.6666666666666666,4,2,20 -1288,1292,0.0,0.0,0.0,4,0,1 -1292,1296,0.0,0.0,0.0,6,1,11 -1296,1300,0.0,0.0,0.0,4,15,104 -1300,1304,0.0,0.0,0.0,4,0,4 -1304,1308,0.0,0.0,0.0,4,0,6 -1308,1312,0.0,0.0,0.0,5,0,7 -1312,1316,0.0,0.0,0.0,5,0,6 -1316,1320,0.0,0.0,0.0,3,1,8 -1320,1324,0.0,0.0,0.0,4,1,2 -1324,1328,0.0,0.0,0.0,3,0,1 -1328,1332,0.0,0.0,0.0,3,0,7 -1332,1336,0.0,0.0,0.0,3,0,11 -1336,1340,0.0,0.0,0.0,3,0,7 -1340,1344,0.0,0.0,0.0,4,0,9 -1344,1348,0.0,0.0,0.0,3,0,6 -1348,1352,0.0,0.0,0.0,2,0,1 -1352,1356,0.0,0.0,0.0,2,0,1 -1356,1360,0.0,0.0,0.0,4,3,9 -1360,1364,0.2,0.2,0.20000000000000004,5,5,13 -1364,1368,0.0,0.0,0.0,3,0,4 -1368,1372,0.8,0.6666666666666666,0.7272727272727272,6,5,90 -1372,1376,0.0,0.0,0.0,4,1,1 -1376,1380,0.0,0.0,0.0,2,1,6 -1380,1384,0.0,0.0,0.0,3,0,2 -1384,1388,0.0,0.0,0.0,3,0,3 -1388,1392,0.0,0.0,0.0,2,0,6 -1392,1396,0.0,0.0,0.0,3,0,2 -1396,1400,0.0,0.0,0.0,3,0,1 -1400,1404,0.0,0.0,0.0,3,0,1 -1404,1408,0.0,0.0,0.0,2,0,3 -1408,1412,0.0,0.0,0.0,3,0,3 -1412,1416,0.0,0.0,0.0,5,0,1 -1416,1420,0.0,0.0,0.0,4,0,2 -1420,1424,1.0,0.3333333333333333,0.5,3,1,6 -1424,1428,0.0,0.0,0.0,3,0,3 -1428,1432,0.0,0.0,0.0,2,1,6 -1432,1436,0.0,0.0,0.0,4,1,7 -1436,1440,0.0,0.0,0.0,4,1,8 -1440,1444,0.0,0.0,0.0,6,2,8 -1444,1448,0.5,0.2,0.28571428571428575,5,2,10 -1448,1452,0.3333333333333333,0.16666666666666666,0.2222222222222222,6,3,7 -1452,1456,0.5,0.1111111111111111,0.1818181818181818,9,2,4 -1456,1460,0.0,0.0,0.0,12,0,5 -1460,1464,1.0,0.09090909090909091,0.16666666666666669,11,1,4 -1464,1468,0.3333333333333333,0.1111111111111111,0.16666666666666666,9,3,7 -1468,1472,0.5,0.1111111111111111,0.1818181818181818,9,2,6 -1472,1476,1.0,0.1,0.18181818181818182,10,1,5 -1476,1480,0.0,0.0,0.0,11,0,4 -1480,1484,0.0,0.0,0.0,9,0,3 -1484,1488,1.0,0.25,0.4,8,2,7 -1488,1492,1.0,0.2,0.33333333333333337,10,2,5 -1492,1496,0.0,0.0,0.0,8,0,2 -1496,1500,0.0,0.0,0.0,7,0,2 -1500,1504,0.0,0.0,0.0,7,0,2 -1504,1508,1.0,0.16666666666666666,0.2857142857142857,6,1,2 -1508,1512,0.0,0.0,0.0,3,0,2 -1512,1516,0.0,0.0,0.0,3,0,3 -1516,1520,0.0,0.0,0.0,4,0,4 -1520,1524,0.3333333333333333,0.16666666666666666,0.2222222222222222,6,3,7 -1524,1528,0.0,0.0,0.0,8,0,1 -1528,1532,0.0,0.0,0.0,7,0,3 -1532,1536,0.0,0.0,0.0,4,0,4 -1536,1540,1.0,0.2,0.33333333333333337,5,1,3 -1540,1544,0.0,0.0,0.0,2,0,1 -1544,1548,0.0,0.0,0.0,3,0,1 -1548,1552,0.0,0.0,0.0,5,0,1 -1552,1556,0.0,0.0,0.0,4,0,2 -1556,1560,1.0,0.2,0.33333333333333337,5,1,16 -1560,1564,0.0,0.0,0.0,4,0,13 -1564,1568,0.0,0.0,0.0,3,0,8 -1568,1572,0.0,0.0,0.0,4,0,13 -1572,1576,0.25,0.5,0.3333333333333333,4,8,86 -1576,1580,1.0,0.25,0.4,4,1,8 -1580,1584,0.0,0.0,0.0,2,0,1 -1584,1588,0.0,0.0,0.0,2,0,8 -1588,1592,0.0,0.0,0.0,1,0,1 -1592,1596,0.0,0.0,0.0,1,0,5 -1596,1600,0.0,0.0,0.0,1,0,1 -1600,1604,0.0,0.0,0.0,3,0,5 -1604,1608,0.0,0.0,0.0,3,0,1 -1608,1612,0.0,0.0,0.0,3,0,3 -1612,1616,0.0,0.0,0.0,3,1,7 -1616,1620,1.0,0.3333333333333333,0.5,3,1,9 -1620,1624,0.0,0.0,0.0,3,0,1 -1624,1628,0.0,0.0,0.0,2,0,2 -1628,1632,0.0,0.0,0.0,3,0,17 -1632,1636,1.0,0.5,0.6666666666666666,4,2,18 -1636,1640,0.6666666666666666,0.4,0.5,5,3,26 -1640,1644,0.0,0.0,0.0,5,0,12 -1644,1648,0.0,0.0,0.0,6,0,6 -1648,1652,1.0,0.16666666666666666,0.2857142857142857,6,1,4 -1652,1656,0.0,0.0,0.0,3,0,1 -1656,1660,0.0,0.0,0.0,3,0,7 -1660,1664,1.0,1.0,1.0,1,1,3 -1664,1668,0.0,0.0,0.0,1,0,1 -1668,1672,0.0,0.0,0.0,1,0,1 -1672,1676,0.0,0.0,0.0,1,0,5 -1676,1680,0.0,0.0,0.0,2,0,3 -1680,1684,0.0,0.0,0.0,2,0,7 -1684,1688,0.0,0.0,0.0,1,0,12 -1688,1692,0.0,0.0,0.0,1,0,12 -1692,1696,1.0,1.0,1.0,1,1,1 -1696,1700,0.0,0.0,0.0,1,0,3 -1700,1704,0.0,0.0,0.0,1,0,1 -1704,1708,0.0,0.0,0.0,1,1,7 -1708,1712,0.0,0.0,0.0,2,0,8 -1712,1716,0.0,0.0,0.0,1,0,12 -1716,1720,0.0,0.0,0.0,2,0,4 -1720,1724,0.0,0.0,0.0,2,0,13 -1724,1728,0.0,0.0,0.0,2,0,13 -1728,1732,1.0,0.25,0.4,4,1,11 -1732,1736,0.0,0.0,0.0,3,0,13 -1736,1740,0.0,0.0,0.0,2,1,4 -1740,1744,0.0,0.0,0.0,2,1,4 -1744,1748,0.0,0.0,0.0,1,0,1 -1748,1752,0.0,0.0,0.0,1,0,10 -1752,1756,0.0,0.0,0.0,2,0,17 -1756,1760,0.0,0.0,0.0,2,1,6 -1760,1764,0.0,0.0,0.0,1,0,6 -1764,1768,0.0,0.0,0.0,1,0,4 -1768,1772,0.0,0.0,0.0,2,2,29 -1772,1776,0.0,0.0,0.0,1,0,4 -1776,1780,0.0,0.0,0.0,1,0,5 -1780,1784,0.0,0.0,0.0,3,1,5 -1784,1788,0.0,0.0,0.0,2,0,6 -1788,1792,0.0,0.0,0.0,2,0,6 -1792,1796,0.0,0.0,0.0,2,1,10 -1796,1800,0.0,0.0,0.0,2,0,1 -1800,1804,1.0,0.25,0.4,4,1,7 -1804,1808,0.0,0.0,0.0,3,1,7 -1808,1812,0.0,0.0,0.0,3,2,4 -1812,1816,0.0,0.0,0.0,2,0,3 -1816,1820,0.0,0.0,0.0,2,0,2 -1820,1824,0.0,0.0,0.0,2,1,9 -1824,1828,0.3333333333333333,0.3333333333333333,0.3333333333333333,3,3,13 -1828,1832,0.0,0.0,0.0,2,0,12 -1832,1836,0.0,0.0,0.0,2,0,12 -1836,1840,0.0,0.0,0.0,2,0,8 -1840,1844,0.0,0.0,0.0,1,0,3 -1844,1848,0.0,0.0,0.0,2,0,2 -1848,1852,0.0,0.0,0.0,2,0,11 -1852,1856,0.0,0.0,0.0,2,1,4 -1856,1860,0.0,0.0,0.0,3,0,4 -1860,1864,0.0,0.0,0.0,2,4,6 -1864,1868,1.0,0.3333333333333333,0.5,3,1,1 -1868,1872,0.0,0.0,0.0,3,2,10 -1872,1876,0.0,0.0,0.0,3,0,4 -1876,1880,0.0,0.0,0.0,2,0,1 -1892,1896,0.0,0.0,0.0,1,0,11 -1896,1900,0.0,0.0,0.0,1,0,4 -1900,1904,0.0,0.0,0.0,1,0,3 -1904,1908,0.0,0.0,0.0,2,0,1 -1908,1912,0.0,0.0,0.0,2,1,1 -1912,1916,0.0,0.0,0.0,2,0,3 -1916,1920,0.0,0.0,0.0,1,0,3 -1920,1924,0.5,0.3333333333333333,0.4,3,2,13 -1924,1928,0.0,0.0,0.0,3,0,1 -1928,1932,0.0,0.0,0.0,2,0,5 -1932,1936,0.0,0.0,0.0,2,0,11 -1936,1940,0.5,0.3333333333333333,0.4,3,2,18 -1940,1944,0.0,0.0,0.0,2,0,20 -1944,1948,0.0,0.0,0.0,2,0,17 -1948,1952,0.0,0.0,0.0,1,0,18 -1952,1956,1.0,0.3333333333333333,0.5,3,1,10 -1956,1960,0.0,0.0,0.0,2,0,8 -1960,1964,1.0,0.3333333333333333,0.5,3,1,9 -1964,1968,0.6666666666666666,0.6666666666666666,0.6666666666666666,3,3,12 -1968,1972,0.0,0.0,0.0,1,0,3 -1972,1976,0.0,0.0,0.0,2,0,1 -1976,1980,0.0,0.0,0.0,2,0,2 -1980,1984,0.0,0.0,0.0,3,0,2 -1984,1988,1.0,0.3333333333333333,0.5,3,1,8 -1988,1992,0.0,0.0,0.0,2,0,7 -1992,1996,0.0,0.0,0.0,2,0,14 -1996,2000,1.0,0.5,0.6666666666666666,2,1,9 -2000,2004,0.0,0.0,0.0,2,0,16 -2004,2008,0.0,0.0,0.0,2,0,2 -2008,2012,0.0,0.0,0.0,3,0,10 -2012,2016,0.0,0.0,0.0,3,0,4 -2016,2020,0.0,0.0,0.0,2,0,6 -2020,2024,0.0,0.0,0.0,2,0,1 -2024,2028,0.0,0.0,0.0,2,1,10 -2028,2032,0.0,0.0,0.0,2,0,12 -2032,2036,0.0,0.0,0.0,3,0,8 -2036,2040,0.0,0.0,0.0,3,0,9 -2040,2044,0.0,0.0,0.0,3,0,3 -2044,2048,0.0,0.0,0.0,2,0,4 -2048,2052,1.0,0.5,0.6666666666666666,2,1,5 -2052,2056,0.0,0.0,0.0,1,2,17 -2076,2080,1.0,1.0,1.0,1,1,13 -2100,2104,0.0,0.0,0.0,1,0,3 -2104,2108,0.0,0.0,0.0,1,0,5 -2108,2112,0.0,0.0,0.0,1,0,19 -2112,2116,1.0,0.5,0.6666666666666666,2,1,23 -2116,2120,0.0,0.0,0.0,4,0,15 -2120,2124,0.0,0.0,0.0,3,0,11 -2124,2128,0.0,0.0,0.0,3,0,10 -2128,2132,0.0,0.0,0.0,3,0,2 -2132,2136,0.0,0.0,0.0,1,0,1 -2136,2140,0.0,0.0,0.0,1,0,4 -2140,2144,0.0,0.0,0.0,2,1,7 -2144,2148,0.0,0.0,0.0,1,0,4 -2148,2152,0.0,0.0,0.0,1,0,4 -2152,2156,0.0,0.0,0.0,1,0,3 -2156,2160,0.0,0.0,0.0,1,0,1 -2172,2176,0.0,0.0,0.0,1,0,3 -2176,2180,0.0,0.0,0.0,1,0,6 -2180,2184,0.0,0.0,0.0,1,1,7 -2184,2188,0.0,0.0,0.0,1,0,4 -2188,2192,0.0,0.0,0.0,1,0,10 -2192,2196,0.0,0.0,0.0,2,0,4 -2196,2200,0.0,0.0,0.0,3,0,1 -2200,2204,0.0,0.0,0.0,3,1,3 -2204,2208,0.0,0.0,0.0,4,0,4 -2208,2212,0.0,0.0,0.0,3,0,9 -2212,2216,0.0,0.0,0.0,2,0,5 -2216,2220,0.0,0.0,0.0,1,0,4 -2220,2224,0.5,0.6666666666666666,0.5714285714285715,3,4,9 -2224,2228,0.5,0.3333333333333333,0.4,3,2,10 -2228,2232,0.0,0.0,0.0,4,0,2 -2232,2236,0.0,0.0,0.0,1,0,2 -2236,2240,0.0,0.0,0.0,1,0,1 -2240,2244,0.0,0.0,0.0,1,0,4 -2244,2248,0.0,0.0,0.0,1,0,2 -2248,2252,0.0,0.0,0.0,1,1,6 -2252,2256,0.0,0.0,0.0,1,1,5 -2256,2260,0.0,0.0,0.0,1,1,3 -2260,2264,0.0,0.0,0.0,1,1,8 -2264,2268,0.0,0.0,0.0,1,2,7 -2268,2272,0.0,0.0,0.0,2,0,3 -2272,2276,0.0,0.0,0.0,2,0,6 -2276,2280,0.0,0.0,0.0,2,0,5 -2280,2284,1.0,0.5,0.6666666666666666,2,1,1 -2284,2288,1.0,0.6666666666666666,0.8,3,2,7 -2288,2292,1.0,0.3333333333333333,0.5,3,1,7 -2292,2296,0.5,0.25,0.3333333333333333,4,2,4 -2296,2300,0.0,0.0,0.0,3,2,8 -2300,2304,0.0,0.0,0.0,3,0,3 -2304,2308,0.0,0.0,0.0,3,0,6 -2308,2312,0.5,0.3333333333333333,0.4,3,2,11 -2312,2316,1.0,0.3333333333333333,0.5,3,1,15 -2316,2320,0.6666666666666666,0.5,0.5714285714285715,4,3,10 -2320,2324,0.0,0.0,0.0,5,0,6 -2324,2328,0.0,0.0,0.0,6,0,4 -2328,2332,0.0,0.0,0.0,5,0,3 -2332,2336,0.0,0.0,0.0,4,0,7 -2336,2340,0.0,0.0,0.0,4,0,6 -2340,2344,0.0,0.0,0.0,3,0,5 -2344,2348,0.5,0.3333333333333333,0.4,3,2,7 -2348,2352,0.0,0.0,0.0,2,0,4 -2352,2356,0.5,0.25,0.3333333333333333,4,2,10 -2356,2360,0.0,0.0,0.0,3,0,8 -2360,2364,0.0,0.0,0.0,4,1,9 -2364,2368,0.0,0.0,0.0,3,0,5 -2368,2372,0.0,0.0,0.0,2,1,3 -2372,2376,0.0,0.0,0.0,1,0,4 -2376,2380,0.0,0.0,0.0,2,0,3 -2380,2384,0.0,0.0,0.0,1,0,1 -2384,2388,0.0,0.0,0.0,2,0,3 -2388,2392,0.0,0.0,0.0,2,1,11 -2392,2396,0.0,0.0,0.0,2,0,6 -2396,2400,0.0,0.0,0.0,1,0,9 -2400,2404,0.0,0.0,0.0,2,0,5 -2404,2408,0.0,0.0,0.0,1,0,5 -2408,2412,0.0,0.0,0.0,1,0,1 -2412,2416,0.0,0.0,0.0,1,0,3 -2416,2420,0.0,0.0,0.0,3,0,5 -2420,2424,0.0,0.0,0.0,3,1,4 -2424,2428,0.0,0.0,0.0,2,0,1 -2428,2432,0.0,0.0,0.0,2,0,4 -2432,2436,0.0,0.0,0.0,2,1,6 -2436,2440,0.0,0.0,0.0,2,1,6 -2440,2444,1.0,0.5,0.6666666666666666,2,1,5 -2444,2448,0.0,0.0,0.0,1,0,9 -2448,2452,0.0,0.0,0.0,2,0,5 -2452,2456,1.0,0.5,0.6666666666666666,2,1,3 -2460,2464,0.0,0.0,0.0,1,0,2 -2464,2468,0.0,0.0,0.0,1,0,4 -2468,2472,0.0,0.0,0.0,2,0,5 -2472,2476,0.0,0.0,0.0,2,0,2 -2476,2480,0.0,0.0,0.0,3,0,4 -2480,2484,0.0,0.0,0.0,3,0,6 -2484,2488,0.0,0.0,0.0,3,0,6 -2488,2492,0.0,0.0,0.0,3,0,5 -2492,2496,0.0,0.0,0.0,3,0,4 -2496,2500,0.0,0.0,0.0,3,0,1 -2500,2504,1.0,0.3333333333333333,0.5,3,1,4 -2504,2508,0.0,0.0,0.0,3,0,4 -2508,2512,0.0,0.0,0.0,3,5,11 -2512,2516,0.5,0.5,0.5,4,4,7 -2516,2520,1.0,0.3333333333333333,0.5,3,1,1 -2520,2524,0.0,0.0,0.0,3,0,1 -2524,2528,0.0,0.0,0.0,4,3,5 -2528,2532,0.0,0.0,0.0,4,0,5 -2532,2536,0.6666666666666666,0.4,0.5,5,3,6 -2536,2540,0.3333333333333333,0.25,0.28571428571428575,4,3,7 -2540,2544,0.0,0.0,0.0,2,0,2 -2544,2548,0.0,0.0,0.0,3,0,1 -2548,2552,0.0,0.0,0.0,2,0,2 -2552,2556,0.0,0.0,0.0,2,0,5 -2556,2560,1.0,0.6666666666666666,0.8,3,2,12 -2560,2564,0.0,0.0,0.0,4,0,4 -2564,2568,0.0,0.0,0.0,4,0,4 -2568,2572,0.0,0.0,0.0,3,0,1 -2572,2576,0.0,0.0,0.0,3,0,7 -2576,2580,1.0,0.2,0.33333333333333337,5,1,3 -2580,2584,0.5,0.3333333333333333,0.4,3,2,6 -2584,2588,1.0,0.3333333333333333,0.5,3,1,2 -2588,2592,1.0,0.5,0.6666666666666666,4,2,6 -2592,2596,1.0,0.3333333333333333,0.5,3,1,1 -2596,2600,0.0,0.0,0.0,2,0,4 -2600,2604,0.0,0.0,0.0,2,0,2 -2604,2608,0.0,0.0,0.0,1,0,4 -2608,2612,0.0,0.0,0.0,1,0,6 -2612,2616,0.0,0.0,0.0,3,0,8 -2616,2620,1.0,0.25,0.4,4,1,9 -2620,2624,0.0,0.0,0.0,3,0,4 -2624,2628,0.0,0.0,0.0,3,0,6 -2628,2632,0.0,0.0,0.0,3,0,8 -2632,2636,0.0,0.0,0.0,3,1,6 -2636,2640,0.0,0.0,0.0,3,0,4 -2640,2644,1.0,0.3333333333333333,0.5,3,1,2 -2644,2648,0.5,0.5,0.5,2,2,5 -2648,2652,0.0,0.0,0.0,3,0,7 -2652,2656,0.0,0.0,0.0,4,0,5 -2656,2660,0.0,0.0,0.0,4,0,7 -2660,2664,0.0,0.0,0.0,4,0,4 -2664,2668,0.0,0.0,0.0,3,1,8 -2668,2672,0.0,0.0,0.0,3,0,8 -2672,2676,1.0,0.25,0.4,4,1,2 -2676,2680,0.0,0.0,0.0,2,0,2 -2680,2684,0.0,0.0,0.0,3,1,4 -2684,2688,0.0,0.0,0.0,3,0,2 -2688,2692,0.0,0.0,0.0,5,1,4 -2692,2696,0.0,0.0,0.0,6,2,12 -2696,2700,0.0,0.0,0.0,7,2,10 -2700,2704,0.0,0.0,0.0,7,1,12 -2704,2708,0.0,0.0,0.0,7,0,8 -2708,2712,1.0,0.14285714285714285,0.25,7,1,7 -2712,2716,0.0,0.0,0.0,6,1,6 -2716,2720,1.0,0.16666666666666666,0.2857142857142857,6,1,5 -2720,2724,0.0,0.0,0.0,6,0,7 -2724,2728,1.0,0.16666666666666666,0.2857142857142857,6,1,3 -2728,2732,0.0,0.0,0.0,4,0,2 -2732,2736,0.5,0.2,0.28571428571428575,5,2,5 -2736,2740,0.0,0.0,0.0,3,0,2 -2740,2744,0.0,0.0,0.0,3,0,2 -2744,2748,1.0,0.3333333333333333,0.5,3,1,3 -2748,2752,0.0,0.0,0.0,3,1,9 -2752,2756,0.0,0.0,0.0,3,1,21 -2756,2760,0.0,0.0,0.0,4,0,8 -2760,2764,0.0,0.0,0.0,4,0,16 -2764,2768,0.0,0.0,0.0,4,0,11 -2768,2772,0.3333333333333333,0.25,0.28571428571428575,4,3,16 -2772,2776,1.0,0.25,0.4,4,1,5 -2776,2780,0.0,0.0,0.0,4,0,2 -2780,2784,0.5,0.25,0.3333333333333333,4,2,6 -2784,2788,0.0,0.0,0.0,3,0,6 -2788,2792,0.0,0.0,0.0,4,1,3 -2792,2796,0.0,0.0,0.0,3,3,6 -2796,2800,0.0,0.0,0.0,2,1,4 -2800,2804,0.0,0.0,0.0,2,1,3 -2804,2808,0.0,0.0,0.0,3,0,4 -2808,2812,0.0,0.0,0.0,3,0,1 -2812,2816,0.0,0.0,0.0,2,0,3 -2816,2820,0.0,0.0,0.0,2,6,120 -2820,2824,0.0,0.0,0.0,1,1,4 -2824,2828,0.0,0.0,0.0,2,0,2 -2828,2832,0.0,0.0,0.0,2,0,2 -2832,2836,0.0,0.0,0.0,3,1,5 -2836,2840,0.0,0.0,0.0,3,2,4 -2840,2844,0.0,0.0,0.0,3,0,1 -2844,2848,0.0,0.0,0.0,3,0,4 -2848,2852,0.0,0.0,0.0,2,0,9 -2852,2856,0.0,0.0,0.0,1,0,8 -2872,2876,0.0,0.0,0.0,2,0,1 -2876,2880,1.0,0.5,0.6666666666666666,2,1,3 -2880,2884,0.0,0.0,0.0,1,0,1 -2884,2888,0.0,0.0,0.0,1,0,2 -2888,2892,1.0,1.0,1.0,1,1,1 -2896,2900,0.0,0.0,0.0,1,0,2 -2900,2904,0.0,0.0,0.0,2,0,2 -2904,2908,0.0,0.0,0.0,2,0,2 -2908,2912,0.0,0.0,0.0,2,0,1 -2912,2916,0.0,0.0,0.0,1,0,1 -2916,2920,0.0,0.0,0.0,2,0,5 -2920,2924,0.0,0.0,0.0,2,0,2 -2924,2928,0.0,0.0,0.0,2,0,4 -2928,2932,0.0,0.0,0.0,2,0,7 -2932,2936,0.0,0.0,0.0,3,0,2 -2936,2940,1.0,0.25,0.4,4,1,5 -2940,2944,0.0,0.0,0.0,4,2,8 -2944,2948,0.0,0.0,0.0,6,1,2 -2948,2952,0.25,0.14285714285714285,0.18181818181818182,7,4,5 -2952,2956,0.5,0.16666666666666666,0.25,6,2,2 -2956,2960,0.0,0.0,0.0,6,0,2 -2960,2964,0.5,0.16666666666666666,0.25,6,2,5 -2964,2968,0.5,0.6666666666666666,0.5714285714285715,6,8,13 -2968,2972,0.0,0.0,0.0,3,1,1 -2972,2976,0.0,0.0,0.0,3,0,3 -2976,2980,0.0,0.0,0.0,4,0,6 -2980,2984,0.0,0.0,0.0,1,0,12 -2984,2988,0.0,0.0,0.0,3,1,11 -2988,2992,0.0,0.0,0.0,3,1,18 -2992,2996,0.0,0.0,0.0,4,2,23 -2996,3000,0.5,0.25,0.3333333333333333,4,2,6 -3000,3004,0.0,0.0,0.0,2,0,3 -3004,3008,1.0,0.3333333333333333,0.5,3,1,4 -3008,3012,0.0,0.0,0.0,2,0,4 -3012,3016,0.5,0.5,0.5,2,2,7 -3016,3020,0.0,0.0,0.0,1,1,6 -3020,3024,0.0,0.0,0.0,1,0,1 -3024,3028,1.0,1.0,1.0,1,1,1 -3040,3044,0.0,0.0,0.0,2,0,3 -3044,3048,0.0,0.0,0.0,2,1,4 -3048,3052,1.0,0.25,0.4,4,1,5 -3052,3056,1.0,0.2,0.33333333333333337,5,1,3 -3056,3060,0.0,0.0,0.0,3,0,1 -3060,3064,0.0,0.0,0.0,2,0,1 -3064,3068,0.0,0.0,0.0,3,0,2 -3068,3072,0.0,0.0,0.0,2,0,1 -3072,3076,0.0,0.0,0.0,3,0,9 -3076,3080,0.0,0.0,0.0,2,3,10 -3080,3084,0.0,0.0,0.0,2,0,3 -3084,3088,0.0,0.0,0.0,3,2,10 -3088,3092,1.0,0.3333333333333333,0.5,3,1,1 -3092,3096,0.0,0.0,0.0,3,0,3 -3096,3100,0.0,0.0,0.0,3,0,7 -3100,3104,0.0,0.0,0.0,4,0,6 -3104,3108,0.0,0.0,0.0,4,1,15 -3108,3112,0.0,0.0,0.0,3,0,7 -3112,3116,0.0,0.0,0.0,3,0,4 -3116,3120,0.0,0.0,0.0,3,0,5 -3120,3124,0.0,0.0,0.0,3,0,3 -3124,3128,0.0,0.0,0.0,2,0,1 -3128,3132,0.0,0.0,0.0,3,1,4 -3132,3136,0.0,0.0,0.0,3,0,1 -3136,3140,0.0,0.0,0.0,3,0,3 -3140,3144,0.0,0.0,0.0,4,0,3 -3144,3148,1.0,0.25,0.4,4,1,9 -3148,3152,0.0,0.0,0.0,4,0,2 -3152,3156,0.0,0.0,0.0,3,0,7 -3156,3160,0.0,0.0,0.0,4,1,4 -3160,3164,0.0,0.0,0.0,4,2,9 -3164,3168,0.0,0.0,0.0,3,0,1 -3168,3172,0.0,0.0,0.0,2,0,1 -3172,3176,0.5,0.5,0.5,2,2,7 -3176,3180,0.0,0.0,0.0,1,0,4 -3188,3192,0.0,0.0,0.0,1,0,2 -3192,3196,0.0,0.0,0.0,3,0,2 -3196,3200,0.0,0.0,0.0,3,0,3 -3200,3204,1.0,0.25,0.4,4,1,4 -3204,3208,0.0,0.0,0.0,3,0,1 -3208,3212,0.0,0.0,0.0,3,0,2 -3212,3216,1.0,0.25,0.4,4,1,2 -3216,3220,0.0,0.0,0.0,4,0,2 -3220,3224,0.0,0.0,0.0,4,1,4 -3224,3228,0.0,0.0,0.0,4,1,9 -3228,3232,0.0,0.0,0.0,4,1,3 -3232,3236,0.0,0.0,0.0,3,2,7 -3236,3240,0.0,0.0,0.0,4,0,2 -3240,3244,0.0,0.0,0.0,5,0,2 -3244,3248,0.0,0.0,0.0,4,1,11 -3248,3252,0.0,0.0,0.0,2,0,5 -3252,3256,0.0,0.0,0.0,2,0,11 -3256,3260,1.0,0.14285714285714285,0.25,7,1,3 -3260,3264,0.0,0.0,0.0,6,0,5 -3264,3268,1.0,0.16666666666666666,0.2857142857142857,6,1,2 -3268,3272,0.0,0.0,0.0,4,0,2 -3272,3276,1.0,0.2,0.33333333333333337,5,1,5 -3276,3280,0.0,0.0,0.0,6,1,10 -3280,3284,0.5,0.16666666666666666,0.25,6,2,8 -3284,3288,1.0,0.25,0.4,4,1,9 -3288,3292,0.0,0.0,0.0,2,1,10 -3292,3296,0.0,0.0,0.0,3,1,6 -3296,3300,0.25,0.3333333333333333,0.28571428571428575,3,4,24 -3300,3304,1.0,0.3333333333333333,0.5,3,1,6 -3304,3308,0.0,0.0,0.0,2,0,13 -3308,3312,0.0,0.0,0.0,3,0,5 -3312,3316,0.0,0.0,0.0,2,1,3 -3316,3320,0.0,0.0,0.0,1,0,4 -3320,3324,0.0,0.0,0.0,2,0,3 -3324,3328,0.0,0.0,0.0,1,0,2 -3328,3332,0.0,0.0,0.0,2,0,3 -3332,3336,0.0,0.0,0.0,2,0,4 -3336,3340,0.5,0.5,0.5,2,2,5 -3340,3344,0.0,0.0,0.0,1,0,9 -3344,3348,0.0,0.0,0.0,2,0,6 -3348,3352,0.0,0.0,0.0,1,0,13 -3352,3356,0.0,0.0,0.0,1,0,6 -3356,3360,0.0,0.0,0.0,1,0,7 -3360,3364,0.0,0.0,0.0,3,0,4 -3364,3368,0.0,0.0,0.0,2,0,1 -3368,3372,1.0,0.3333333333333333,0.5,3,1,3 -3372,3376,0.0,0.0,0.0,2,0,1 -3376,3380,0.0,0.0,0.0,2,0,5 -3380,3384,0.0,0.0,0.0,2,0,5 -3384,3388,0.0,0.0,0.0,2,0,2 -3388,3392,0.0,0.0,0.0,2,0,2 -3392,3396,0.0,0.0,0.0,1,0,3 -3396,3400,0.0,0.0,0.0,1,0,2 -3400,3404,0.0,0.0,0.0,1,0,4 -3404,3408,0.0,0.0,0.0,3,0,1 -3420,3424,0.0,0.0,0.0,2,0,2 -3424,3428,0.0,0.0,0.0,3,0,5 -3428,3432,0.0,0.0,0.0,4,0,3 -3432,3436,0.0,0.0,0.0,3,0,4 -3436,3440,0.0,0.0,0.0,3,0,2 -3440,3444,0.0,0.0,0.0,3,1,7 -3444,3448,0.0,0.0,0.0,3,0,9 -3448,3452,0.0,0.0,0.0,2,0,6 -3452,3456,0.0,0.0,0.0,1,0,1 -3456,3460,0.0,0.0,0.0,1,0,3 -3460,3464,0.0,0.0,0.0,1,0,1 -3464,3468,0.0,0.0,0.0,2,0,5 -3468,3472,0.0,0.0,0.0,4,1,9 -3472,3476,0.0,0.0,0.0,5,0,1 -3476,3480,0.0,0.0,0.0,4,0,4 -3480,3484,0.0,0.0,0.0,3,1,7 -3484,3488,0.0,0.0,0.0,3,0,4 -3488,3492,0.0,0.0,0.0,2,0,11 -3492,3496,0.0,0.0,0.0,2,0,4 -3496,3500,0.0,0.0,0.0,2,2,9 -3500,3504,0.0,0.0,0.0,2,0,9 -3504,3508,0.0,0.0,0.0,2,0,6 -3508,3512,1.0,0.25,0.4,4,1,4 -3512,3516,1.0,0.09090909090909091,0.16666666666666669,11,1,3 -3516,3520,0.3333333333333333,0.14285714285714285,0.2,7,3,4 -3520,3524,0.0,0.0,0.0,7,0,1 -3524,3528,0.6666666666666666,0.25,0.36363636363636365,8,3,8 -3528,3532,0.0,0.0,0.0,7,2,6 -3532,3536,0.0,0.0,0.0,8,1,4 -3536,3540,0.5,0.6666666666666666,0.5714285714285715,9,12,24 -3540,3544,0.75,0.6666666666666666,0.7058823529411765,9,8,19 -3544,3548,0.0,0.0,0.0,7,1,6 -3548,3552,0.75,0.3333333333333333,0.46153846153846156,9,4,12 -3552,3556,1.0,0.25,0.4,8,2,7 -3556,3560,0.75,0.42857142857142855,0.5454545454545454,7,4,7 -3560,3564,0.6,0.6,0.6,5,5,8 -3564,3568,0.0,0.0,0.0,4,0,7 -3568,3572,0.0,0.0,0.0,4,0,1 -3572,3576,0.0,0.0,0.0,3,0,2 -3576,3580,0.0,0.0,0.0,4,0,2 -3580,3584,0.6666666666666666,0.3333333333333333,0.4444444444444444,6,3,6 -3584,3588,0.5,0.42857142857142855,0.4615384615384615,7,6,9 -3588,3592,1.0,0.16666666666666666,0.2857142857142857,6,1,4 -3592,3596,0.6666666666666666,0.3333333333333333,0.4444444444444444,6,3,6 -3596,3600,0.0,0.0,0.0,7,0,1 -3600,3604,0.0,0.0,0.0,6,0,2 -3604,3608,0.0,0.0,0.0,5,0,4 -3608,3612,1.0,0.2,0.33333333333333337,5,1,4 -3612,3616,0.0,0.0,0.0,8,2,4 -3616,3620,0.2857142857142857,0.25,0.26666666666666666,8,7,10 -3620,3624,0.25,0.2222222222222222,0.23529411764705882,9,8,10 -3624,3628,0.0,0.0,0.0,8,1,7 -3628,3632,0.75,0.5,0.6,6,4,7 -3632,3636,1.0,0.6666666666666666,0.8,3,2,13 -3636,3640,0.0,0.0,0.0,5,0,1 -3640,3644,0.0,0.0,0.0,4,0,1 -3644,3648,0.6666666666666666,0.4,0.5,5,3,5 -3648,3652,0.0,0.0,0.0,4,0,1 -3652,3656,0.0,0.0,0.0,5,1,2 -3656,3660,0.0,0.0,0.0,3,0,2 -3660,3664,0.0,0.0,0.0,2,0,4 -3664,3668,0.0,0.0,0.0,3,0,4 -3668,3672,0.0,0.0,0.0,2,0,2 -3672,3676,0.0,0.0,0.0,3,0,1 -3676,3680,0.0,0.0,0.0,3,0,1 -3680,3684,0.0,0.0,0.0,1,0,2 -3684,3688,0.0,0.0,0.0,2,0,2 -3688,3692,0.0,0.0,0.0,3,0,1 -3692,3696,0.0,0.0,0.0,3,0,1 -3696,3700,0.0,0.0,0.0,2,0,1 -3700,3704,0.0,0.0,0.0,2,0,1 -3704,3708,0.0,0.0,0.0,2,0,4 -3708,3712,0.5,0.5,0.5,2,2,6 -3712,3716,0.0,0.0,0.0,4,0,2 -3716,3720,0.0,0.0,0.0,3,0,1 -3720,3724,0.0,0.0,0.0,4,0,1 -3724,3728,0.0,0.0,0.0,4,0,2 -3728,3732,0.0,0.0,0.0,4,1,7 -3732,3736,0.0,0.0,0.0,2,0,5 -3736,3740,1.0,0.5,0.6666666666666666,2,1,4 -3740,3744,0.0,0.0,0.0,1,0,2 -3760,3764,1.0,0.5,0.6666666666666666,2,1,10 -3764,3768,0.0,0.0,0.0,2,0,1 -3768,3772,0.0,0.0,0.0,1,0,1 -3772,3776,0.0,0.0,0.0,2,0,1 -3776,3780,0.0,0.0,0.0,3,0,4 -3780,3784,0.0,0.0,0.0,2,0,6 -3784,3788,0.0,0.0,0.0,2,0,4 -3788,3792,0.0,0.0,0.0,1,0,5 -3800,3804,0.0,0.0,0.0,1,0,4 -3804,3808,0.0,0.0,0.0,2,0,2 -3808,3812,0.0,0.0,0.0,2,1,16 -3812,3816,1.0,0.25,0.4,4,1,9 -3816,3820,1.0,0.3333333333333333,0.5,3,1,5 -3820,3824,0.0,0.0,0.0,2,0,6 -3824,3828,0.0,0.0,0.0,2,0,6 -3828,3832,0.0,0.0,0.0,1,0,5 -3832,3836,0.0,0.0,0.0,1,0,1 -3836,3840,0.0,0.0,0.0,2,0,2 -3840,3844,0.0,0.0,0.0,3,0,10 -3844,3848,0.0,0.0,0.0,3,0,1 -3848,3852,0.0,0.0,0.0,3,1,6 -3852,3856,0.0,0.0,0.0,2,0,3 -3856,3860,0.0,0.0,0.0,3,0,5 -3860,3864,0.0,0.0,0.0,3,0,11 -3864,3868,0.0,0.0,0.0,4,0,7 -3868,3872,0.5,0.14285714285714285,0.22222222222222224,7,2,9 -3872,3876,1.0,0.16666666666666666,0.2857142857142857,6,1,1 -3876,3880,0.0,0.0,0.0,5,3,14 -3880,3884,1.0,0.16666666666666666,0.2857142857142857,6,1,9 -3884,3888,0.0,0.0,0.0,5,4,6 -3888,3892,0.0,0.0,0.0,4,3,8 -3892,3896,0.0,0.0,0.0,3,2,9 -3896,3900,1.0,0.2,0.33333333333333337,5,1,7 -3900,3904,0.0,0.0,0.0,6,0,3 -3904,3908,0.0,0.0,0.0,5,0,3 -3908,3912,0.0,0.0,0.0,4,0,3 -3912,3916,1.0,0.25,0.4,4,1,5 -3916,3920,0.5,0.3333333333333333,0.4,3,2,6 -3920,3924,0.0,0.0,0.0,2,0,5 -3924,3928,0.0,0.0,0.0,2,1,9 -3928,3932,0.0,0.0,0.0,2,2,8 -3932,3936,0.0,0.0,0.0,2,1,11 -3936,3940,0.0,0.0,0.0,1,0,1 -3968,3972,1.0,0.5,0.6666666666666666,2,1,1 -3972,3976,0.0,0.0,0.0,1,0,1 -3976,3980,0.0,0.0,0.0,1,0,2 -3980,3984,0.0,0.0,0.0,2,0,1 -3984,3988,0.0,0.0,0.0,2,0,8 -3988,3992,0.0,0.0,0.0,1,0,2 -3992,3996,0.0,0.0,0.0,2,1,3 -3996,4000,0.0,0.0,0.0,1,0,3 -4000,4004,0.0,0.0,0.0,3,0,3 -4004,4008,0.0,0.0,0.0,2,0,2 -4008,4012,0.0,0.0,0.0,2,0,2 -4012,4016,0.0,0.0,0.0,3,0,4 -4016,4020,0.0,0.0,0.0,2,0,1 -4020,4024,0.0,0.0,0.0,2,1,6 -4024,4028,0.0,0.0,0.0,2,0,4 -4028,4032,0.0,0.0,0.0,1,0,1 -4044,4048,0.0,0.0,0.0,1,0,2 -4048,4052,0.0,0.0,0.0,2,0,1 -4052,4056,0.0,0.0,0.0,2,0,4 -4056,4060,0.0,0.0,0.0,2,0,2 -4060,4064,1.0,0.5,0.6666666666666666,2,1,4 -4064,4068,0.0,0.0,0.0,2,0,3 -4068,4072,0.0,0.0,0.0,2,0,1 -4072,4076,1.0,0.5,0.6666666666666666,2,1,5 -4076,4080,0.0,0.0,0.0,1,0,3 -4100,4104,0.0,0.0,0.0,1,0,1 -4104,4108,0.0,0.0,0.0,1,0,3 -4108,4112,0.0,0.0,0.0,2,0,2 -4112,4116,0.0,0.0,0.0,2,0,5 -4116,4120,0.0,0.0,0.0,1,0,1 -4128,4132,0.0,0.0,0.0,1,0,3 -4132,4136,0.0,0.0,0.0,1,0,2 -4136,4140,0.0,0.0,0.0,2,0,4 -4140,4144,0.0,0.0,0.0,2,0,1 -4144,4148,0.0,0.0,0.0,2,0,8 -4148,4152,1.0,0.5,0.6666666666666666,2,1,6 -4152,4156,0.0,0.0,0.0,1,0,2 -4160,4164,0.0,0.0,0.0,1,0,2 -4164,4168,0.0,0.0,0.0,1,0,7 -4168,4172,1.0,0.3333333333333333,0.5,3,1,16 -4172,4176,0.0,0.0,0.0,3,0,2 -4176,4180,0.0,0.0,0.0,1,0,10 -4180,4184,1.0,1.0,1.0,1,1,4 -4184,4188,0.0,0.0,0.0,1,0,4 -4188,4192,0.0,0.0,0.0,2,0,3 -4192,4196,0.0,0.0,0.0,2,1,12 -4196,4200,1.0,0.5,0.6666666666666666,2,1,1 -4204,4208,0.0,0.0,0.0,1,0,7 -4208,4212,0.0,0.0,0.0,1,0,2 -4212,4216,0.5,0.5,0.5,2,2,4 -4216,4220,0.0,0.0,0.0,1,0,4 -4236,4240,0.0,0.0,0.0,1,0,3 -4240,4244,0.0,0.0,0.0,1,0,4 -4284,4288,0.0,0.0,0.0,1,0,6 -4288,4292,0.0,0.0,0.0,1,0,3 -4292,4296,0.0,0.0,0.0,1,1,10 -4296,4300,0.0,0.0,0.0,1,0,1 -4356,4360,1.0,1.0,1.0,1,1,6 -4360,4364,0.0,0.0,0.0,3,0,2 -4364,4368,1.0,0.4,0.5714285714285715,5,2,7 -4368,4372,1.0,0.5,0.6666666666666666,6,3,19 -4372,4376,0.5,0.16666666666666666,0.25,6,2,14 -4376,4380,0.3333333333333333,0.2,0.25,5,3,18 -4380,4384,0.0,0.0,0.0,3,0,1 -4384,4388,0.0,0.0,0.0,2,0,3 -4388,4392,1.0,0.5,0.6666666666666666,2,1,7 -4392,4396,0.0,0.0,0.0,2,0,2 -4396,4400,0.0,0.0,0.0,2,0,4 -4400,4404,0.0,0.0,0.0,2,2,5 -4404,4408,0.0,0.0,0.0,1,0,3 -4412,4416,0.0,0.0,0.0,1,0,1 -4416,4420,0.0,0.0,0.0,1,0,1 -4420,4424,0.0,0.0,0.0,1,0,7 -4424,4428,0.0,0.0,0.0,1,0,2 -4428,4432,0.0,0.0,0.0,1,0,4 -4432,4436,0.0,0.0,0.0,1,0,11 -4436,4440,0.0,0.0,0.0,1,0,11 -4440,4444,0.0,0.0,0.0,1,0,5 -4444,4448,0.0,0.0,0.0,1,0,3 -4448,4452,0.0,0.0,0.0,1,0,1 -4452,4456,0.0,0.0,0.0,1,0,1 -4456,4460,0.0,0.0,0.0,1,0,13 -4460,4464,0.0,0.0,0.0,3,0,5 -4464,4468,1.0,0.25,0.4,4,1,1 -4468,4472,0.5,0.25,0.3333333333333333,4,2,6 -4472,4476,1.0,0.25,0.4,4,1,6 -4476,4480,0.5,0.4,0.4444444444444445,5,4,6 -4480,4484,0.0,0.0,0.0,3,1,5 -4484,4488,0.0,0.0,0.0,3,0,6 -4488,4492,1.0,0.5,0.6666666666666666,2,1,15 -4492,4496,0.0,0.0,0.0,4,0,1 -4496,4500,0.25,0.25,0.25,4,4,11 -4500,4504,0.0,0.0,0.0,4,1,4 -4504,4508,0.4,0.4,0.4000000000000001,5,5,10 -4508,4512,0.0,0.0,0.0,6,0,3 -4512,4516,0.0,0.0,0.0,6,0,2 -4516,4520,0.0,0.0,0.0,4,0,4 -4520,4524,1.0,0.25,0.4,4,1,1 -4524,4528,0.0,0.0,0.0,2,0,1 -4528,4532,0.5,0.2,0.28571428571428575,5,2,6 -4532,4536,0.3333333333333333,0.14285714285714285,0.2,7,3,5 -4536,4540,0.0,0.0,0.0,9,0,2 diff --git a/experiment/hdbscan/main_kitti_processing_hdbscan_voxel.py b/experiment/hdbscan/main_kitti_processing_hdbscan_voxel.py index 149b0f8..045db87 100644 --- a/experiment/hdbscan/main_kitti_processing_hdbscan_voxel.py +++ b/experiment/hdbscan/main_kitti_processing_hdbscan_voxel.py @@ -21,14 +21,10 @@ def segment_pcds_by_hdbscan(start_index, end_index): - file_name = ( - "experiment_bin_0704_4_sem_voxel_offset0_T0l03/start{}_end{}.pickle".format( - start_index, end_index - ) - ) + file_name = "experiment_bin/start{}_end{}.pickle".format(start_index, end_index) with open(file_name, "rb") as file: - data = pickle.load(file) + data = pickle.load(file) # prepared dense cloud pcd_hdbscan_voxel_down_points = np.asarray(data[2]["voxel_pcd_original_points"]) pcd_hdbscan_voxel_down = o3d.geometry.PointCloud() @@ -62,9 +58,9 @@ def process_kitti_hdbscan(from_num, to_num): result_tuple = segment_pcds_by_hdbscan(start_index, end_index) - file_name = "experiment_bin_0704_4_sem_voxel_offset0_T0l03_hdbscan/start{}_end{}.pickle".format( + file_name = "experiment_bin_hdbscan/start{}_end{}.pickle".format( start_index, end_index - ) + ) # hdbscan results new_file = open(file_name, "w") new_file.close() diff --git a/experiment/hdbscan/main_kitti_processing_metrics_hdbscan.py b/experiment/hdbscan/main_kitti_processing_metrics_hdbscan.py index 40cbfde..f3bdf2d 100644 --- a/experiment/hdbscan/main_kitti_processing_metrics_hdbscan.py +++ b/experiment/hdbscan/main_kitti_processing_metrics_hdbscan.py @@ -81,7 +81,7 @@ def main(): from_num = 0 to_num = 4540 - instance_thresholds = [5, 20, 30, 50] + instance_thresholds = [30, 50] for instance_threshold in instance_thresholds: print("Start to process instance_threshold={}".format(instance_threshold)) @@ -93,7 +93,7 @@ def main(): start_index = current_from_num end_index = start_index + 4 - file_name = "experiment_bin_0704_4_sem_voxel_offset0_T0l03_hdbscan/start{}_end{}.pickle".format( + file_name = "experiment_bin_hdbscan/start{}_end{}.pickle".format( start_index, end_index ) @@ -106,7 +106,7 @@ def main(): if ( inst_label_array_for_clustering.sum() == 0 - ): # в облаке нет инстансов => пропускаем + ): # there are no instances in the cloud => skip skipped += 1 print( "start_index={}, end_index={} skip".format(start_index, end_index) @@ -139,9 +139,7 @@ def main(): pred_labels_unique.discard(0) with open( - "experiment_1004_4_without0_sem_voxel_offset0_T0l03_hdbscan_{}.csv".format( - instance_threshold - ), + "experiment_hdbscan_{}.csv".format(instance_threshold), "a", newline="", ) as file: diff --git a/experiment/main_calc_metrics_by_csv.py b/experiment/main_calc_metrics_by_csv.py index 2c7d855..49138be 100644 --- a/experiment/main_calc_metrics_by_csv.py +++ b/experiment/main_calc_metrics_by_csv.py @@ -65,7 +65,7 @@ def calculate_metrics(file_name): def main(): - calculate_metrics("experiment_2_a5b5_sem_voxel_offset0_T0l025_50.csv") + calculate_metrics("experiment_hdbscan_50.csv") if __name__ == "__main__": diff --git a/experiment/main_kitti_processing.py b/experiment/main_kitti_processing.py index 9d358ba..dede9d5 100644 --- a/experiment/main_kitti_processing.py +++ b/experiment/main_kitti_processing.py @@ -197,7 +197,7 @@ def process_kitti( result_tuple = segment_pcds(config) file_name = ( - "experiment_2_a5b5_sem_voxel_offset0_T0l025/start{}_end{}.pickle".format( + "experiment_bin/start{}_end{}.pickle".format( config.start_index, config.end_index ) ) @@ -217,7 +217,7 @@ def main(): alpha_physical_distance = 5 beta_instance_distance = 5 - T_normalized_cut = 0.025 + T_normalized_cut = 0.02 process_kitti( start_pcd_num, diff --git a/experiment/main_kitti_processing_metrics.py b/experiment/main_kitti_processing_metrics.py index 029ca88..a44c11f 100644 --- a/experiment/main_kitti_processing_metrics.py +++ b/experiment/main_kitti_processing_metrics.py @@ -61,7 +61,7 @@ def main(): from_num = 0 to_num = 4540 - instance_thresholds = [5, 20, 30, 50] + instance_thresholds = [30, 50] for instance_threshold in instance_thresholds: print("Start to process instance_threshold={}".format(instance_threshold)) @@ -73,7 +73,7 @@ def main(): start_index = current_from_num end_index = start_index + 4 - file_name = "experiment_2_a5b5_sem_voxel_offset0_T0l025/start{}_end{}.pickle".format( + file_name = "experiment_bin/start{}_end{}.pickle".format( start_index, end_index ) @@ -86,7 +86,7 @@ def main(): if ( inst_label_array_for_clustering.sum() == 0 - ): # в облаке нет инстансов => пропускаем + ): # there are no instances in the cloud => skip skipped += 1 print( "start_index={}, end_index={} skip".format(start_index, end_index) @@ -115,9 +115,7 @@ def main(): pred_labels_unique.discard(0) with open( - "experiment_2_a5b5_sem_voxel_offset0_T0l025_{}.csv".format( - instance_threshold - ), + "experiment_{}.csv".format(instance_threshold), "a", newline="", ) as file: From 36cac3d3d451f7d9c98b4011366ea5fbc3a21c74 Mon Sep 17 00:00:00 2001 From: SVivdich02 Date: Thu, 30 May 2024 10:34:04 +0300 Subject: [PATCH 13/21] small fixes --- experiment/main_kitti_processing.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/experiment/main_kitti_processing.py b/experiment/main_kitti_processing.py index dede9d5..9e18732 100644 --- a/experiment/main_kitti_processing.py +++ b/experiment/main_kitti_processing.py @@ -196,10 +196,8 @@ def process_kitti( result_tuple = segment_pcds(config) - file_name = ( - "experiment_bin/start{}_end{}.pickle".format( - config.start_index, config.end_index - ) + file_name = "experiment_bin/start{}_end{}.pickle".format( + config.start_index, config.end_index ) new_file = open(file_name, "w") new_file.close() From a28cdeec3c2aa42c96265df81643691980190a71 Mon Sep 17 00:00:00 2001 From: SVivdich02 Date: Thu, 30 May 2024 13:04:02 +0300 Subject: [PATCH 14/21] fixes --- experiment/main_kitti_processing.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/experiment/main_kitti_processing.py b/experiment/main_kitti_processing.py index 9e18732..4931d68 100644 --- a/experiment/main_kitti_processing.py +++ b/experiment/main_kitti_processing.py @@ -15,6 +15,9 @@ import copy import numpy as np import pickle +import sys + +sys.path.append('/Users/sofiavivdich/proj/lidar-labelling') from scipy.spatial.distance import cdist From a65b611430d57b4fd968dc3a324d68b4b9337009 Mon Sep 17 00:00:00 2001 From: SVivdich02 Date: Sat, 1 Jun 2024 09:30:46 +0300 Subject: [PATCH 15/21] fixes --- experiment/main_calc_metrics_by_csv.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/experiment/main_calc_metrics_by_csv.py b/experiment/main_calc_metrics_by_csv.py index 49138be..0eb48cf 100644 --- a/experiment/main_calc_metrics_by_csv.py +++ b/experiment/main_calc_metrics_by_csv.py @@ -65,7 +65,7 @@ def calculate_metrics(file_name): def main(): - calculate_metrics("experiment_hdbscan_50.csv") + calculate_metrics("experiment_50.csv") if __name__ == "__main__": From ea9193dc453f9b2d2c6aa78a1b0eb9e42dd71e7a Mon Sep 17 00:00:00 2001 From: SVivdich02 Date: Sat, 1 Jun 2024 09:46:56 +0300 Subject: [PATCH 16/21] refactoring --- experiment/main_calc_metrics_by_csv.py | 2 +- experiment/main_kitti_processing.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/experiment/main_calc_metrics_by_csv.py b/experiment/main_calc_metrics_by_csv.py index 0eb48cf..49138be 100644 --- a/experiment/main_calc_metrics_by_csv.py +++ b/experiment/main_calc_metrics_by_csv.py @@ -65,7 +65,7 @@ def calculate_metrics(file_name): def main(): - calculate_metrics("experiment_50.csv") + calculate_metrics("experiment_hdbscan_50.csv") if __name__ == "__main__": diff --git a/experiment/main_kitti_processing.py b/experiment/main_kitti_processing.py index 4931d68..a42809c 100644 --- a/experiment/main_kitti_processing.py +++ b/experiment/main_kitti_processing.py @@ -17,7 +17,7 @@ import pickle import sys -sys.path.append('/Users/sofiavivdich/proj/lidar-labelling') +sys.path.append("/Users/sofiavivdich/proj/lidar-labelling") from scipy.spatial.distance import cdist From 9e826c2914bb98f4d8cd104d28947285fde27906 Mon Sep 17 00:00:00 2001 From: SVivdich02 Date: Sat, 1 Jun 2024 10:24:24 +0300 Subject: [PATCH 17/21] update requirements --- requirements.txt | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/requirements.txt b/requirements.txt index 3720fa0..21df6b1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,14 +1,20 @@ +attrs==23.1.0 +evops==1.0.0 +hdbscan==0.8.33 +jupyter==1.0.0 +matplotlib==3.7.2 numpy==1.25.2 +numpy-indexed==0.3.7 open3d==0.17.0 -opencv_python==4.8.1.78 -Pillow==9.4.0 -pytest==7.2.2 -scipy==1.11.3 -torch==2.0.0 -torchvision==0.15.1 +opencv-python==4.8.1.78 +overrides==7.4.0 +Pillow==10.0.0 pykitti==0.3.1 -numpy_indexed==0.3.7 -matplotlib==3.7.2 -supervision==0.14.0 -segment_anything==1.0 -zope.interface==6.1.0 \ No newline at end of file +pytest==7.4.4 +scikit-learn==1.3.0 +scipy==1.11.2 +segment-anything==1.0 +supervision==0.16.0 +torch==2.1.0 +torchvision==0.16.0 +zope.interface==6.1 From 3f690ce7edbaea48e873cb43277feb89eeefcaed Mon Sep 17 00:00:00 2001 From: SVivdich02 Date: Sat, 1 Jun 2024 10:50:07 +0300 Subject: [PATCH 18/21] update README and example files --- README.md | 7 +++- example.ipynb | 103 +++++++++++------------------------------------ example_gt.ipynb | 5 ++- 3 files changed, 33 insertions(+), 82 deletions(-) diff --git a/README.md b/README.md index bb53720..8232121 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ lidar-labelling is a tool for automatic segmentation of raw lidar clouds based o Our labelling algorithm consists of two stages. -The first stage is a preliminary marking - a naive transfer of segmentation from images (performed by the [SAM](https://github.com/facebookresearch/segment-anything) algorithm) to the cloud. Then multi-stage processing of the cloud is performed, which allows us to make the cloud more compact before the final labelling without losing points that are significant for labelling. The preprocessing stages include removing points whose corresponding pixels were not marked on a sequence of images, selection of points close to the sensors, removal of noise, cloud voxelization. +The first stage is a preliminary segmentation - a naive transfer of segmentation from images (performed by the [SAM](https://github.com/facebookresearch/segment-anything) algorithm) to the cloud. Then multi-stage processing of the cloud is performed, which allows us to make the cloud more compact before the final labelling without losing points that are significant for labelling. The preprocessing stages include removing points whose corresponding pixels were not marked on a sequence of images, selection of points close to the sensors, removal of noise, cloud voxelization. The next stage is segmentation itself. The segmentation criterion in this work is the distance between points, which is calculated through the physical distance and the degree of similarity of the labelling of points on several images. Based on the distance matrix, the prepared cloud is segmented using the [GraphCut](https://ieeexplore.ieee.org/abstract/document/937505) algorithm. @@ -16,6 +16,11 @@ This tool currently supports processing of [KITTI](https://www.cvlibs.net/datase ## Usage Please check `example.ipynb` with a example of cloud segmentation from the [KITTI](https://www.cvlibs.net/datasets/kitti/eval_odometry.php) dataset. +## Experiments +Files for reproducing experiments are in folder `experiment`. You will need the [KITTI](https://www.cvlibs.net/datasets/kitti/eval_odometry.php) dataset with its folder structure and pre-performed image segmentation using the [SAM](https://github.com/facebookresearch/segment-anything) algorithm in npz format. + +First run `main_kitti_processing.py` to generate segmentation with our algorithm. Then run `main_kitti_processing_metrics.py` to calculate the segmentation metrics of each run and write them to a csv file. Then run `main_calc_metrics_by_csv.py` to calculate the average values ​​of the metrics in the csv file. + ## License This project is licensed under the Apache License — see the [LICENSE](https://github.com/prime-slam/lidar-labelling/blob/main/LICENSE) file for details. diff --git a/example.ipynb b/example.ipynb index d4a0b93..147e2ea 100644 --- a/example.ipynb +++ b/example.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -16,7 +16,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -32,7 +32,7 @@ " \"start_image_index_offset\": 0,\n", " \"alpha_physical_distance\": 5,\n", " \"beta_instance_distance\": 5,\n", - " \"T_normalized_cut\": 0.025,\n", + " \"T_normalized_cut\": 0.02,\n", " \"reduce_detail_int_to_union_threshold\": 0.5,\n", " \"reduce_detail_int_to_mask_threshold\": 0.6,\n", " \"cam_name\": \"cam2\",\n", @@ -46,7 +46,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -61,27 +61,16 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(498379, 4)" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "points2instances.shape" ] }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -98,7 +87,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -117,7 +106,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -135,7 +124,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -152,7 +141,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -165,7 +154,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -182,7 +171,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -207,27 +196,16 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(3502, 3502)" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "dist.shape" ] }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -247,19 +225,9 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(3502, 3502)\n", - "3502\n", - "3502\n" - ] - } - ], + "outputs": [], "source": [ "print(dist.shape)\n", "print(len(points))\n", @@ -268,7 +236,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -287,48 +255,25 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "22" - ] - }, - "execution_count": 16, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "len(clusters)" ] }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([ 206, 207, 456, 457, 496, 498, 1271, 1272, 1275, 1276, 1285,\n", - " 1390, 1450, 1451, 1559, 1560, 1596, 1597, 2310, 2311])" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "clusters[0]" ] }, { "cell_type": "code", - "execution_count": 18, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ diff --git a/example_gt.ipynb b/example_gt.ipynb index 9ae87ae..aebb952 100644 --- a/example_gt.ipynb +++ b/example_gt.ipynb @@ -33,7 +33,7 @@ " \"start_image_index_offset\": 0,\n", " \"alpha_physical_distance\": 5,\n", " \"beta_instance_distance\": 5,\n", - " \"T_normalized_cut\": 0.025,\n", + " \"T_normalized_cut\": 0.02,\n", " \"reduce_detail_int_to_union_threshold\": 0.5,\n", " \"reduce_detail_int_to_mask_threshold\": 0.6,\n", " \"cam_name\": \"cam2\",\n", @@ -398,7 +398,8 @@ "outputs": [], "source": [ "# an array of predictions\n", - "# if instance_threshold percent or more of the cluster is in the gt instance, consider the cluster to be selected for comparison\n", + "# if instance_threshold percent or more of the cluster is in the gt instance,\n", + "# consider the cluster to be selected for comparison\n", "\n", "pred_inst_array = build_pred_inst_array(\n", " copy.deepcopy(inst_label_array_for_clustering),\n", From b63346de13c6c38a94ac4c6ce83b2c28ad6a0e1f Mon Sep 17 00:00:00 2001 From: SVivdich02 Date: Sat, 1 Jun 2024 10:59:49 +0300 Subject: [PATCH 19/21] update README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8232121..8efc470 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,11 @@ [![tests](https://github.com/prime-slam/lidar-labelling/actions/workflows/ci.yml/badge.svg)](https://github.com/prime-slam/lidar-labelling/actions/workflows/ci.yml) [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) -lidar-labelling is a tool for automatic segmentation of raw lidar clouds based on image segmentation. +lidar-labelling is a tool for automatic segmentation of dense lidar clouds based on image segmentation. Our labelling algorithm consists of two stages. -The first stage is a preliminary segmentation - a naive transfer of segmentation from images (performed by the [SAM](https://github.com/facebookresearch/segment-anything) algorithm) to the cloud. Then multi-stage processing of the cloud is performed, which allows us to make the cloud more compact before the final labelling without losing points that are significant for labelling. The preprocessing stages include removing points whose corresponding pixels were not marked on a sequence of images, selection of points close to the sensors, removal of noise, cloud voxelization. +The first stage is a initial segmentation - a naive transfer of segmentation from images (performed by the [SAM](https://github.com/facebookresearch/segment-anything) algorithm) to the cloud. Then multi-stage processing of the cloud is performed, which allows us to make the cloud more compact before the final labelling without losing points that are significant for labelling. The preprocessing stages include removing points whose corresponding pixels were not marked on a sequence of images, selection of points close to the sensors, removal of noise, cloud voxelization. The next stage is segmentation itself. The segmentation criterion in this work is the distance between points, which is calculated through the physical distance and the degree of similarity of the labelling of points on several images. Based on the distance matrix, the prepared cloud is segmented using the [GraphCut](https://ieeexplore.ieee.org/abstract/document/937505) algorithm. From 542545e20e67e7e17b1f32d916015669b4f54540 Mon Sep 17 00:00:00 2001 From: SVivdich02 Date: Sat, 1 Jun 2024 11:07:36 +0300 Subject: [PATCH 20/21] fixes --- experiment/main_calc_metrics_by_csv.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/experiment/main_calc_metrics_by_csv.py b/experiment/main_calc_metrics_by_csv.py index 49138be..0eb48cf 100644 --- a/experiment/main_calc_metrics_by_csv.py +++ b/experiment/main_calc_metrics_by_csv.py @@ -65,7 +65,7 @@ def calculate_metrics(file_name): def main(): - calculate_metrics("experiment_hdbscan_50.csv") + calculate_metrics("experiment_50.csv") if __name__ == "__main__": From afef3db573a3430bc305ea7a4da014c327487d1b Mon Sep 17 00:00:00 2001 From: SVivdich02 Date: Sat, 1 Jun 2024 11:20:36 +0300 Subject: [PATCH 21/21] fixes --- example.ipynb | 7 ---- example_gt.ipynb | 7 ---- main.py | 102 ----------------------------------------------- 3 files changed, 116 deletions(-) delete mode 100644 main.py diff --git a/example.ipynb b/example.ipynb index 147e2ea..9016091 100644 --- a/example.ipynb +++ b/example.ipynb @@ -285,13 +285,6 @@ "pcd_colored = color_pcd_by_clusters_and_voxels(pcd_for_clustering, trace, clusters)\n", "visualize_pcd(pcd_colored)" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { diff --git a/example_gt.ipynb b/example_gt.ipynb index aebb952..35f6b44 100644 --- a/example_gt.ipynb +++ b/example_gt.ipynb @@ -466,13 +466,6 @@ ")\n", "visualize_pcd(colored_pcd_for_clustering)" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { diff --git a/main.py b/main.py deleted file mode 100644 index 6d632f1..0000000 --- a/main.py +++ /dev/null @@ -1,102 +0,0 @@ -# Copyright (c) 2023, Sofia Vivdich and Anastasiia Kornilova -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import copy -import numpy as np -import open3d as o3d - -from scipy.spatial.distance import cdist - -from src.datasets.kitti_dataset import KittiDataset - -from src.services.normalized_cut_service import normalized_cut - -from src.services.preprocessing.common.config import ConfigDTO -from src.services.preprocessing.init.map import InitMapProcessor -from src.services.preprocessing.init.instances_matrix import ( - InitInstancesMatrixProcessor, -) -from src.services.preprocessing.not_zero import SelectionNotZeroProcessor -from src.services.preprocessing.in_cube import SelectionInCubeProcessor -from src.services.preprocessing.statistical_outlier import StatisticalOutlierProcessor -from src.services.preprocessing.voxel_down import VoxelDownProcessor - -from src.utils.distances_utils import remove_isolated_points -from src.utils.distances_utils import sam_label_distance -from src.utils.pcd_utils import color_pcd_by_clusters_and_voxels - - -def main(): - dataset_path = "dataset/" - sequence = "00" - image_instances_path = "pipeline/vfm-labels/sam/00/" - kitti = KittiDataset(dataset_path, sequence, image_instances_path) - - config = ConfigDTO( - **{ - "dataset": kitti, - "start_index": 19, - "end_index": 23, - "start_image_index_offset": 3, - "cam_name": "cam2", - "R": 12, - "nb_neighbors": 30, - "std_ratio": 5.0, - "voxel_size": 0.25, - } - ) - - init_pcd = InitMapProcessor().process(config) - points2instances = InitInstancesMatrixProcessor().process(config, init_pcd) - - processors = [ - SelectionNotZeroProcessor(), - SelectionInCubeProcessor(), - StatisticalOutlierProcessor(), - ] - - pcd = copy.deepcopy(init_pcd) - for processor in processors: - pcd, points2instances = processor.process(config, pcd, points2instances) - - pcd_for_clustering = copy.deepcopy(pcd) - - pcd, points2instances, trace = VoxelDownProcessor().process( - config, pcd, points2instances - ) - - points = np.asarray(pcd.points) - spatial_distance = cdist(points, points) - - dist, masks = sam_label_distance( - points2instances, spatial_distance, proximity_threshold=2, beta=10, alpha=2 - ) - - dist, points, trace = remove_isolated_points(dist, points, trace) - - T = 0.2 - eigenval = 2 - clusters = normalized_cut( - dist, np.array([i for i in range(len(points))], dtype=int), T, eigenval - ) - - pcd_clustered = color_pcd_by_clusters_and_voxels( - pcd_for_clustering, trace, clusters - ) - - o3d.visualization.draw_geometries([pcd_clustered]) - - -if __name__ == "__main__": - main()