From cadc3f2815abba7e97cddadfa66ca54774fef72a Mon Sep 17 00:00:00 2001 From: Maciej Wielgosz <maciej.wielgosz@nibio.no> Date: Wed, 21 Dec 2022 16:58:16 +0100 Subject: [PATCH] update in sem seg metric + helper scripts --- .../get_terrestial_validation_few_samples.sh | 10 +++ .../get_val_corrected_few_samples.sh | 12 ++++ metrics/metrics_sem_seg.py | 65 ++++++++++--------- 3 files changed, 58 insertions(+), 29 deletions(-) create mode 100755 bash_helper_scripts/get_terrestial_validation_few_samples.sh create mode 100755 bash_helper_scripts/get_val_corrected_few_samples.sh diff --git a/bash_helper_scripts/get_terrestial_validation_few_samples.sh b/bash_helper_scripts/get_terrestial_validation_few_samples.sh new file mode 100755 index 0000000..d7466f7 --- /dev/null +++ b/bash_helper_scripts/get_terrestial_validation_few_samples.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +TARGET_FOLDER=/home/nibio/mutable-outside-world/code/gitlab_fsct/instance_segmentation_classic/maciek +# clean the folder +rm -rf $TARGET_FOLDER/* + +cp -r /home/nibio/mutable-outside-world/data/terestial_data_for_training_sem_seg_model/validation/burum_2_tile_-100_0.las $TARGET_FOLDER +cp -r /home/nibio/mutable-outside-world/data/terestial_data_for_training_sem_seg_model/validation/plot82_tile_-25_0.las $TARGET_FOLDER +cp -r /home/nibio/mutable-outside-world/data/terestial_data_for_training_sem_seg_model/validation/plot72_tile_-25_0.las $TARGET_FOLDER + diff --git a/bash_helper_scripts/get_val_corrected_few_samples.sh b/bash_helper_scripts/get_val_corrected_few_samples.sh new file mode 100755 index 0000000..cc31bc1 --- /dev/null +++ b/bash_helper_scripts/get_val_corrected_few_samples.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +TARGET_FOLDER=/home/nibio/mutable-outside-world/code/gitlab_fsct/instance_segmentation_classic/maciek +# clean the folder +rm -rf $TARGET_FOLDER/* + +cp -r /home/nibio/mutable-outside-world/data/corrected/validation/burum2_tile_-100_0.las $TARGET_FOLDER +cp -r /home/nibio/mutable-outside-world/data/corrected/validation/Plot89_tile_-25_0.las $TARGET_FOLDER +cp -r /home/nibio/mutable-outside-world/data/corrected/validation/plot82_tile_-25_0.las $TARGET_FOLDER +# cp -r /home/nibio/mutable-outside-world/data/corrected/validation/Plot104_tile_-25_0.las $TARGET_FOLDER + + diff --git a/metrics/metrics_sem_seg.py b/metrics/metrics_sem_seg.py index 19a737a..b93e7e8 100644 --- a/metrics/metrics_sem_seg.py +++ b/metrics/metrics_sem_seg.py @@ -4,9 +4,7 @@ from joblib import Parallel, delayed import laspy from matplotlib import pyplot as plt import numpy as np -# from sklearn.neighbors import NearestNeighbors from sklearn.neighbors import KDTree -from tqdm import tqdm from sklearn.metrics import ConfusionMatrixDisplay, confusion_matrix, f1_score, precision_score, recall_score @@ -47,41 +45,40 @@ class MetricSemSeg: # sort the list in place file_name_list_original.sort() - # get the list of the core names of the original point clouds - # file_name_list_original_core = [] - # for file_name in file_name_list_original: - # file_name_list_original_core.append(os.path.basename(file_name).split('.')[0]) + # get the files which have the same core name as the original point clouds + file_name_list_original_core = [] + for file_name in file_name_list_original: + file_name_list_original_core.append(os.path.basename(file_name).split('.')[0]) # get list of the predicted point clouds file_name_list_predicted = [] for file in os.listdir(self.pred_folder): - if file.endswith(".las"): - file_name_list_predicted.append(os.path.join(self.pred_folder, file)) + # get files which have the same core name as the original point clouds and suffix of '.segmented' + if os.path.basename(file).split('.')[0] in file_name_list_original_core and os.path.basename(file).split('.')[1] == 'segmented': + print("processing file {}".format(file)) + # check is the file is a las file + if file.endswith(".las"): + file_name_list_predicted.append(os.path.join(self.pred_folder, file)) + # check if the file is a ply file and there is no las file with the same core name + elif file.endswith(".ply") and (os.path.basename(file).split('.')[0] + '.segmented.las' not in os.listdir(self.pred_folder)): + # if not convert it to las file + file_name = os.path.join(self.pred_folder, file) + file_name_las = os.path.basename(file).split('.')[0] + '.segmented.las' + file_name_las = os.path.join(self.pred_folder, file_name_las) + if self.verbose: + print("converting {} to las file".format(file)) + os.system("pdal translate {} {} --writers.las.dataformat_id=3 --writers.las.extra_dims=all".format(file_name, file_name_las)) + file_name_list_predicted.append(file_name_las) + + # remove double files + file_name_list_predicted = list(set(file_name_list_predicted)) # sort the list in place file_name_list_predicted.sort() # check if the number of files in the two folders is the same if len(file_name_list_original) != len(file_name_list_predicted): - raise Exception('The number of files in the two folders is not the same.') - - # get core names of ground truth point clouds - file_name_list_original_core = [] - for file_name in file_name_list_original: - file_name_list_original_core.append(os.path.basename(file_name).split('.')[0]) - - # get core names of predicted point clouds - file_name_list_predicted_core = [] - for file_name in file_name_list_predicted: - file_name_list_predicted_core.append(os.path.basename(file_name).split('.')[0]) - - # remove the suffix of '.segmented' from the predicted point clouds - file_name_list_predicted_core = [file_name.split('.')[0] for file_name in file_name_list_predicted_core] - - # compare the two lists and check if they are the same - if file_name_list_original_core != file_name_list_predicted_core: - raise ValueError("The two lists of point clouds are not the same") - + raise ValueError("The two folders do not have the same number of files") # zip the two lists file_name_list = list(zip(file_name_list_original, file_name_list_predicted)) @@ -166,7 +163,7 @@ class MetricSemSeg: labels_original_closest = labels_original[indices] # get the confusion matrix - conf_matrix = np.round(confusion_matrix(labels_original_closest, labels_predicted, normalize='false'), decimals=2) + conf_matrix = np.round(confusion_matrix(labels_original_closest, labels_predicted, normalize='true'), decimals=2) # if conf_matrix.shape[0] == 3 add diagonal elements to make it 4x4 at dimension 2 if conf_matrix.shape[0] == 3: @@ -187,7 +184,7 @@ class MetricSemSeg: class_names = ['terrain', 'vegetation', 'CWD', 'stem'] disp = ConfusionMatrixDisplay(confusion_matrix=conf_matrix, display_labels=class_names) disp.plot() - plt.savefig('confusion_matrix.png') + plt.savefig(file_name_original + '_confusion_matrix.png') # compute precision, recall and f1 score using sklearn.metrics precision = precision_score(labels_original_closest, labels_predicted, average='weighted') @@ -260,6 +257,16 @@ class MetricSemSeg: # compute the mean of the confusion matrix conf_matrix_mean = np.mean(conf_matrix_list, axis=0) + # save the confusion matrix + if self.plot_confusion_matrix: + if conf_matrix_mean.shape[0] == 3: + class_names = ['terrain', 'vegetation', 'stem'] + elif conf_matrix_mean.shape[0] == 4: + class_names = ['terrain', 'vegetation', 'CWD', 'stem'] + disp = ConfusionMatrixDisplay(confusion_matrix=conf_matrix_mean, display_labels=class_names) + disp.plot() + plt.savefig('confusion_matrix_mean.png') + # compute the mean of the precision, recall and f1 score precision_mean = np.mean(precision_list) recall_mean = np.mean(recall_list) -- GitLab