Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
inovisao
pynovisao
Commits
298009a8
Commit
298009a8
authored
Jul 02, 2018
by
Geazy Menezes
Browse files
grafical confusion matrix(cnn support) and fix feature extraction selectors
parent
072d35cb
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
90 additions
and
44 deletions
+90
-44
src/classification/cnn_keras.py
src/classification/cnn_keras.py
+37
-6
src/extraction/__init__.py
src/extraction/__init__.py
+3
-4
src/pynovisao.py
src/pynovisao.py
+48
-32
src/util/utils.py
src/util/utils.py
+2
-2
No files found.
src/classification/cnn_keras.py
View file @
298009a8
...
...
@@ -26,6 +26,9 @@ from keras.models import Model, load_model
from
keras.layers
import
Dropout
,
Flatten
,
Dense
from
keras.callbacks
import
ModelCheckpoint
,
TensorBoard
from
keras
import
backend
as
K
from
numpy
import
resize
,
expand_dims
from
keras.preprocessing.image
import
load_img
,
img_to_array
from
interface.interface
import
InterfaceException
as
IException
from
classification.classifier
import
Classifier
...
...
@@ -35,7 +38,7 @@ from collections import OrderedDict
from
util.config
import
Config
from
util.file_utils
import
File
from
util.utils
import
TimeUtils
logger
=
logging
.
getLogger
(
'PIL'
)
logger
.
setLevel
(
logging
.
WARNING
)
...
...
@@ -49,6 +52,13 @@ START_TIME = time.time()
IMG_WIDTH
,
IMG_HEIGHT
=
256
,
256
weight_path
=
None
dict_preprocessing
=
{}
dict_preprocessing
[
0
]
=
applications
.
xception
.
preprocess_input
,
applications
.
xception
.
decode_predictions
dict_preprocessing
[
1
]
=
applications
.
vgg16
.
preprocess_input
,
applications
.
vgg16
.
decode_predictions
dict_preprocessing
[
2
]
=
applications
.
vgg19
.
preprocess_input
,
applications
.
vgg19
.
decode_predictions
dict_preprocessing
[
3
]
=
applications
.
resnet50
.
preprocess_input
,
applications
.
resnet50
.
decode_predictions
dict_preprocessing
[
4
]
=
applications
.
inception_v3
.
preprocess_input
,
applications
.
inception_v3
.
decode_predictions
dict_preprocessing
[
5
]
=
applications
.
mobilenet
.
preprocess_input
,
applications
.
mobilenet
.
decode_predictions
class
CNNKeras
(
Classifier
):
""" Class for CNN classifiers based on Keras applications """
...
...
@@ -201,6 +211,7 @@ class CNNKeras(Classifier):
except
Exception
,
e
:
print
e
else
:
print
File
.
make_path
(
predict_directory
,
file
)
os
.
symlink
(
File
.
make_path
(
predict_directory
,
file
),
File
.
make_path
(
predict_directory
,
'png'
,
file
))
...
...
@@ -208,7 +219,7 @@ class CNNKeras(Classifier):
classify_generator
=
classify_datagen
.
flow_from_directory
(
File
.
make_path
(
predict_directory
,
'png'
),
ta
rg
et_size
=
(
IMG_HEIGHT
,
IMG_WIDTH
),
taet_size
=
(
IMG_HEIGHT
,
IMG_WIDTH
),
batch_size
=
1
,
shuffle
=
False
,
class_mode
=
None
)
...
...
@@ -333,21 +344,27 @@ class CNNKeras(Classifier):
def
select_model_params
(
self
,
num_classes
):
if
self
.
fine_tuning_rate
.
value
!=
-
1
:
if
self
.
architecture
.
value
==
"Xception"
:
self
.
app
=
0
model
=
applications
.
Xception
(
weights
=
"imagenet"
,
include_top
=
False
,
input_shape
=
(
IMG_WIDTH
,
IMG_HEIGHT
,
3
))
elif
self
.
architecture
.
value
==
"VGG16"
:
self
.
app
=
1
model
=
applications
.
VGG16
(
weights
=
"imagenet"
,
include_top
=
False
,
input_shape
=
(
IMG_WIDTH
,
IMG_HEIGHT
,
3
))
elif
self
.
architecture
.
value
==
"VGG19"
:
self
.
app
=
2
model
=
applications
.
VGG19
(
weights
=
"imagenet"
,
include_top
=
False
,
input_shape
=
(
IMG_WIDTH
,
IMG_HEIGHT
,
3
))
elif
self
.
architecture
.
value
==
"ResNet50"
:
self
.
app
=
3
model
=
applications
.
ResNet50
(
weights
=
"imagenet"
,
include_top
=
False
,
input_shape
=
(
IMG_WIDTH
,
IMG_HEIGHT
,
3
))
elif
self
.
architecture
.
value
==
"InceptionV3"
:
self
.
app
=
4
model
=
applications
.
InceptionV3
(
weights
=
"imagenet"
,
include_top
=
False
,
input_shape
=
(
IMG_WIDTH
,
IMG_HEIGHT
,
3
))
elif
self
.
architecture
.
value
==
"MobileNet"
:
self
.
app
=
5
model
=
applications
.
MobileNet
(
weights
=
"imagenet"
,
include_top
=
False
,
input_shape
=
(
IMG_WIDTH
,
IMG_HEIGHT
,
3
))
...
...
@@ -356,21 +373,27 @@ class CNNKeras(Classifier):
else
:
# without transfer learning
if
self
.
architecture
.
value
==
"Xception"
:
self
.
app
=
0
model
=
applications
.
Xception
(
weights
=
None
,
include_top
=
False
,
input_shape
=
(
IMG_WIDTH
,
IMG_HEIGHT
,
3
))
elif
self
.
architecture
.
value
==
"VGG16"
:
self
.
app
=
1
model
=
applications
.
VGG16
(
weights
=
None
,
include_top
=
False
,
input_shape
=
(
IMG_WIDTH
,
IMG_HEIGHT
,
3
))
elif
self
.
architecture
.
value
==
"VGG19"
:
self
.
app
=
2
model
=
applications
.
VGG19
(
weights
=
None
,
include_top
=
False
,
input_shape
=
(
IMG_WIDTH
,
IMG_HEIGHT
,
3
))
elif
self
.
architecture
.
value
==
"ResNet50"
:
self
.
app
=
3
model
=
applications
.
ResNet50
(
weights
=
None
,
include_top
=
False
,
input_shape
=
(
IMG_WIDTH
,
IMG_HEIGHT
,
3
))
elif
self
.
architecture
.
value
==
"InceptionV3"
:
self
.
app
=
4
model
=
applications
.
InceptionV3
(
weights
=
None
,
include_top
=
False
,
input_shape
=
(
IMG_WIDTH
,
IMG_HEIGHT
,
3
))
elif
self
.
architecture
.
value
==
"MobileNet"
:
self
.
app
=
5
model
=
applications
.
MobileNet
(
weights
=
None
,
include_top
=
False
,
input_shape
=
(
IMG_WIDTH
,
IMG_HEIGHT
,
3
))
for
layer
in
model
.
layers
:
...
...
@@ -456,6 +479,9 @@ class CNNKeras(Classifier):
img
.
save
(
File
.
make_path
(
dir_class_train
,
new_file
),
"PNG"
,
quality
=
100
)
else
:
print
100
*
'-'
print
File
.
make_path
(
root
,
file
)
print
100
*
'-'
os
.
symlink
(
File
.
make_path
(
root
,
file
),
File
.
make_path
(
dir_class_train
,
file
))
...
...
@@ -524,7 +550,12 @@ class CNNKeras(Classifier):
return
train_generator
,
validation_generator
,
test_generator
def
single_classify
(
self
,
image_path
,
directory
,
extractors
,
dict_classes
):
from
matplotlib.pylab
import
imread
image
=
imread
(
image_path
)
predict
=
self
.
model
.
predict
([
image
])[
0
]
return
dict_classes
[
predict
]
\ No newline at end of file
preprocess_input
,
decode_predictions
=
dict_preprocessing
[
self
.
app
]
pil_image
=
load_img
(
image_path
)
np_image
=
img_to_array
(
pil_image
)
res_image
=
resize
(
np_image
,
(
IMG_HEIGHT
,
IMG_WIDTH
,
3
))
tensor
=
expand_dims
(
res_image
,
axis
=
0
)
tensor
=
preprocess_input
(
tensor
)
predict
=
self
.
model
.
predict
(
tensor
)
predict
=
np
.
argmax
(
predict
,
axis
=
1
)
return
dict_classes
[
predict
[
0
]]
src/extraction/__init__.py
View file @
298009a8
...
...
@@ -13,7 +13,7 @@ __all__ = ["extractor",
"hog"
,
"image_moments"
,
"lbp"
,
"gabor"
]
"gabor"
]
from
collections
import
OrderedDict
...
...
@@ -24,11 +24,10 @@ _extractor_list = OrderedDict( [
[
"color_summarizer"
,
Config
(
"Color Statistics"
,
True
,
bool
,
meta
=
ColorStats
)],
[
"glcm"
,
Config
(
"Gray-Level Co-Occurrence Matrix"
,
True
,
bool
,
meta
=
GLCM
)],
[
"hog"
,
Config
(
"Histogram of Oriented Gradients"
,
True
,
bool
,
meta
=
HOG
)],
[
"hu_moments"
,
Config
(
"Hu Image Moments"
,
Fals
e
,
bool
,
meta
=
HuMoments
)],
[
"rc_moments"
,
Config
(
"Image Moments (Raw/Central)"
,
Fals
e
,
bool
,
meta
=
RawCentralMoments
)],
[
"hu_moments"
,
Config
(
"Hu Image Moments"
,
Tru
e
,
bool
,
meta
=
HuMoments
)],
[
"rc_moments"
,
Config
(
"Image Moments (Raw/Central)"
,
Tru
e
,
bool
,
meta
=
RawCentralMoments
)],
[
"lbp"
,
Config
(
"Local Binary Patterns"
,
True
,
bool
,
meta
=
LBP
)],
[
"gabor"
,
Config
(
"Gabor Filter Bank"
,
True
,
bool
,
meta
=
GABOR
)]
]
)
def
get_extractor_config
():
...
...
src/pynovisao.py
View file @
298009a8
...
...
@@ -416,10 +416,10 @@ class Act(object):
self
.
extractors
=
[
new_config
[
extractor
].
meta
for
extractor
in
new_config
if
new_config
[
extractor
].
value
==
True
]
if
len
(
self
.
extractors
)
==
0
:
raise
IException
(
"Please select at least one extractor"
)
self
.
tk
.
append_log
(
"
\n
Config updated:
\n
%s"
,
'
\n
'
.
join
([
"%s: %s"
%
(
new_config
[
extractor
].
label
,
"on"
if
new_config
[
extractor
].
value
==
True
else
"off"
)
for
extractor
in
new_config
]))
...
...
@@ -945,44 +945,52 @@ class Act(object):
def
run_grafic_confusion_matrix
(
self
):
'''
Generate a a graphical confusion matrix where images are classified and according to classification go to the wrong or right folder.
Just Available to WekaClassifier and CNNKeras.
'''
from
classification
import
WekaClassifiers
if
not
isinstance
(
self
.
classifier
,
WekaClassifiers
):
message
=
'Only available to Weka Classifiers.'
IException
(
message
)
from
classification
import
WekaClassifiers
,
CNNKeras
is_weka
=
isinstance
(
self
.
classifier
,
WekaClassifiers
)
is_keras
=
isinstance
(
self
.
classifier
,
CNNKeras
)
if
not
(
is_weka
or
is_keras
):
message
=
'Only available to Weka and CNN Keras classifiers.'
raise
IException
(
message
)
if
not
self
.
has_trained
:
message
=
'Dataset Must Be Trained.'
IException
(
message
)
raise
IException
(
message
)
from
os.path
import
abspath
from
os.path
import
abspath
,
isdir
directory
=
self
.
tk
.
utils
.
ask_directory
()
if
not
directory
:
message
=
'No directory
selected
.'
IException
(
message
)
folder
=
self
.
tk
.
utils
.
ask_directory
()
if
not
folder
:
message
=
'No
selected
directory.'
raise
IException
(
message
)
return
directory
=
abspath
(
directory
)
folder
=
abspath
(
folder
)
dataset
=
abspath
(
self
.
dataset
)
if
directory
==
self
.
dataset
:
if
folder
==
self
.
dataset
:
title
=
'Same Dataset'
message
=
'The dataset selected is the same of the trained. Are you sure that is right?'
option
=
self
.
tk
.
ask_ok_cancel
(
title
,
message
)
if
not
option
:
return
from
os
import
listdir
,
mkdir
listdirs
=
listdir
(
folder
)
size_dirs
=
reduce
(
lambda
a
,
b
:
a
+
b
,
[
0
]
+
[
len
(
listdir
(
folder
+
'/'
+
d
))
for
d
in
listdirs
if
isdir
(
folder
+
'/'
+
d
)])
if
not
size_dirs
:
message
=
'Dataset has no content or the subfolder has no content.'
raise
IException
(
message
)
from
shutil
import
rmtree
from
os
import
mkdir
,
listdir
from
os.path
import
isdir
from
os
import
symlink
def
create_folder_struct
(
matrix_path
,
class_names
,
human
,
computer
):
try
:
rmtree
(
matrix_path
)
except
Exception
as
e
:
print
str
(
e
)
pass
mkdir
(
matrix_path
,
0777
)
for
class_
in
class_names
:
...
...
@@ -991,13 +999,15 @@ class Act(object):
for
_class
in
class_names
:
mkdir
(
real
+
computer
+
_class
,
0777
)
index
=
directory
[
-
2
::
-
1
].
index
(
'/'
)
matrix_path
=
directory
[:
-
(
index
+
1
)]
+
'folder_confusion_matrix'
class_names
,
classes
=
listdir
(
directory
),
{}
header_output
=
'Starting Graphical Confusion Matrix
\n\n
'
index
=
folder
[
-
2
::
-
1
].
index
(
'/'
)
matrix_path
=
folder
[:
-
(
index
+
1
)]
+
'folder_confusion_matrix'
class_names
,
classes
=
listdir
(
folder
),
{}
for
i
in
range
(
len
(
class_names
)
-
1
,
-
1
,
-
1
):
if
isdir
(
dataset
+
'/'
+
class_names
[
i
]):
if
class_names
[
i
][
0
]
is
not
'.'
:
if
class_names
[
i
][
0
]
!=
'.'
:
continue
del
class_names
[
i
]
for
i
,
name
in
enumerate
(
class_names
):
...
...
@@ -1005,21 +1015,27 @@ class Act(object):
images
=
[]
for
classe
in
class_names
:
image_names
=
listdir
(
directory
+
'/'
+
classe
)
image_names
=
listdir
(
folder
+
'/'
+
classe
)
for
i
in
range
(
len
(
image_names
)):
image_names
[
i
]
=
directory
+
'/'
,
classe
,
'/'
+
image_names
[
i
]
image_names
[
i
]
=
folder
+
'/'
,
classe
,
'/'
+
image_names
[
i
]
images
.
extend
(
image_names
)
human
,
computer
=
'/human_'
,
'/computer_'
create_folder_struct
(
matrix_path
,
class_names
,
human
,
computer
)
for
image_path
in
images
:
original
=
reduce
(
lambda
a
,
b
:
a
+
b
,
image_path
)
header_output_middle
=
header_output
+
'Dataset selected: '
+
folder
+
'
\n\n
'
self
.
tk
.
write_log
(
header_output_middle
+
'Initializing...'
)
total
=
str
(
len
(
images
))
for
i
,
image_path
in
enumerate
(
images
):
original_name
=
reduce
(
lambda
a
,
b
:
a
+
b
,
image_path
)
real_class_path
=
matrix_path
+
human
+
image_path
[
1
]
predicted
=
self
.
classifier
.
single_classify
(
original
,
directory
,
self
.
extractors
,
classes
)
predicted
=
self
.
classifier
.
single_classify
(
original_name
,
folder
,
self
.
extractors
,
classes
)
message
=
header_output_middle
+
str
(
i
+
1
)
+
' of '
+
total
+
' images classifield.'
self
.
tk
.
write_log
(
message
)
predicted_class_path
=
real_class_path
+
computer
+
predicted
name_
predicted
=
predicted_class_path
+
image_path
[
2
]
symlink
(
original
,
name
_
predicted
)
predicted
_name
=
predicted_class_path
+
image_path
[
2
]
symlink
(
original
_
name
,
predicted
_name
)
message
=
'Graphical Confusion Matrix s
aved in '
+
matrix_path
self
.
tk
.
append
_log
(
message
)
message
=
header_output
+
'S
aved in '
+
matrix_path
self
.
tk
.
write
_log
(
message
)
src/util/utils.py
View file @
298009a8
...
...
@@ -374,9 +374,9 @@ class BooleanUtils(object):
@
staticmethod
def
str_to_bool
(
s
):
if
s
==
'True'
:
if
s
==
'True'
or
s
==
1
:
return
True
elif
s
==
'False'
:
elif
s
==
'False'
or
s
==
0
:
return
False
else
:
raise
ValueError
\ No newline at end of file
Write
Preview
Markdown
is supported
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