arcgis-python-api icon indicating copy to clipboard operation
arcgis-python-api copied to clipboard

Handling mismatch of point cloud classification labels during PointCNN prediction

Open chenzhaiyu opened this issue 4 years ago • 1 comments

Is your feature request related to a problem? Please describe. Yes. Applying the PointCNN model trained on dataset A, for prediction on dataset B, throws an obscure error, given that the two datasets have mismatched classification labels and the print_metrics=True is provided. Please consider handling the error in a clear way.

Code to reproduce

from arcgis.learn import PointCNN
from arcgis.learn import prepare_data
data_path = r'dataset_a'
data = prepare_data(data_path, dataset_type='PointCloud', batch_size=4)
pointcnn = PointCNN(data, pretrained_path='path_to_pretrained_model_on_dataset_a')
pointcnn.predict_las(path='path_to_dataset_b', print_metrics=True)
# dataset_a and dataset_b have different raw classification label scale (e.g. dataset_a has 8 classes while dataset_b has 5).
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
D:\Softwares\Anaconda\envs\arcgis-api-env\lib\site-packages\laspy\file.py in __getitem__(self, index)
    686         try:
--> 687             index.stop
    688         except AttributeError:

AttributeError: 'int' object has no attribute 'stop'

During handling of the above exception, another exception occurred:

AttributeError                            Traceback (most recent call last)
<ipython-input-6-1a56f93b20e9> in <module>
----> 1 pointcnn.predict_las(path='./eval_3/input', output_path='./eval_3/output', print_metrics=True)

D:\Softwares\Anaconda\envs\arcgis-api-env\lib\site-packages\arcgis\learn\models\_pointcnnseg.py in predict_las(self, path, output_path, print_metrics, **kwargs)
    372         """
    373 
--> 374         return inference_las(path, self, output_path, print_metrics, **kwargs)
    375 
    376     def compute_precision_recall(self):

D:\Softwares\Anaconda\envs\arcgis-api-env\lib\site-packages\arcgis\learn\_utils\pointcloud_data.py in inference_las(path, pointcnn_model, out_path, print_metrics, remap_classes, selective_classify)
   1195                                                                                    print_metrics,
   1196                                                                                    reclassify_classes,
-> 1197                                                                                    selective_classify)
   1198             global_false_positives = np.add(global_false_positives, false_positives)
   1199             global_true_positives = np.add(global_true_positives, true_positives)

D:\Softwares\Anaconda\envs\arcgis-api-env\lib\site-packages\arcgis\learn\_utils\pointcloud_data.py in write_resulting_las(in_las_filename, out_las_filename, labels, num_classes, data, print_metrics, reclassify_classes, selective_classify)
    967     if print_metrics:
    968         for p in f:
--> 969             p = f[i]
    970             current_class = inverse_class_mapping[old_labels[i]]
    971             if reclassify_classes != {}:

D:\Softwares\Anaconda\envs\arcgis-api-env\lib\site-packages\laspy\file.py in __getitem__(self, index)
    687             index.stop
    688         except AttributeError:
--> 689             return self.read(index)
    690 
    691         output = []

D:\Softwares\Anaconda\envs\arcgis-api-env\lib\site-packages\laspy\file.py in read(self, index, nice)
    291         '''Reads the point at the given index'''
    292         if self._reader.get_pointrecordscount() >= index:
--> 293             return(self._reader.get_point(index, nice))
    294         else:
    295             raise util.LaspyException("Index greater than point records count")

D:\Softwares\Anaconda\envs\arcgis-api-env\lib\site-packages\laspy\base.py in get_point(self, index, nice)
    698             return
    699         self._current = index
--> 700         return(laspy.util.Point(self, self.get_raw_point(index), nice= nice))
    701 
    702 

D:\Softwares\Anaconda\envs\arcgis-api-env\lib\site-packages\laspy\util.py in __init__(self, reader, bytestr, unpacked_list, nice)
    399             raise LaspyException("No byte string or attribute list supplied for point.")
    400         if nice:
--> 401             self.make_nice()
    402     def make_nice(self):
    403         '''Turn a point instance with the bare essentials (an unpacked list of data)

D:\Softwares\Anaconda\envs\arcgis-api-env\lib\site-packages\laspy\util.py in make_nice(self)
    415         self.edge_flight_line = self.reader.packed_str(bstr[7])
    416 
--> 417         bstr = self.reader.binary_str(self.raw_classification)
    418         self.classification = self.reader.packed_str(bstr[0:5])
    419         self.synthetic = self.reader.packed_str(bstr[5])

AttributeError: 'Point' object has no attribute 'raw_classification'

Describe the solution you'd like Adding an assertion on the raw classification labels between two datasets at the beginning of prediction.

Describe alternatives you've considered Stating in the documentation that if print_metrics=True is provided, the user has to make sure the two datasets' raw classifications are comparable.

Additional context print_metrics=False works well regardless of the mismatch of class labels.

chenzhaiyu avatar Jul 31 '20 09:07 chenzhaiyu

@chenzhaiyu Thanks for reporting it. cc @vbhv14

priyankatuteja avatar Dec 30 '20 10:12 priyankatuteja

This issue is older and will be closed in an effort to remove stale issues. Please feel free to reopen if needed.

nanaeaubry avatar Sep 16 '22 05:09 nanaeaubry