Commit 5c135584 authored by Daniel Scheffler's avatar Daniel Scheffler
Browse files

Image classifiers MinDist, SAM and SID can now label pixels exceeding a given...


Image classifiers MinDist, SAM and SID can now label pixels exceeding a given distance metric as unclassified.
Signed-off-by: Daniel Scheffler's avatarDaniel Scheffler <danschef@gfz-potsdam.de>
parent 1ca747a1
Pipeline #3884 failed with stage
in 2 minutes and 9 seconds
......@@ -93,6 +93,27 @@ class _ImageClassifier(object):
return self.cmap
@staticmethod
def _label_unclassified_pixels(cmap, label_unclassified, threshold, distances):
# type: (GeoArray, int, Union[str, int, float], np.ndarray) -> GeoArray
assert cmap is not None and distances is not None
assert np.can_cast(label_unclassified, cmap.dtype)
# noinspection PyProtectedMember
cmap_nodataVal = cmap._nodata
if isinstance(threshold, (int, float)):
pass
elif isinstance(threshold, str) and threshold.endswith('%'):
percent = float(threshold.split('%')[0].strip())
dists = distances[cmap != cmap_nodataVal] if cmap_nodataVal is not None else distances
threshold = np.nanpercentile(dists, 100 - percent)
else:
raise ValueError(threshold)
cmap[distances > threshold] = label_unclassified
return cmap
def show_cmap(self):
if self.cmap:
self.cmap.show()
......@@ -147,6 +168,12 @@ class MinimumDistance_Classifier(_ImageClassifier):
return tilepos, cmap, dist
def label_unclassified_pixels(self, label_unclassified, threshold):
# type: (int, Union[str, int, float]) -> GeoArray
return self._label_unclassified_pixels(
self.cmap, label_unclassified, threshold, self.euclidian_distance
)
class kNN_Classifier(_ImageClassifier):
def __init__(self, train_spectra, train_labels, CPUs=1, **kwargs):
......@@ -227,6 +254,12 @@ class SAM_Classifier(_ImageClassifier):
return np.arccos(quotient)
def label_unclassified_pixels(self, label_unclassified, threshold):
# type: (int, Union[str, int, float]) -> GeoArray
return self._label_unclassified_pixels(
self.cmap, label_unclassified, threshold, self.angles_deg
)
class SID_Classifier(_ImageClassifier):
def __init__(self, train_spectra, CPUs=1):
......@@ -286,6 +319,12 @@ class SID_Classifier(_ImageClassifier):
return np.sum(p * np.log(p / q) + q * np.log(q / p), axis=axis)
def label_unclassified_pixels(self, label_unclassified, threshold):
# type: (int, Union[str, int, float]) -> GeoArray
return self._label_unclassified_pixels(
self.cmap, label_unclassified, threshold, self.sid
)
class RF_Classifier(_ImageClassifier):
"""Random forest classifier."""
......
......@@ -82,6 +82,13 @@ class Test_SAM_Classifier(unittest.TestCase):
self.assertTrue(np.array_equal(cmap_sp, cmap_mp))
def test_label_unclassified_pixels(self):
SC = SAM_Classifier(cluster_centers, CPUs=None)
SC.classify(test_gA, in_nodataVal=-9999, tiledims=(400, 200))
SC.label_unclassified_pixels(label_unclassified=-1, threshold=10)
SC.label_unclassified_pixels(label_unclassified=-1, threshold='10%')
class Test_SID_Classifier(unittest.TestCase):
def test_classify(self):
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment