Skip to content

Commit 9417856

Browse files
committed
updating source code with the latest
1 parent bc89900 commit 9417856

27 files changed

+858
-82
lines changed

odir_image_crop.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2019 Jordi Corbilla. All Rights Reserved.
1+
# Copyright 2019-2020 Jordi Corbilla. All Rights Reserved.
22
#
33
# Licensed under the Apache License, Version 2.0 (the "License");
44
# you may not use this file except in compliance with the License.

odir_image_crop_job.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2019 Jordi Corbilla. All Rights Reserved.
1+
# Copyright 2019-2020 Jordi Corbilla. All Rights Reserved.
22
#
33
# Licensed under the Apache License, Version 2.0 (the "License");
44
# you may not use this file except in compliance with the License.

odir_image_resizer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2019 Jordi Corbilla. All Rights Reserved.
1+
# Copyright 2019-2020 Jordi Corbilla. All Rights Reserved.
22
#
33
# Licensed under the Apache License, Version 2.0 (the "License");
44
# you may not use this file except in compliance with the License.

odir_image_testing_crop_job.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2019 Jordi Corbilla. All Rights Reserved.
1+
# Copyright 2019-2020 Jordi Corbilla. All Rights Reserved.
22
#
33
# Licensed under the Apache License, Version 2.0 (the "License");
44
# you may not use this file except in compliance with the License.

odir_image_treatment.py

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# Copyright 2019-2020 Jordi Corbilla. All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
# ==============================================================================
15+
import numpy as np
16+
import tensorflow as tf
17+
from skimage import exposure
18+
19+
20+
class ImageTreatment:
21+
def __init__(self, image_size):
22+
self.image_size = image_size
23+
24+
def scaling(self, image, scale_vector):
25+
# Resize to 4-D vector
26+
image = np.reshape(image, (1, self.image_size, self.image_size, 3))
27+
boxes = np.zeros((len(scale_vector), 4), dtype=np.float32)
28+
for index, scale in enumerate(scale_vector):
29+
x1 = y1 = 0.5 - 0.5 * scale
30+
x2 = y2 = 0.5 + 0.5 * scale
31+
boxes[index] = np.array([y1, x1, y2, x2], dtype=np.float32)
32+
box_ind = np.zeros((len(scale_vector)), dtype=np.int32)
33+
crop_size = np.array([self.image_size, self.image_size], dtype=np.int32)
34+
35+
output = tf.image.crop_and_resize(image, boxes, box_ind, crop_size)
36+
output = np.array(output, dtype=np.uint8)
37+
return output
38+
39+
def brightness(self, image, delta):
40+
output = tf.image.adjust_brightness(image, delta)
41+
output = np.array(output, dtype=np.uint8)
42+
return output
43+
44+
def contrast(self, image, contrast_factor):
45+
output = tf.image.adjust_contrast(image, contrast_factor)
46+
output = np.array(output, dtype=np.uint8)
47+
return output
48+
49+
def saturation(self, image, saturation_factor):
50+
output = tf.image.adjust_saturation(image, saturation_factor)
51+
output = np.array(output, dtype=np.uint8)
52+
return output
53+
54+
def hue(self, image, delta):
55+
output = tf.image.adjust_hue(image, delta)
56+
output = np.array(output, dtype=np.uint8)
57+
return output
58+
59+
def central_crop(self, image, central_fraction):
60+
output = tf.image.central_crop(image, central_fraction)
61+
output = np.array(output, dtype=np.uint8)
62+
return output
63+
64+
def crop_to_bounding_box(self, image, offset_height, offset_width, target_height, target_width):
65+
output = tf.image.crop_to_bounding_box(image, offset_height, offset_width, target_height, target_width)
66+
output = tf.image.resize(output, (self.image_size, self.image_size))
67+
output = np.array(output, dtype=np.uint8)
68+
return output
69+
70+
def gamma(self, image, gamma):
71+
output = tf.image.adjust_gamma(image, gamma)
72+
output = np.array(output, dtype=np.uint8)
73+
return output
74+
75+
def rot90(self, image, k):
76+
output = tf.image.rot90(image, k)
77+
output = np.array(output, dtype=np.uint8)
78+
return output
79+
80+
def rescale_intensity(self, image):
81+
p2, p98 = np.percentile(image, (2, 98))
82+
img_rescale = exposure.rescale_intensity(image, in_range=(p2, p98))
83+
return img_rescale
84+
85+
def equalize_histogram(self, image):
86+
img_eq = exposure.equalize_hist(image)
87+
return img_eq
88+
89+
def equalize_adapthist(self, image):
90+
img_adapted = exposure.equalize_adapthist(image, clip_limit=0.03)
91+
return img_adapted

odir_inception_testing_inference.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# Copyright 2019 Jordi Corbilla. All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
# ==============================================================================
15+
from __future__ import absolute_import, division, print_function, unicode_literals
16+
17+
import logging.config
18+
import tensorflow as tf
19+
from absl import app
20+
from odir_advance_plotting import Plotter
21+
from odir_kappa_score import FinalScore
22+
from odir_normalize_input import Normalizer
23+
from odir_predictions_writer import Prediction
24+
import odir
25+
26+
def main(argv):
27+
print(tf.version.VERSION)
28+
image_size = 224
29+
test_run = 'zC'
30+
31+
# load the data
32+
(x_train, y_train), (x_test, y_test) = odir.load_data(image_size, 1)
33+
34+
class_names = ['Normal', 'Diabetes', 'Glaucoma', 'Cataract', 'AMD', 'Hypertension', 'Myopia', 'Others']
35+
36+
# plot data input
37+
plotter = Plotter(class_names)
38+
plotter.plot_input_images(x_train, y_train)
39+
40+
x_test_drawing = x_test
41+
42+
# normalize input based on model
43+
normalizer = Normalizer()
44+
x_test = normalizer.normalize_vgg16(x_test)
45+
46+
# load one of the test runs
47+
model = tf.keras.models.load_model(r'C:\Users\thund\Source\Repos\TFM-ODIR\models\image_classification\modelvgg100.h5')
48+
model.summary()
49+
50+
# display the content of the model
51+
baseline_results = model.evaluate(x_test, y_test, verbose=2)
52+
for name, value in zip(model.metrics_names, baseline_results):
53+
print(name, ': ', value)
54+
print()
55+
56+
# test a prediction
57+
test_predictions_baseline = model.predict(x_test)
58+
plotter.plot_confusion_matrix_generic(y_test, test_predictions_baseline, test_run, 0)
59+
60+
# save the predictions
61+
prediction_writer = Prediction(test_predictions_baseline, 400)
62+
prediction_writer.save()
63+
prediction_writer.save_all(y_test)
64+
65+
# show the final score
66+
score = FinalScore()
67+
score.output()
68+
69+
# plot output results
70+
plotter.plot_output(test_predictions_baseline, y_test, x_test_drawing)
71+
72+
73+
if __name__ == '__main__':
74+
# create logger
75+
logging.config.fileConfig('logging.conf')
76+
logger = logging.getLogger('odir')
77+
app.run(main)

odir_kappa_score.py

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,46 @@
1+
# Copyright 2019 Jordi Corbilla. All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
# ==============================================================================
115
import csv
216
import numpy as np
317
from sklearn import metrics
418

5-
def import_data(filepath):
6-
with open(filepath, 'r') as f:
7-
reader = csv.reader(f)
8-
header = next(reader)
9-
pr_data = [[int(row[0])] + list(map(float, row[1:])) for row in reader]
10-
pr_data = np.array(pr_data)
11-
return pr_data
1219

13-
def odir_metrics(gt_data, pr_data):
14-
th = 0.5
15-
gt = gt_data.flatten()
16-
pr = pr_data.flatten()
17-
kappa = metrics.cohen_kappa_score(gt, pr > th)
18-
f1 = metrics.f1_score(gt, pr > th, average='micro')
19-
auc = metrics.roc_auc_score(gt, pr)
20-
final_score = (kappa + f1 + auc) / 3.0
21-
return kappa, f1, auc, final_score
20+
class FinalScore:
21+
def odir_metrics(self, gt_data, pr_data):
22+
th = 0.5
23+
gt = gt_data.flatten()
24+
pr = pr_data.flatten()
25+
kappa = metrics.cohen_kappa_score(gt, pr > th)
26+
f1 = metrics.f1_score(gt, pr > th, average='micro')
27+
auc = metrics.roc_auc_score(gt, pr)
28+
final_score = (kappa + f1 + auc) / 3.0
29+
return kappa, f1, auc, final_score
2230

23-
gt_data = import_data('odir_ground_truth.csv')
24-
pr_data = import_data('odir_predictions.csv')
25-
kappa, f1, auc, final_score = odir_metrics(gt_data[:, 1:], pr_data[:, 1:])
26-
print("kappa score:", kappa, " f-1 score:", f1, " AUC vlaue:", auc, " Final Score:", final_score)
31+
def import_data(self, filepath):
32+
with open(filepath, 'r') as f:
33+
reader = csv.reader(f)
34+
header = next(reader)
35+
pr_data = [[int(row[0])] + list(map(float, row[1:])) for row in reader]
36+
pr_data = np.array(pr_data)
37+
return pr_data
38+
39+
def output(self):
40+
gt_data = self.import_data('odir_ground_truth.csv')
41+
pr_data = self.import_data('odir_predictions.csv')
42+
kappa, f1, auc, final_score = self.odir_metrics(gt_data[:, 1:], pr_data[:, 1:])
43+
print("Kappa score:", kappa)
44+
print("F-1 score:", f1)
45+
print("AUC value:", auc)
46+
print("Final Score:", final_score)

odir_load_ground_truth_files.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Copyright 2019-2020 Jordi Corbilla. All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
# ==============================================================================
15+
import csv
16+
17+
18+
class GroundTruthFiles:
19+
def __init__(self):
20+
self.amd = []
21+
self.cataract = []
22+
self.diabetes = []
23+
self.glaucoma = []
24+
self.hypertension = []
25+
self.myopia = []
26+
self.others = []
27+
28+
def populate_vectors(self, ground_truth_file):
29+
with open(ground_truth_file) as csvDataFile:
30+
csv_reader = csv.reader(csvDataFile)
31+
32+
for row in csv_reader:
33+
column_id = row[0]
34+
normal = row[1]
35+
diabetes = row[2]
36+
glaucoma = row[3]
37+
cataract = row[4]
38+
amd = row[5]
39+
hypertension = row[6]
40+
myopia = row[7]
41+
others = row[8]
42+
# just discard the first row
43+
if column_id != "ID":
44+
print("Processing image: " + column_id + "_left.jpg")
45+
if diabetes == '1':
46+
self.diabetes.append([column_id, normal, diabetes, glaucoma, cataract, amd, hypertension, myopia, others])
47+
if glaucoma == '1':
48+
self.glaucoma.append([column_id, normal, diabetes, glaucoma, cataract, amd, hypertension, myopia, others])
49+
if cataract == '1':
50+
self.cataract.append([column_id, normal, diabetes, glaucoma, cataract, amd, hypertension, myopia, others])
51+
if amd == '1':
52+
self.amd.append([column_id, normal, diabetes, glaucoma, cataract, amd, hypertension, myopia, others])
53+
if hypertension == '1':
54+
self.hypertension.append([column_id, normal, diabetes, glaucoma, cataract, amd, hypertension, myopia, others])
55+
if myopia == '1':
56+
self.myopia.append([column_id, normal, diabetes, glaucoma, cataract, amd, hypertension, myopia, others])
57+
if others == '1':
58+
self.others.append([column_id, normal, diabetes, glaucoma, cataract, amd, hypertension, myopia, others])
59+

odir_model_advanced.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2019 Jordi Corbilla. All Rights Reserved.
1+
# Copyright 2019-2020 Jordi Corbilla. All Rights Reserved.
22
#
33
# Licensed under the Apache License, Version 2.0 (the "License");
44
# you may not use this file except in compliance with the License.
@@ -30,7 +30,7 @@ def compile(self):
3030
model.add(layers.Flatten())
3131
model.add(layers.Dense(64, activation='relu'))
3232
model.add(layers.Dense(8, activation='sigmoid'))
33-
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
33+
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=self.metrics)
3434
self.show_summary(model)
3535
self.plot_summary(model, 'model_advanced.png')
3636
return model

odir_model_base.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2019 Jordi Corbilla. All Rights Reserved.
1+
# Copyright 2019-2020 Jordi Corbilla. All Rights Reserved.
22
#
33
# Licensed under the Apache License, Version 2.0 (the "License");
44
# you may not use this file except in compliance with the License.
@@ -17,8 +17,9 @@
1717

1818

1919
class ModelBase:
20-
def __init__(self, input_shape):
20+
def __init__(self, input_shape, metrics):
2121
self.input_shape = input_shape
22+
self.metrics = metrics
2223

2324
def show_summary(self, model):
2425
model.summary()

odir_model_factory.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2019 Jordi Corbilla. All Rights Reserved.
1+
# Copyright 2019-2020 Jordi Corbilla. All Rights Reserved.
22
#
33
# Licensed under the Apache License, Version 2.0 (the "License");
44
# you may not use this file except in compliance with the License.
@@ -27,11 +27,11 @@ class ModelTypes(enum.Enum):
2727

2828
class Factory:
2929

30-
def __init__(self, input_shape):
30+
def __init__(self, input_shape, metrics):
3131
self.Makers = {
32-
ModelTypes.vgg16: Vgg16(input_shape),
33-
ModelTypes.inception_v1: InceptionV1(input_shape),
34-
ModelTypes.advanced_testing: Advanced(input_shape)
32+
ModelTypes.vgg16: Vgg16(input_shape, metrics),
33+
ModelTypes.inception_v1: InceptionV1(input_shape, metrics),
34+
ModelTypes.advanced_testing: Advanced(input_shape, metrics)
3535
}
3636

3737
def compile(self, model_type):

odir_model_inception_v1.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2019 Jordi Corbilla. All Rights Reserved.
1+
# Copyright 2019-2020 Jordi Corbilla. All Rights Reserved.
22
#
33
# Licensed under the Apache License, Version 2.0 (the "License");
44
# you may not use this file except in compliance with the License.
@@ -41,7 +41,7 @@ def compile(self):
4141
output = Dense(8, activation='sigmoid')(dense_3)
4242
model = Model([input_img], output)
4343

44-
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
44+
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=self.metrics)
4545

4646
self.show_summary(model)
4747
self.plot_summary(model, 'model_inception_v1.png')

odir_model_runner.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2019 Jordi Corbilla. All Rights Reserved.
1+
# Copyright 2019-2020 Jordi Corbilla. All Rights Reserved.
22
#
33
# Licensed under the Apache License, Version 2.0 (the "License");
44
# you may not use this file except in compliance with the License.

0 commit comments

Comments
 (0)