-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathdeep-homography.py
157 lines (130 loc) · 6.12 KB
/
deep-homography.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
import keras
from keras.models import Sequential, load_model
from keras.layers import Conv2D, MaxPooling2D, Dropout, Flatten, Dense, Reshape, Activation, Lambda
from keras.optimizers import SGD
from keras import backend as K
import glob
import numpy as np
import os.path
import matplotlib.pyplot as plt
# Data loader for training and validation
def data_loader(path):
while True:
for npz in glob.glob(os.path.join(path, '*.npz')):
# Load pack into memory
archive = np.load(npz)
images = archive['images']/255 # Normalize to 0 <= images <= 1
offsets = archive['offsets']/32 # Normalize to -1 <= offsets <= 1
yield images, offsets
# Common architecture to both networks
def common(model):
model.add(Conv2D(64, (3, 3), activation='relu', input_shape=(128, 128, 2)))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D((2, 2), strides=2))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D((2, 2), strides=2))
model.add(Conv2D(128, (3, 3), activation='relu'))
model.add(Conv2D(128, (3, 3), activation='relu'))
model.add(MaxPooling2D((2, 2), strides=2))
model.add(Conv2D(128, (3, 3), activation='relu'))
model.add(Conv2D(128, (3, 3), activation='relu'))
model.add(MaxPooling2D((2, 2), strides=2))
model.add(Dropout(0.5))
model.add(Flatten())
model.add(Dense(1024, activation='relu'))
return model
# Last layer of the regression network
def regression_network_last(model, lr):
model_r = common(model)
model_r.add(Dense(8, activation='relu'))
sgd = SGD(lr=lr, momentum=0.9)
model_r.compile(loss='mean_squared_error', optimizer=sgd, metrics=['mse'])
return model_r
# For the Lambda function of finding the maximum along the 21x21 distribution
def max_function(x):
y = K.max(x, axis=2)
return y
# Last layer of classification network
def classification_network_last(model, lr, batch_size=64):
model_c = common(model)
model_c.add(Dense(168))
model_c.add(Reshape((8, 21)))
model_c.add(Activation(activation=K.softmax))
model_c.add(Lambda(max_function))
sgd = SGD(lr=lr, momentum=0.9)
model_c.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['mse'])
return model_c
def decrease_lrate(epoch):
initial_lr = 0.005
return initial_lr * 10 ** (-int(epoch/4))
# Model training for regression network
def regression_network(train_data_path, val_data_path, total_iterations, batch_size, itr, steps_per_epoch, val_steps):
model_r = Sequential()
model_r = regression_network_last(model_r, lr=0.005)
epochs = int(total_iterations / steps_per_epoch) + 1
lrate = keras.callbacks.LearningRateScheduler(decrease_lrate)
model_r.fit_generator(generator=data_loader(train_data_path),
steps_per_epoch=steps_per_epoch,
epochs=epochs,
verbose=1,
validation_data=data_loader(val_data_path),
validation_steps=val_steps,
callbacks=[lrate])
model_r.save('models/regression.h5')
# Model training for classification network
def classification_network(train_data_path, val_data_path, total_iterations, batch_size, itr, steps_per_epoch, val_steps):
model_c = Sequential()
model_c = classification_network_last(model_c, lr=0.005)
lrate = keras.callbacks.LearningRateScheduler(decrease_lrate)
epochs = int(total_iterations / steps_per_epoch) + 1
model_c.fit_generator(generator=data_loader(train_data_path),
steps_per_epoch=steps_per_epoch,
epochs=epochs,
verbose=1,
validation_data=data_loader(val_data_path),
validation_steps=val_steps,
callbacks=[lrate])
model_c.save('models/classification.h5')
def test_model(model_save_path, test_data_path, test_size=5000, batch_size=64):
i = 0
j = 0
error = np.empty(int(test_size/batch_size)+1)
images = np.empty((batch_size, 128, 128, 2))
offsets = np.empty((batch_size, 8))
model_l = load_model(model_save_path)
for npz_test in glob.glob(os.path.join(test_data_path, '*.npz')):
archive = np.load(npz_test)
images[i] = np.resize(archive['images'], (128, 128, 2))/255
offsets[i] = archive['offsets']
i = i + 1
if i % batch_size == 0:
offsets_predicted = model_l.predict(images)*64
x_1 = np.sqrt((offsets[:, 0] - offsets_predicted[:, 0]) ** 2 + (offsets[:, 1] - offsets_predicted[:, 1]) ** 2)
x_2 = np.sqrt((offsets[:, 2] - offsets_predicted[:, 2]) ** 2 + (offsets[:, 3] - offsets_predicted[:, 3]) ** 2)
x_3 = np.sqrt((offsets[:, 4] - offsets_predicted[:, 4]) ** 2 + (offsets[:, 5] - offsets_predicted[:, 5]) ** 2)
x_4 = np.sqrt((offsets[:, 6] - offsets_predicted[:, 6]) ** 2 + (offsets[:, 6] - offsets_predicted[:, 7]) ** 2)
error[j] = np.average(x_1 + x_2 + x_3 + x_4)/4
print('Mean Corner Error: ', error[j])
j = j + 1
i = 0
print('Mean Average Corner Error: ', np.average(error))
train_data_path = 'train-data-combined/'
val_data_path = 'val-data-combined/'
test_data_path = 'test-data/'
total_iterations = 90000
batch_size = 64
train_samples = 500000
steps_per_epoch = int(train_samples / batch_size)
val_samples = 50000
val_steps = int(val_samples / batch_size)
itr = 30000
# print("Starting Training of Regression Network...")
# regression_network(train_data_path, val_data_path, total_iterations, batch_size, itr, steps_per_epoch, val_steps)
#
# print("Starting Training of Classification Network...")
# classification_network(train_data_path, val_data_path, total_iterations, batch_size, itr, steps_per_epoch, val_steps)
print("Testing the Regression Network...")
test_model(model_save_path='models/regression.h5', test_data_path='test-data/')
# print("Testing the Classification Network...")
# test_model(model_save_path='models/classification.h5', test_data_path='test-data/')