Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
bob
bob.bio.vein
Commits
fe2f04c1
Commit
fe2f04c1
authored
Oct 05, 2017
by
André Anjos
💬
Committed by
André Anjos
Oct 12, 2017
Browse files
Add script to help debugging watershedding
parent
483e6b5b
Changes
1
Hide whitespace changes
Inline
Side-by-side
bob/bio/vein/script/watershed_mask.py
0 → 100644
View file @
fe2f04c1
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
# Wed 4 Oct 11:23:52 2017 CEST
"""Preprocesses a fingervein image with a watershed/neural-net seeded mask
Usage: %(prog)s [-v...] [-s <path>] [-f <float>] [-b <float>] [--scan]
<model> <database> [<stem>...]
%(prog)s --help
%(prog)s --version
Arguments:
<model> Path to model to use for find watershed markers
<database> Name of the database to use for creating the model (options are:
"fv3d" or "verafinger")
<stem> Name of the object on the database to display, without the root
or the extension. If none provided, run for all possible stems on
the database
Options:
-h, --help Shows this help message and exits
-V, --version Prints the version and exits
-v, --verbose Increases the output verbosity level
-f, --fg-threshold=<float> Foreground threshold value. Should be set to a
number that is between 0.5 and 1.0. The higher,
the less markers for the foreground watershed
process will be produced. [default: 0.7]
-b, --bg-threshold=<float> Background threshold value. Should be set to a
number that is between 0.0 and 0.5. The smaller,
the less markers for the foreground watershed
process will be produced. [default: 0.3]
-S, --scan If set, ignores settings for the threshold and
scans the whole range of threshold printing the
Jaccard, M1 and M2 merith figures
-s <path>, --save=<path> If set, saves image into a file instead of
displaying it
Examples:
Visualize the preprocessing toolchain over a single image
$ %(prog)s model.hdf5 verafinger sample-stem
Save the results of the preprocessing to a file. In this case, the program
runs non-interactively:
$ %(prog)s -s graphics.png model.hdf5 verafinger sample-stem
Scans the set of possible thresholds printing Jaccard, M1 and M2 indexes:
$ %(prog)s --scan model.hdf5 verafinger sample-stem
"""
import
os
import
sys
import
time
import
numpy
import
schema
import
docopt
import
bob.core
logger
=
bob
.
core
.
log
.
setup
(
"bob.bio.vein"
)
import
matplotlib.pyplot
as
plt
import
bob.io.base
import
bob.io.image
def
validate
(
args
):
'''Validates command-line arguments, returns parsed values
This function uses :py:mod:`schema` for validating :py:mod:`docopt`
arguments. Logging level is not checked by this procedure (actually, it is
ignored) and must be previously setup as some of the elements here may use
logging for outputing information.
Parameters:
args (dict): Dictionary of arguments as defined by the help message and
returned by :py:mod:`docopt`
Returns
dict: Validate dictionary with the same keys as the input and with values
possibly transformed by the validation procedure
Raises:
schema.SchemaError: in case one of the checked options does not validate.
'''
valid_databases
=
(
'fv3d'
,
'verafinger'
)
sch
=
schema
.
Schema
({
'<model>'
:
schema
.
And
(
os
.
path
.
exists
,
error
=
'<model> should point to an existing path'
),
'<database>'
:
schema
.
And
(
lambda
n
:
n
in
valid_databases
,
error
=
'<database> must be one of %s'
%
', '
.
join
(
valid_databases
)),
'--fg-threshold'
:
schema
.
And
(
schema
.
Use
(
float
),
lambda
n
:
0.5
<
n
<
1.0
,
error
=
'--fg-threshold should be a float between 0.5 and 1.0'
,
),
'--bg-threshold'
:
schema
.
And
(
schema
.
Use
(
float
),
lambda
n
:
0.0
<
n
<
0.5
,
error
=
'--bg-threshold should be a float between 0.0 and 0.5'
,
),
str
:
object
,
#ignores strings we don't care about
},
ignore_extra_keys
=
True
)
return
sch
.
validate
(
args
)
def
make_figure
(
image
,
markers
,
edges
,
mask
):
'''Returns a matplotlib figure with the detailed processing result'''
plt
.
clf
()
#completely clears the current figure
figure
=
plt
.
gcf
()
plt
.
subplot
(
2
,
2
,
1
)
_
=
markers
.
copy
().
astype
(
'uint8'
)
_
[
_
==
1
]
=
128
plt
.
imshow
(
_
,
cmap
=
'gray'
)
plt
.
title
(
'Markers'
)
plt
.
subplot
(
2
,
2
,
2
)
_
=
numpy
.
dstack
([
(
_
|
(
2550
*
edges
).
astype
(
'uint8'
)),
_
,
_
,
])
plt
.
imshow
(
_
)
plt
.
title
(
'Edges'
)
plt
.
subplot
(
2
,
2
,
3
)
plt
.
imshow
(
mask
.
astype
(
'uint8'
)
*
255
,
cmap
=
'gray'
)
plt
.
title
(
'Mask'
)
plt
.
subplot
(
2
,
2
,
4
)
plt
.
imshow
(
image
,
cmap
=
'gray'
)
red_mask
=
numpy
.
dstack
([
(
~
mask
).
astype
(
'uint8'
)
*
255
,
numpy
.
zeros_like
(
image
),
numpy
.
zeros_like
(
image
),
])
plt
.
imshow
(
red_mask
,
alpha
=
0.15
)
plt
.
title
(
'Image (masked)'
)
return
figure
def
process_one
(
args
,
image
,
path
):
'''Processes a single image'''
from
bob.bio.vein.preprocessor
import
WatershedMask
,
AnnotatedRoIMask
# loads the processor once - avoids re-reading weights from the disk
processor
=
WatershedMask
(
model
=
args
[
'<model>'
],
foreground_threshold
=
args
[
'--fg-threshold'
],
background_threshold
=
args
[
'--bg-threshold'
],
)
annotator
=
AnnotatedRoIMask
()
from
bob.bio.vein.preprocessor.utils
import
\
jaccard_index
,
intersect_ratio
,
intersect_ratio_of_complement
start
=
time
.
time
()
markers
,
edges
,
mask
=
processor
.
run
(
image
)
total_time
=
time
.
time
()
-
start
# error
annotated_mask
=
annotator
(
image
)
ji
=
jaccard_index
(
annotated_mask
,
mask
)
m1
=
intersect_ratio
(
annotated_mask
,
mask
)
m2
=
intersect_ratio_of_complement
(
annotated_mask
,
mask
)
logger
.
debug
(
'%s, %.2f, %.2f, %.2f, %g, %g, %g'
,
path
,
total_time
,
args
[
'--fg-threshold'
],
args
[
'--bg-threshold'
],
ji
,
m1
,
m2
)
if
not
args
[
'--scan'
]:
fig
=
make_figure
(
image
,
markers
,
edges
,
mask
)
fig
.
suptitle
(
'%s @ %s - JI=%.4f, M1=%.4f, M2=%.4f
\n
'
\
'($
\\
tau_{FG}$ = %.2f - $
\\
tau_{BG}$ = %.2f)'
%
\
(
path
,
args
[
'<database>'
],
ji
,
m1
,
m2
,
args
[
'--fg-threshold'
],
args
[
'--bg-threshold'
]),
fontsize
=
12
)
if
args
[
'--save'
]:
fig
.
savefig
(
args
[
'--save'
])
else
:
print
(
'Close the figure to continue...'
)
plt
.
show
()
return
(
path
,
total_time
,
args
[
'--fg-threshold'
],
args
[
'--bg-threshold'
],
ji
,
m1
,
m2
)
def
eval_best_thresholds
(
results
):
'''Evaluates the best thresholds taking into consideration various indexes'''
m1
=
numpy
.
array
([
k
[
-
2
]
for
k
in
results
])
m2
=
numpy
.
array
([
k
[
-
1
]
for
k
in
results
])
index
=
m1
/
m2
return
index
.
argmax
()
def
main
(
user_input
=
None
):
if
user_input
is
not
None
:
argv
=
user_input
else
:
argv
=
sys
.
argv
[
1
:]
import
pkg_resources
completions
=
dict
(
prog
=
os
.
path
.
basename
(
sys
.
argv
[
0
]),
version
=
pkg_resources
.
require
(
'bob.bio.vein'
)[
0
].
version
)
args
=
docopt
.
docopt
(
__doc__
%
completions
,
argv
=
argv
,
version
=
completions
[
'version'
],
)
try
:
from
.validate
import
setup_logger
logger
=
setup_logger
(
'bob.bio.vein'
,
args
[
'--verbose'
])
args
=
validate
(
args
)
except
schema
.
SchemaError
as
e
:
sys
.
exit
(
e
)
if
args
[
'<database>'
]
==
'fv3d'
:
from
..configurations.fv3d
import
database
as
db
elif
args
[
'<database>'
]
==
'verafinger'
:
from
..configurations.verafinger
import
database
as
db
database_replacement
=
"%s/.bob_bio_databases.txt"
%
os
.
environ
[
"HOME"
]
db
.
replace_directories
(
database_replacement
)
all_files
=
db
.
objects
()
# if a specific <stem> was not provided, run for all possible stems
if
not
args
[
'<stem>'
]:
args
[
'<stem>'
]
=
[
k
.
path
for
k
in
all_files
]
# Loads the image, the mask and save it to a PNG file
for
stem
in
args
[
'<stem>'
]:
f
=
[
k
for
k
in
all_files
if
k
.
path
==
stem
]
if
len
(
f
)
==
0
:
raise
RuntimeError
(
'File with stem "%s" does not exist on "%s"'
%
\
stem
,
args
[
'<database>'
])
f
=
f
[
0
]
image
=
f
.
load
(
db
.
original_directory
,
db
.
original_extension
)
if
args
[
'--scan'
]:
results
=
[]
logger
.
debug
(
'stem, time, fg_thres, bg_thres, jaccard, m1, m2'
)
for
fg_threshold
in
numpy
.
arange
(
0.6
,
1.0
,
step
=
0.1
):
for
bg_threshold
in
numpy
.
arange
(
0.1
,
0.5
,
step
=
0.1
):
args
[
'--fg-threshold'
]
=
fg_threshold
args
[
'--bg-threshold'
]
=
bg_threshold
results
.
append
(
process_one
(
args
,
image
,
f
.
path
))
best_thresholds
=
eval_best_thresholds
(
results
)
logger
.
info
(
'%s: FG = %.2f | BG = %.2f | M1/M2 = %.2f'
,
f
.
path
,
results
[
best_thresholds
][
2
],
results
[
best_thresholds
][
3
],
results
[
best_thresholds
][
-
2
]
/
results
[
best_thresholds
][
-
1
])
else
:
process_one
(
args
,
image
,
f
.
path
)
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a 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