Skip to content

Commit eea9e1d

Browse files
committed
Commit Message:
Jupyter Notebook for Face recognition. Change log: One-Shot Learning with Cosine Similarity. Committed By: Arvindh
1 parent e3225fc commit eea9e1d

2 files changed

+317
-4
lines changed

CNN using Keras and TensorFlow2.0_MNIST.ipynb

+4-4
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
},
1010
{
1111
"cell_type": "code",
12-
"execution_count": null,
12+
"execution_count": 2,
1313
"metadata": {},
1414
"outputs": [],
1515
"source": [
@@ -236,18 +236,18 @@
236236
"outputs": [],
237237
"source": [
238238
"#Save the model.\n",
239-
"model.save('mnist_number_trained_model.h5')\n",
239+
"model.save('models/mnist_number_trained_model.h5')\n",
240240
"\n"
241241
]
242242
},
243243
{
244244
"cell_type": "code",
245-
"execution_count": null,
245+
"execution_count": 3,
246246
"metadata": {},
247247
"outputs": [],
248248
"source": [
249249
"#load the saved model\n",
250-
"classifier=load_model('mnist_number_trained_model.h5')"
250+
"classifier=load_model('models/mnist_number_trained_model.h5')"
251251
]
252252
},
253253
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,313 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"## One-Shot Learning with Cosine Similarity\n",
8+
"This notebook contains code for Face recognition.\n",
9+
"\n",
10+
"Reference:\n",
11+
"\n",
12+
"https://sefiks.com/2018/08/06/deep-face-recognition-with-keras/\n",
13+
"\n",
14+
"https://www.robots.ox.ac.uk/~vgg/data/vgg_face/\n",
15+
"\n",
16+
"Udemy Course:\n",
17+
"\n",
18+
"https://www.udemy.com/share/10381KBEoacl5STXU=/\n",
19+
"\n",
20+
"\n",
21+
"Note:\n",
22+
"Please put the person images in people_images folder.\n"
23+
]
24+
},
25+
{
26+
"cell_type": "code",
27+
"execution_count": 1,
28+
"metadata": {},
29+
"outputs": [],
30+
"source": [
31+
"#Import modules.\n",
32+
"from tensorflow.keras.models import Model, Sequential\n",
33+
"from tensorflow.keras.layers import Input, Convolution2D, ZeroPadding2D, MaxPooling2D, Flatten, Dense, Dropout, Activation\n",
34+
"from PIL import Image\n",
35+
"import numpy as np\n",
36+
"from tensorflow.keras.preprocessing import image\n",
37+
"from tensorflow.keras.preprocessing.image import load_img, save_img, img_to_array\n",
38+
"from tensorflow.keras.applications.imagenet_utils import preprocess_input\n",
39+
"#VGG 16 CNN model.\n",
40+
"from tensorflow.keras.applications.vgg16 import VGG16\n",
41+
"from tensorflow.keras.utils import plot_model\n",
42+
"import matplotlib.pyplot as plt\n",
43+
"\n",
44+
"import cv2 as cv\n",
45+
"import os\n",
46+
"from os import listdir\n",
47+
"from os.path import isfile, join"
48+
]
49+
},
50+
{
51+
"cell_type": "code",
52+
"execution_count": 2,
53+
"metadata": {},
54+
"outputs": [],
55+
"source": [
56+
"#VGGFace.\n",
57+
"#https://www.robots.ox.ac.uk/~vgg/\n",
58+
"model = Sequential()\n",
59+
"model.add(ZeroPadding2D((1,1),input_shape=(224,224, 3)))\n",
60+
"model.add(Convolution2D(64, (3, 3), activation='relu'))\n",
61+
"model.add(ZeroPadding2D((1,1)))\n",
62+
"model.add(Convolution2D(64, (3, 3), activation='relu'))\n",
63+
"model.add(MaxPooling2D((2,2), strides=(2,2)))\n",
64+
"\n",
65+
"model.add(ZeroPadding2D((1,1)))\n",
66+
"model.add(Convolution2D(128, (3, 3), activation='relu'))\n",
67+
"model.add(ZeroPadding2D((1,1)))\n",
68+
"model.add(Convolution2D(128, (3, 3), activation='relu'))\n",
69+
"model.add(MaxPooling2D((2,2), strides=(2,2)))\n",
70+
"\n",
71+
"model.add(ZeroPadding2D((1,1)))\n",
72+
"model.add(Convolution2D(256, (3, 3), activation='relu'))\n",
73+
"model.add(ZeroPadding2D((1,1)))\n",
74+
"model.add(Convolution2D(256, (3, 3), activation='relu'))\n",
75+
"model.add(ZeroPadding2D((1,1)))\n",
76+
"model.add(Convolution2D(256, (3, 3), activation='relu'))\n",
77+
"model.add(MaxPooling2D((2,2), strides=(2,2)))\n",
78+
"\n",
79+
"model.add(ZeroPadding2D((1,1)))\n",
80+
"model.add(Convolution2D(512, (3, 3), activation='relu'))\n",
81+
"model.add(ZeroPadding2D((1,1)))\n",
82+
"model.add(Convolution2D(512, (3, 3), activation='relu'))\n",
83+
"model.add(ZeroPadding2D((1,1)))\n",
84+
"model.add(Convolution2D(512, (3, 3), activation='relu'))\n",
85+
"model.add(MaxPooling2D((2,2), strides=(2,2)))\n",
86+
"\n",
87+
"model.add(ZeroPadding2D((1,1)))\n",
88+
"model.add(Convolution2D(512, (3, 3), activation='relu'))\n",
89+
"model.add(ZeroPadding2D((1,1)))\n",
90+
"model.add(Convolution2D(512, (3, 3), activation='relu'))\n",
91+
"model.add(ZeroPadding2D((1,1)))\n",
92+
"model.add(Convolution2D(512, (3, 3), activation='relu'))\n",
93+
"model.add(MaxPooling2D((2,2), strides=(2,2)))\n",
94+
"\n",
95+
"model.add(Convolution2D(4096, (7, 7), activation='relu'))\n",
96+
"model.add(Dropout(0.5))\n",
97+
"model.add(Convolution2D(4096, (1, 1), activation='relu'))\n",
98+
"model.add(Dropout(0.5))\n",
99+
"model.add(Convolution2D(2622, (1, 1)))\n",
100+
"model.add(Flatten())\n",
101+
"model.add(Activation('softmax'))\n",
102+
"#print(model.summary())"
103+
]
104+
},
105+
{
106+
"cell_type": "code",
107+
"execution_count": 3,
108+
"metadata": {},
109+
"outputs": [],
110+
"source": [
111+
"# Load the model.\n",
112+
"# Download the model from https://drive.google.com/file/d/1CPSeum3HpopfomUEK1gybeuIVoeJT_Eo/view?usp=sharing\n",
113+
"#plot_model(model, to_file='VGG-16.png')\n",
114+
"model.load_weights('models/vgg_face_weights.h5')"
115+
]
116+
},
117+
{
118+
"cell_type": "code",
119+
"execution_count": 4,
120+
"metadata": {},
121+
"outputs": [],
122+
"source": [
123+
"#Function to pre-process images\n",
124+
"def preprocess_image(image_path):\n",
125+
" img = load_img(image_path, target_size=(224, 224))\n",
126+
" img = img_to_array(img)\n",
127+
" img = np.expand_dims(img, axis=0)\n",
128+
" img = preprocess_input(img)\n",
129+
" return img\n"
130+
]
131+
},
132+
{
133+
"cell_type": "code",
134+
"execution_count": 5,
135+
"metadata": {},
136+
"outputs": [],
137+
"source": [
138+
"#Function to find Cosine Similarity.\n",
139+
"\n",
140+
"def cosine_similarity(src_vector, test_vector):\n",
141+
" #Cosine Distance\n",
142+
" num=np.matmul(np.transpose(src_vector),test_vector)\n",
143+
" norm1=np.sum(np.multiply(src_vector,src_vector))\n",
144+
" norm2=np.sum(np.multiply(test_vector,test_vector))\n",
145+
" return 1 -(num/(np.sqrt(norm1)*np.sqrt(norm2)))"
146+
]
147+
},
148+
{
149+
"cell_type": "code",
150+
"execution_count": 6,
151+
"metadata": {},
152+
"outputs": [],
153+
"source": [
154+
"#Previous layer from output.\n",
155+
"vgg_face_descriptor= Model(inputs=model.layers[0].input, outputs=model.layers[-2].output)"
156+
]
157+
},
158+
{
159+
"cell_type": "code",
160+
"execution_count": 7,
161+
"metadata": {},
162+
"outputs": [
163+
{
164+
"name": "stdout",
165+
"output_type": "stream",
166+
"text": [
167+
"Collected 5 images\n",
168+
"Found a face\n",
169+
"Found a face\n",
170+
"Found a face\n",
171+
"Found a face\n",
172+
"Found a face\n"
173+
]
174+
}
175+
],
176+
"source": [
177+
"#Detect faces via camera.\n",
178+
"\n",
179+
"#Find faces from images and save them.\n",
180+
"def makedir(directory):\n",
181+
" if not os.path.exists(directory):\n",
182+
" os.makedirs(directory)\n",
183+
" return None\n",
184+
" else:\n",
185+
" pass\n",
186+
"#Haar Cascade Classifier.\n",
187+
"\n",
188+
"face_detector=cv.CascadeClassifier('Haarcascades/haarcascade_frontalface_default.xml')\n",
189+
"\n",
190+
"mypath = \"./people_images/\"\n",
191+
"image_file_names = [f for f in listdir(mypath) if isfile(join(mypath, f))]\n",
192+
"print(\"Collected \" + str(len(image_file_names)) + \" images\")\n",
193+
"makedir(\"./faces/\")\n",
194+
"\n",
195+
"for image_name in image_file_names:\n",
196+
" person_image = cv.imread(mypath+image_name)\n",
197+
" face_info = face_detector.detectMultiScale(person_image, 1.3, 5)\n",
198+
" print('Found a face')\n",
199+
" for (x,y,w,h) in face_info:\n",
200+
" face = person_image[y:y+h, x:x+w]\n",
201+
" roi = cv.resize(face, (128, 128), interpolation = cv.INTER_CUBIC)\n",
202+
" path = \"./faces/\" + \"face_\" + image_name \n",
203+
" cv.imwrite(path, roi)"
204+
]
205+
},
206+
{
207+
"cell_type": "code",
208+
"execution_count": 8,
209+
"metadata": {},
210+
"outputs": [],
211+
"source": [
212+
"face_folder='./faces'\n",
213+
"#Dictionary to store feature vectors.\n",
214+
"face_dict=dict()\n",
215+
"\n",
216+
"for file in listdir(face_folder):\n",
217+
" person,ext=file.split(\".\")\n",
218+
" face_dict[person]=vgg_face_descriptor.predict(preprocess_image('./faces/%s.jpg' % (person)))[0,:]\n"
219+
]
220+
},
221+
{
222+
"cell_type": "code",
223+
"execution_count": null,
224+
"metadata": {},
225+
"outputs": [],
226+
"source": [
227+
"capture=cv.VideoCapture(0)\n",
228+
"\n",
229+
"while (True):\n",
230+
" ret, img=capture.read()\n",
231+
" #Haar Cascade Classifier\n",
232+
" faces=face_detector.detectMultiScale(img,1.3,5)\n",
233+
" \n",
234+
" for (x,y,w,h) in faces:\n",
235+
" if w >100:\n",
236+
" #Draw bounding rectangle.\n",
237+
" cv.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)\n",
238+
" #Crop the image.\n",
239+
" face_detect=img[int(y):int(y+h),int(x):int(x+w)]\n",
240+
" #Resize to VGGFace dimensions.\n",
241+
" face_detect=cv.resize(face_detect,(224,224))\n",
242+
" #PreProcess image.\n",
243+
"\n",
244+
"\n",
245+
" img_pixels = image.img_to_array(face_detect)\n",
246+
" img_pixels = np.expand_dims(img_pixels, axis = 0)\n",
247+
" img_pixels /= 255\n",
248+
" #face_detect=preprocess_image(face_detect)\n",
249+
" #face_detect/=255\n",
250+
" #cv.imshow('Image',img)\n",
251+
" capture_vector=vgg_face_descriptor.predict(img_pixels)[0,:]\n",
252+
" found=0\n",
253+
" for index in face_dict:\n",
254+
" saved_vector=face_dict[index]\n",
255+
" name=index\n",
256+
" cs=cosine_similarity(capture_vector,saved_vector)\n",
257+
" if (cs<0.45):\n",
258+
" cv.putText(img, name[5:], (int(x+w+15), int(y-12)), cv.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)\n",
259+
" found=1\n",
260+
" #cv.rectangle(img,(x,y),(x+w,y+h),(255,0,255),2)\n",
261+
" break\n",
262+
" #connect face and text\n",
263+
" cv.line(img,(int((x+x+w)/2),y+15),(x+w,y-20),(255, 0, 0),1)\n",
264+
" cv.line(img,(x+w,y-20),(x+w+10,y-20),(255, 0, 0),1)\n",
265+
"\n",
266+
" if(found == 0): #if found image is not in our people database\n",
267+
" cv.putText(img, 'unknown', (int(x+w+15), int(y-12)), cv.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2)\n",
268+
"\n",
269+
" cv.imshow('Image',img)\n",
270+
" if cv.waitKey(1) == 13: #13 is the Enter Key\n",
271+
" break\n",
272+
" \n",
273+
"capture.release()\n",
274+
"cv.destroyAllWindows()"
275+
]
276+
},
277+
{
278+
"cell_type": "code",
279+
"execution_count": null,
280+
"metadata": {},
281+
"outputs": [],
282+
"source": []
283+
},
284+
{
285+
"cell_type": "code",
286+
"execution_count": null,
287+
"metadata": {},
288+
"outputs": [],
289+
"source": []
290+
}
291+
],
292+
"metadata": {
293+
"kernelspec": {
294+
"display_name": "Python 3",
295+
"language": "python",
296+
"name": "python3"
297+
},
298+
"language_info": {
299+
"codemirror_mode": {
300+
"name": "ipython",
301+
"version": 3
302+
},
303+
"file_extension": ".py",
304+
"mimetype": "text/x-python",
305+
"name": "python",
306+
"nbconvert_exporter": "python",
307+
"pygments_lexer": "ipython3",
308+
"version": "3.6.12"
309+
}
310+
},
311+
"nbformat": 4,
312+
"nbformat_minor": 4
313+
}

0 commit comments

Comments
 (0)