-
Notifications
You must be signed in to change notification settings - Fork 0
/
utils.py
93 lines (81 loc) · 3.64 KB
/
utils.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
'''
Helper functions for face recognition
'''
import numpy as np
import random
import os
import cv2
from keras.models import Sequential
from keras.layers import Flatten, Dense, Conv2D, MaxPooling2D
from keras import backend as K
from keras.utils import load_img, img_to_array
def euclidean_distance(vectors):
vector1, vector2 = vectors
sum_square = K.sum(K.square(vector1 - vector2), axis=1, keepdims=True)
return K.sqrt(K.maximum(sum_square, K.epsilon()))
def contrastive_loss(Y_true, D):
margin = 1
return K.mean(Y_true * K.square(D) + (1 - Y_true) * K.maximum((margin-D),0))
def accuracy(y_true, y_pred):
return K.mean(K.equal(y_true, K.cast(y_pred < 0.5, y_true.dtype)))
def create_pairs(X,Y, num_classes):
pairs, labels = [], []
# index of images in X and Y for each class
class_idx = [np.where(Y==i)[0] for i in range(num_classes)]
# The minimum number of images across all classes
min_images = min(len(class_idx[i]) for i in range(num_classes)) - 1
for c in range(num_classes):
for n in range(min_images):
# create positive pair
img1 = X[class_idx[c][n]]
img2 = X[class_idx[c][n+1]]
pairs.append((img1, img2))
labels.append(1)
# create negative pair
# first, create list of classes that are different from the current class
neg_list = list(range(num_classes))
neg_list.remove(c)
# select a random class from the negative list.
# this class will be used to form the negative pair
neg_c = random.sample(neg_list,1)[0]
img1 = X[class_idx[c][n]]
img2 = X[class_idx[neg_c][n]]
pairs.append((img1,img2))
labels.append(0)
# The .astype(np.float32) is added by me to match Tensorflow
return np.array(pairs).astype(np.float32), np.array(labels).astype(np.float32)
def create_shared_network(input_shape):
model = Sequential(name='Shared_Conv_Network')
model.add(Conv2D(filters=64, kernel_size=(3,3), activation='relu', input_shape=input_shape))
model.add(MaxPooling2D())
model.add(Conv2D(filters=64, kernel_size=(3,3), activation='relu'))
model.add(Flatten())
model.add(Dense(units=128, activation='sigmoid'))
return model
def get_data(dir):
X_train, Y_train = [], []
X_test, Y_test = [], []
subfolders = sorted([file.path for file in os.scandir(dir) if file.is_dir()])
for idx, folder in enumerate(subfolders):
for file in sorted(os.listdir(folder)):
img = load_img(folder+"/"+file, color_mode='grayscale')
img = img_to_array(img).astype('float32')/255
img = img.reshape(img.shape[0], img.shape[1],1)
if idx < 35:
X_train.append(img)
Y_train.append(idx)
else:
X_test.append(img)
Y_test.append(idx-35)
# The .astype(np.float32) is added by me to match Tensorflow
X_train = np.array(X_train).astype(np.float32)
X_test = np.array(X_test).astype(np.float32)
Y_train = np.array(Y_train).astype(np.float32)
Y_test = np.array(Y_test).astype(np.float32)
return (X_train, Y_train), (X_test, Y_test)
def write_on_frame(frame, text, text_x, text_y):
(text_width, text_height) = cv2.getTextSize(text, cv2.FONT_HERSHEY_SIMPLEX, fontScale=1, thickness=2)[0]
box_coords = ((text_x, text_y), (text_x+text_width+20, text_y-text_height-20))
cv2.rectangle(frame, box_coords[0], box_coords[1], (255, 255, 255), cv2.FILLED)
cv2.putText(frame, text, (text_x, text_y-10), cv2.FONT_HERSHEY_SIMPLEX, fontScale=1, color=(0,0,0), thickness=2)
return frame