Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
geomultisens
specclassify
Commits
af8fbd02
Commit
af8fbd02
authored
Dec 14, 2020
by
Daniel Scheffler
Browse files
Merge branch 'bugfix/fix_threshold' into 'master'
Bugfix/fix threshold Closes
#1
See merge request
!2
parents
d01b5358
87c56346
Pipeline
#16931
passed with stages
in 9 minutes and 42 seconds
Changes
3
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
specclassify/_baseclasses.py
View file @
af8fbd02
...
...
@@ -217,7 +217,8 @@ class _kNN_ImageClassifier(_ImageClassifier):
cmap
=
np
.
argpartition
(
dists
,
k
,
axis
=
2
)[:,
:,
:
k
].
astype
(
np
.
int16
)
dists_min_k
=
np
.
partition
(
dists
,
k
,
axis
=
2
)[:,
:,
:
k
].
astype
(
np
.
float32
)
else
:
cmap
=
np
.
tile
(
np
.
arange
(
dists
.
shape
[
2
]).
reshape
(
1
,
1
,
-
1
),
(
*
dists
.
shape
[:
2
],
1
))
cmap
=
np
.
tile
(
np
.
arange
(
dists
.
shape
[
2
]).
reshape
((
1
,
1
,
-
1
)),
(
*
dists
.
shape
[:
2
],
1
))
dists_min_k
=
dists
# sort cmap by ascending spectral distances
...
...
specclassify/classifiers/sam.py
View file @
af8fbd02
...
...
@@ -79,9 +79,10 @@ class SAM_Classifier(_ImageClassifier):
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
)
return
self
.
_label_unclassified_pixels
(
cmap
=
self
.
cmap
,
label_unclassified
=
label_unclassified
,
threshold
=
threshold
,
distances
=
self
.
angles_deg
)
def
show_angles_histogram
(
self
,
figsize
=
(
10
,
5
),
bins
=
100
,
normed
=
False
):
self
.
_show_distances_histogram
(
self
.
angles_deg
,
self
.
cmap
,
figsize
=
figsize
,
bins
=
bins
,
normed
=
normed
)
...
...
@@ -105,15 +106,3 @@ class kNN_SAM_Classifier(SAM_Classifier, _kNN_ImageClassifier):
cmap
=
self
.
overwrite_cmap_at_nodata_positions
(
cmap
,
imdata
)
return
cmap
.
astype
(
np
.
int16
),
angles_min_k
def
label_unclassified_pixels
(
self
,
label_unclassified
,
threshold
):
# type: (int, Union[str, int, float]) -> GeoArray
cmap_labelled0
=
self
.
_label_unclassified_pixels
(
GeoArray
(
self
.
cmap
[:,
:,
0
],
nodata
=
self
.
cmap
.
nodata
),
label_unclassified
,
threshold
,
self
.
angles_deg
[:,
:,
0
]
)
cmap
=
self
.
cmap
if
label_unclassified
in
cmap_labelled0
[:]:
cmap
[
cmap_labelled0
[:]
==
label_unclassified
]
=
label_unclassified
return
cmap
tests/test_image_classifier.py
View file @
af8fbd02
...
...
@@ -47,9 +47,6 @@ path_testclassifiers = os.path.join(__path__[0], '..', 'tests', 'data', 'classif
path_classifier_zip
=
os
.
path
.
join
(
path_testclassifiers
,
'LR_classifiers.zip'
)
fName_cls
=
'LR_clust50__Landsat-7__ETM+.dill'
test_gA
=
GeoArray
(
np
.
random
.
RandomState
(
0
).
randint
(
0
,
10000
,
(
1010
,
1010
,
6
),
np
.
int16
))
# 6 Landsat-5 bands
test_gA
[:
5
,
0
,
:]
=
-
9999
test_gA
[:
5
,
1
,
3
]
=
-
9999
# get cluster centers
with
zipfile
.
ZipFile
(
path_classifier_zip
,
"r"
)
as
zf
,
tempfile
.
TemporaryDirectory
()
as
td
:
...
...
@@ -65,6 +62,31 @@ test_gA_pure_endmembers = np.zeros((1, cluster_centers.shape[0], cluster_centers
test_gA_pure_endmembers
[:,
:,
:]
=
cluster_centers
# compute test image
def
_get_testIm
(
shape
,
nodataVal
):
# get array full of nodata values
spec
=
np
.
full
(
shape
,
nodataVal
).
reshape
(
shape
[
0
]
*
shape
[
1
],
shape
[
2
])
# fill array with random spectra taken from the cluster centers
for
i
in
range
(
cluster_centers
.
shape
[
0
]):
spec
[
np
.
random
.
randint
(
spec
.
shape
[
0
],
size
=
spec
.
shape
[
0
]
//
10
),
:]
=
\
cluster_centers
[
i
,
:]
# add 10% noise to each spectrum
spec
=
spec
*
np
.
random
.
normal
(
1
,
.
1
,
spec
.
size
).
reshape
(
spec
.
shape
)
# return in desired image dimensions
return
spec
.
reshape
(
shape
)
test_gA
=
GeoArray
(
_get_testIm
(
shape
=
(
1010
,
1010
,
6
),
nodataVal
=-
9999
).
astype
(
np
.
int16
),
nodata
=-
9999
)
# 6 Landsat-5 bands
test_gA
[:
20
,
0
,
:]
=
-
9999
# set 20 pixels to -9999 in all bands
test_gA
[:
20
,
1
,
3
]
=
-
9999
# set 20 pixels to -9999 in fourth band only
class
Test_MinimumDistance_Classifier
(
unittest
.
TestCase
):
def
test_classify
(
self
):
t0
=
time
()
...
...
@@ -123,6 +145,9 @@ class Test_kNN_MinimumDistance_Classifier(unittest.TestCase):
MDC
.
classify
(
test_gA
,
in_nodataVal
=-
9999
,
cmap_nodataVal
=-
9999
,
tiledims
=
(
400
,
200
))
MDC
.
label_unclassified_pixels
(
label_unclassified
=-
1
,
threshold
=
6000
)
# check that there are no unlabelled spectral neighbors with Dist above 6000 (given threshold) in the output
self
.
assertTrue
(
np
.
max
(
MDC
.
euclidian_distance
[
MDC
.
cmap
[:]
>
0
])
<=
6000
)
def
test_label_unclassified_pixels_relative_th
(
self
):
MDC
=
kNN_MinimumDistance_Classifier
(
cluster_centers
,
cluster_labels
,
self
.
n_neighbors
,
CPUs
=
None
)
MDC
.
classify
(
test_gA
,
in_nodataVal
=-
9999
,
cmap_nodataVal
=-
9999
,
tiledims
=
(
400
,
200
))
...
...
@@ -178,6 +203,7 @@ class Test_SAM_Classifier(unittest.TestCase):
class
Test_kNN_SAM_Classifier
(
unittest
.
TestCase
):
# TODO: apply these tests to all classifiers
def
setUp
(
self
)
->
None
:
self
.
n_neighbors
=
5
...
...
@@ -198,16 +224,70 @@ class Test_kNN_SAM_Classifier(unittest.TestCase):
cmap_mp
=
SC
.
classify
(
test_gA_pure_endmembers
,
in_nodataVal
=-
9999
,
cmap_nodataVal
=-
9999
)
self
.
assertTrue
(
np
.
array_equal
(
cmap_mp
[:,
:,
0
].
flatten
(),
cluster_labels
))
def
test_classification_outputs
(
self
):
SC
=
kNN_SAM_Classifier
(
cluster_centers
,
n_neighbors
=
self
.
n_neighbors
,
CPUs
=
1
)
cmap
=
SC
.
classify
(
test_gA
,
in_nodataVal
=
None
,
cmap_nodataVal
=
None
,
tiledims
=
(
400
,
200
))
# check if first 20 pixels in col 0 contain the same cmap value (input image is nodata in all bands there)
vals
=
np
.
unique
(
cmap
[:
20
,
0
,
:])
self
.
assertEqual
(
len
(
vals
),
self
.
n_neighbors
)
# n differnt neighbors
self
.
assertTrue
(
0
<=
min
(
vals
)
<
cluster_centers
.
shape
[
0
])
# cmap values min between 0 and 49
self
.
assertTrue
(
0
<=
max
(
vals
)
<
cluster_centers
.
shape
[
0
])
# cmap values max between 0 and 49
# check if first 20 pixels in col 1 contain the different cmap value (input image has values in some bands)
vals
=
np
.
unique
(
cmap
[:
20
,
1
,
:])
self
.
assertGreater
(
len
(
vals
),
self
.
n_neighbors
)
# n different neighbors
self
.
assertTrue
(
0
<=
min
(
vals
)
<
cluster_centers
.
shape
[
0
])
# cmap values min between 0 and 49
self
.
assertTrue
(
0
<=
max
(
vals
)
<
cluster_centers
.
shape
[
0
])
# cmap values max between 0 and 49
# check if the cmap contains only values between 0 and 49 in the rest of the image
vals
=
np
.
unique
(
cmap
[:,
2
:,
:])
self
.
assertTrue
(
0
<=
min
(
vals
)
<
cluster_centers
.
shape
[
0
])
# cmap values min between 0 and 49
self
.
assertTrue
(
0
<=
max
(
vals
)
<
cluster_centers
.
shape
[
0
])
# cmap values max between 0 and 49
def
test_label_unclassified_pixels_absolute_th
(
self
):
SC
=
kNN_SAM_Classifier
(
cluster_centers
,
n_neighbors
=
self
.
n_neighbors
,
CPUs
=
None
)
SC
.
classify
(
test_gA
,
in_nodataVal
=-
9999
,
cmap_nodataVal
=-
9999
,
tiledims
=
(
400
,
200
))
SC
.
label_unclassified_pixels
(
label_unclassified
=-
1
,
threshold
=
10
)
# check that there are no unlabelled spectral neighbors with SAM above 10 degrees in the output
self
.
assertTrue
(
np
.
max
(
SC
.
angles_deg
[
SC
.
cmap
[:]
>
0
])
<=
10
)
def
test_label_unclassified_pixels_relative_th
(
self
):
SC
=
kNN_SAM_Classifier
(
cluster_centers
,
self
.
n_neighbors
,
CPUs
=
None
)
SC
.
classify
(
test_gA
,
in_nodataVal
=-
9999
,
cmap_nodataVal
=-
9999
,
tiledims
=
(
400
,
200
))
SC
.
label_unclassified_pixels
(
label_unclassified
=-
1
,
threshold
=
'10%'
)
def
test_label_unclassified_pixels_cmapNodataVal_given
(
self
):
SC
=
kNN_SAM_Classifier
(
cluster_centers
,
n_neighbors
=
self
.
n_neighbors
,
CPUs
=
None
)
SC
.
classify
(
test_gA
,
in_nodataVal
=-
9999
,
cmap_nodataVal
=-
999
,
tiledims
=
(
400
,
200
))
# now label all pixels with SAM above 10 degrees with -1
cmap
=
SC
.
label_unclassified_pixels
(
label_unclassified
=-
1
,
threshold
=
10
)
# check if first 20 pixels in cols 0 and 1 contain only -999
# (nodata pixels in the input image should appear as nodata in the cmap (-999) if cmap_nodataVal=-999)
vals
=
np
.
unique
(
cmap
[:
20
,
:
2
,
:])
self
.
assertEqual
(
len
(
vals
),
1
)
self
.
assertEqual
(
vals
[
0
],
-
999
)
# check if there are pixels in the rest of the image that are labelled as unclassified
vals
=
np
.
unique
(
cmap
[:,
2
:,
:])
self
.
assertTrue
(
-
1
in
vals
)
def
test_label_unclassified_pixels_cmapNodataVal_not_given
(
self
):
SC
=
kNN_SAM_Classifier
(
cluster_centers
,
n_neighbors
=
self
.
n_neighbors
,
CPUs
=
None
)
SC
.
classify
(
test_gA
,
in_nodataVal
=-
9999
,
cmap_nodataVal
=
None
,
tiledims
=
(
400
,
200
))
# now label all pixels with SAM above 10 degrees with -1
cmap
=
SC
.
label_unclassified_pixels
(
label_unclassified
=-
1
,
threshold
=
10
)
# check if first 20 pixels in cols 0 and 1 contain only -1
# (nodata pixels in the input image should appear as unclassified in the cmap (-1) if cmap_nodataVal=None)
vals
=
np
.
unique
(
cmap
[:
20
,
:
2
,
:])
self
.
assertEqual
(
len
(
vals
),
1
)
self
.
assertEqual
(
vals
[
0
],
-
1
)
class
Test_FEDSA_Classifier
(
unittest
.
TestCase
):
def
test_classify
(
self
):
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment