care2achieve commited on
Commit
99f032d
·
1 Parent(s): c1df8d1

updated files

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitignore +0 -1
  2. Dockerfile +1 -1
  3. README.md +0 -10
  4. app/Hackathon_setup/classes.txt +0 -17
  5. app/Hackathon_setup/exp_recognition.py +26 -72
  6. app/Hackathon_setup/exp_recognition_model.py +11 -27
  7. app/Hackathon_setup/face_classifier.joblib +0 -3
  8. app/Hackathon_setup/face_recognition.py +44 -133
  9. app/Hackathon_setup/face_recognition_model.py +14 -38
  10. app/Hackathon_setup/siamese_model.pth +0 -3
  11. app/config.py +18 -10
  12. app/main.py +71 -60
  13. app/static/Angelina_001.jpg +0 -0
  14. app/static/Angelina_002.jpg +0 -0
  15. app/static/Angelina_003.jpg +0 -0
  16. app/static/Angelina_004.jpg +0 -0
  17. app/static/Angelina_005.jpg +0 -0
  18. app/static/Brad_001.jpg +0 -0
  19. app/static/Brad_002.jpg +0 -0
  20. app/static/Brad_003.jpg +0 -0
  21. app/static/Brad_004.jpg +0 -0
  22. app/static/Brad_005.jpg +0 -0
  23. app/static/Denzel_001.jpg +0 -0
  24. app/static/Denzel_002.jpg +0 -0
  25. app/static/Denzel_003.jpg +0 -0
  26. app/static/Denzel_004.jpg +0 -0
  27. app/static/Denzel_005.jpg +0 -0
  28. app/static/Hugh_001.jpg +0 -0
  29. app/static/Hugh_002.jpg +0 -0
  30. app/static/Hugh_003.jpg +0 -0
  31. app/static/Hugh_004.jpg +0 -0
  32. app/static/Hugh_005.jpg +0 -0
  33. app/static/Jennifer_001.jpg +0 -0
  34. app/static/Jennifer_002.jpg +0 -0
  35. app/static/Jennifer_003.jpg +0 -0
  36. app/static/Jennifer_004.jpg +0 -0
  37. app/static/Jennifer_005.jpg +0 -0
  38. app/static/Johnny_001.jpg +0 -0
  39. app/static/Johnny_002.jpg +0 -0
  40. app/static/Johnny_003.jpg +0 -0
  41. app/static/Johnny_004.jpg +0 -0
  42. app/static/Johnny_005.jpg +0 -0
  43. app/static/Kate_001.jpg +0 -0
  44. app/static/Kate_002.jpg +0 -0
  45. app/static/Kate_003.jpg +0 -0
  46. app/static/Kate_004.jpg +0 -0
  47. app/static/Kate_005.jpg +0 -0
  48. app/static/Leonardo_001.jpg +0 -0
  49. app/static/Leonardo_002.jpg +0 -0
  50. app/static/Leonardo_003.jpg +0 -0
.gitignore DELETED
@@ -1 +0,0 @@
1
- **/__pycache__/**
 
 
Dockerfile CHANGED
@@ -24,6 +24,6 @@ USER myuser
24
 
25
  COPY --chown=myuser app app
26
 
27
- EXPOSE 7860
28
 
29
  CMD ["python", "app/main.py"]
 
24
 
25
  COPY --chown=myuser app app
26
 
27
+ EXPOSE 8001
28
 
29
  CMD ["python", "app/main.py"]
README.md DELETED
@@ -1,10 +0,0 @@
1
- ---
2
- title: Hackathon 4
3
- emoji: 🐢
4
- colorFrom: indigo
5
- colorTo: indigo
6
- sdk: docker
7
- pinned: false
8
- ---
9
-
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
app/Hackathon_setup/classes.txt DELETED
@@ -1,17 +0,0 @@
1
- Angelina Jolie
2
- Brad Pitt
3
- Denzel Washington
4
- Hugh Jackman
5
- Jennifer Lawrence
6
- Johnny Depp
7
- Kate Winslet
8
- Leonardo DiCaprio
9
- Megan Fox
10
- Natalie Portman
11
- Nicole Kidman
12
- Robert Downey Jr
13
- Sandra Bullock
14
- Scarlett Johansson
15
- Tom Cruise
16
- Tom Hanks
17
- Will Smith
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/Hackathon_setup/exp_recognition.py CHANGED
@@ -1,10 +1,14 @@
1
  import numpy as np
2
  import cv2
 
3
  import torch
 
4
  from .exp_recognition_model import *
5
  from PIL import Image
 
 
6
  import os
7
- from functools import lru_cache
8
 
9
  #############################################################################################################################
10
  # Caution: Don't change any of the filenames, function names and definitions #
@@ -20,8 +24,10 @@ current_path = os.path.dirname(os.path.abspath(__file__))
20
  #3) If no face is detected,then it returns zero(0).
21
 
22
  def detected_face(image):
 
23
  face_haar = current_path + '/haarcascade_frontalface_default.xml'
24
  face_cascade = cv2.CascadeClassifier(face_haar)
 
25
  gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
26
  faces = face_cascade.detectMultiScale(gray, 1.3, 5)
27
  face_areas=[]
@@ -34,68 +40,6 @@ def detected_face(image):
34
  required_image = images[np.argmax(face_areas)]
35
  required_image = Image.fromarray(required_image)
36
  return required_image
37
-
38
-
39
- def _load_state_dict(model, path, device):
40
- checkpoint = torch.load(path, map_location=device)
41
- if isinstance(checkpoint, dict):
42
- state_dict = checkpoint.get("net_dict") or checkpoint.get("state_dict") or checkpoint
43
- else:
44
- state_dict = checkpoint
45
- model.load_state_dict(state_dict, strict=False)
46
- return model
47
-
48
-
49
- @lru_cache(maxsize=1)
50
- def _load_expression_model():
51
- device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
52
- model_paths = [
53
- "expression_model.t7",
54
- "expression_model.pth",
55
- "exp_recognition_net.t7",
56
- "exp_recognition_model.t7",
57
- ]
58
- for filename in model_paths:
59
- path = os.path.join(current_path, filename)
60
- if os.path.exists(path):
61
- model = facExpRec().to(device)
62
- _load_state_dict(model, path, device)
63
- model.eval()
64
- return model, device
65
- return None, device
66
-
67
-
68
- def _prepare_face(img):
69
- face = detected_face(img)
70
- if face == 0:
71
- face = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY))
72
- return face
73
-
74
-
75
- def _heuristic_expression(face):
76
- gray = np.asarray(face.resize((48, 48)).convert("L"), dtype=np.float32) / 255.0
77
- upper = gray[:24, :]
78
- lower = gray[24:, :]
79
- mouth = gray[30:43, 12:36]
80
- eye_band = gray[10:22, 8:40]
81
- brightness = float(gray.mean())
82
- contrast = float(gray.std())
83
- mouth_darkness = float(1.0 - mouth.mean())
84
- eye_contrast = float(eye_band.std())
85
- lower_edges = float(cv2.Laplacian(lower, cv2.CV_32F).var())
86
- upper_edges = float(cv2.Laplacian(upper, cv2.CV_32F).var())
87
-
88
- if mouth_darkness > 0.52 and lower_edges > upper_edges * 1.15:
89
- return "HAPPINESS"
90
- if eye_contrast > 0.22 and mouth_darkness > 0.42:
91
- return "SURPRISE"
92
- if brightness < 0.34 and contrast > 0.24:
93
- return "ANGER"
94
- if contrast < 0.13:
95
- return "NEUTRAL"
96
- if lower_edges < upper_edges * 0.72:
97
- return "SADNESS"
98
- return "NEUTRAL"
99
 
100
 
101
  #1) Images captured from mobile is passed as parameter to the below function in the API call, It returns the Expression detected by your network.
@@ -105,13 +49,23 @@ def _heuristic_expression(face):
105
  #5) For loading your model use the current_path+'your model file name', anyhow detailed example is given in comments to the function
106
  ##Caution: Don't change the definition or function name; for loading the model use the current_path for path example is given in comments to the function
107
  def get_expression(img):
108
- face = _prepare_face(img)
109
- model, device = _load_expression_model()
110
- if model is None:
111
- return _heuristic_expression(face)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
 
113
- with torch.no_grad():
114
- tensor = trnscm(face).unsqueeze(0).to(device)
115
- logits = model(tensor)
116
- class_index = int(torch.argmax(logits, dim=1).item())
117
- return classes.get(class_index, "UNKNOWN")
 
1
  import numpy as np
2
  import cv2
3
+ from matplotlib import pyplot as plt
4
  import torch
5
+ # In the below line,remove '.' while working on your local system.However Make sure that '.' is present before face_recognition_model while uploading to the server, Do not remove it.
6
  from .exp_recognition_model import *
7
  from PIL import Image
8
+ import base64
9
+ import io
10
  import os
11
+ ## Add more imports if required
12
 
13
  #############################################################################################################################
14
  # Caution: Don't change any of the filenames, function names and definitions #
 
24
  #3) If no face is detected,then it returns zero(0).
25
 
26
  def detected_face(image):
27
+ eye_haar = current_path + '/haarcascade_eye.xml'
28
  face_haar = current_path + '/haarcascade_frontalface_default.xml'
29
  face_cascade = cv2.CascadeClassifier(face_haar)
30
+ eye_cascade = cv2.CascadeClassifier(eye_haar)
31
  gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
32
  faces = face_cascade.detectMultiScale(gray, 1.3, 5)
33
  face_areas=[]
 
40
  required_image = images[np.argmax(face_areas)]
41
  required_image = Image.fromarray(required_image)
42
  return required_image
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
 
44
 
45
  #1) Images captured from mobile is passed as parameter to the below function in the API call, It returns the Expression detected by your network.
 
49
  #5) For loading your model use the current_path+'your model file name', anyhow detailed example is given in comments to the function
50
  ##Caution: Don't change the definition or function name; for loading the model use the current_path for path example is given in comments to the function
51
  def get_expression(img):
52
+ device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
53
+
54
+ ##########################################################################################
55
+ ##Example for loading a model using weight state dictionary: ##
56
+ ## face_det_net = facExpRec() #Example Network ##
57
+ ## model = torch.load(current_path + '/exp_recognition_net.t7', map_location=device) ##
58
+ ## face_det_net.load_state_dict(model['net_dict']) ##
59
+ ## ##
60
+ ##current_path + '/<network_definition>' is path of the saved model if present in ##
61
+ ##the same path as this file, we recommend to put in the same directory ##
62
+ ##########################################################################################
63
+ ##########################################################################################
64
+
65
+ face = detected_face(img)
66
+ if face==0:
67
+ face = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY))
68
+
69
+ # YOUR CODE HERE, return expression using your model
70
 
71
+ return "YET TO BE CODED"
 
 
 
 
app/Hackathon_setup/exp_recognition_model.py CHANGED
@@ -1,7 +1,8 @@
1
  import torch
 
2
  import torch.nn as nn
3
- import torch.nn.functional as F
4
  from torchvision import transforms
 
5
 
6
  ####################################################################################################################
7
  # Define your model and transform and all necessary helper functions here #
@@ -11,37 +12,20 @@ from torchvision import transforms
11
  # Definition of classes as dictionary
12
  classes = {0: 'ANGER', 1: 'DISGUST', 2: 'FEAR', 3: 'HAPPINESS', 4: 'NEUTRAL', 5: 'SADNESS', 6: 'SURPRISE'}
13
 
14
- class facExpRec(nn.Module):
 
15
  def __init__(self):
16
- super().__init__()
17
- self.features = nn.Sequential(
18
- nn.Conv2d(1, 32, kernel_size=3, padding=1),
19
- nn.BatchNorm2d(32),
20
- nn.ReLU(inplace=True),
21
- nn.MaxPool2d(2),
22
- nn.Conv2d(32, 64, kernel_size=3, padding=1),
23
- nn.BatchNorm2d(64),
24
- nn.ReLU(inplace=True),
25
- nn.MaxPool2d(2),
26
- nn.Conv2d(64, 128, kernel_size=3, padding=1),
27
- nn.BatchNorm2d(128),
28
- nn.ReLU(inplace=True),
29
- nn.MaxPool2d(2),
30
- )
31
- self.classifier = nn.Sequential(
32
- nn.Flatten(),
33
- nn.Linear(128 * 6 * 6, 256),
34
- nn.ReLU(inplace=True),
35
- nn.Dropout(0.35),
36
- nn.Linear(256, len(classes)),
37
- )
38
 
39
  def forward(self, x):
40
- x = self.features(x)
41
- return self.classifier(x)
42
 
43
  # Sample Helper function
44
  def rgb2gray(image):
45
  return image.convert('L')
46
 
47
- trnscm = transforms.Compose([rgb2gray, transforms.Resize((48, 48)), transforms.ToTensor()])
 
 
 
1
  import torch
2
+ import torchvision
3
  import torch.nn as nn
 
4
  from torchvision import transforms
5
+ ## Add more imports if required
6
 
7
  ####################################################################################################################
8
  # Define your model and transform and all necessary helper functions here #
 
12
  # Definition of classes as dictionary
13
  classes = {0: 'ANGER', 1: 'DISGUST', 2: 'FEAR', 3: 'HAPPINESS', 4: 'NEUTRAL', 5: 'SADNESS', 6: 'SURPRISE'}
14
 
15
+ # Example Network
16
+ class facExpRec(torch.nn.Module):
17
  def __init__(self):
18
+ pass # remove 'pass' once you have written your code
19
+ #YOUR CODE HERE
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
 
21
  def forward(self, x):
22
+ pass # remove 'pass' once you have written your code
23
+ #YOUR CODE HERE
24
 
25
  # Sample Helper function
26
  def rgb2gray(image):
27
  return image.convert('L')
28
 
29
+ # Sample Transformation function
30
+ #YOUR CODE HERE for changing the Transformation values.
31
+ trnscm = transforms.Compose([rgb2gray, transforms.Resize((48,48)), transforms.ToTensor()])
app/Hackathon_setup/face_classifier.joblib DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:63543e655da6a76c150f1faa489c631a2aef9dd1865670c2c337378570ea44a7
3
- size 2278873
 
 
 
 
app/Hackathon_setup/face_recognition.py CHANGED
@@ -1,11 +1,18 @@
1
  import numpy as np
2
  import cv2
 
3
  import torch
 
4
  from .face_recognition_model import *
5
  from PIL import Image
 
 
6
  import os
7
  import joblib
8
- from functools import lru_cache
 
 
 
9
 
10
  ###########################################################################################################################################
11
  # Caution: Don't change any of the filenames, function names and definitions #
@@ -20,8 +27,10 @@ current_path = os.path.dirname(os.path.abspath(__file__))
20
  #3) If no face is detected,then it returns zero(0).
21
 
22
  def detected_face(image):
 
23
  face_haar = current_path + '/haarcascade_frontalface_default.xml'
24
  face_cascade = cv2.CascadeClassifier(face_haar)
 
25
  gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
26
  faces = face_cascade.detectMultiScale(gray, 1.3, 5)
27
  face_areas=[]
@@ -36,85 +45,6 @@ def detected_face(image):
36
  return required_image
37
 
38
 
39
- def _load_state_dict(model, path, device):
40
- checkpoint = torch.load(path, map_location=device)
41
- if isinstance(checkpoint, dict):
42
- state_dict = checkpoint.get("net_dict") or checkpoint.get("state_dict") or checkpoint
43
- else:
44
- state_dict = checkpoint
45
- model.load_state_dict(state_dict, strict=False)
46
- return model
47
-
48
-
49
- @lru_cache(maxsize=1)
50
- def _load_siamese():
51
- device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
52
- model_paths = [
53
- "siamese_model.t7",
54
- "siamese_model.pth",
55
- "face_similarity_model.t7",
56
- "face_recognition_model.t7",
57
- ]
58
- for filename in model_paths:
59
- path = os.path.join(current_path, filename)
60
- if os.path.exists(path):
61
- model = Siamese().to(device)
62
- _load_state_dict(model, path, device)
63
- model.eval()
64
- return model, device
65
- return None, device
66
-
67
-
68
- @lru_cache(maxsize=1)
69
- def _load_classifier():
70
- classifier_paths = [
71
- "face_classifier.joblib",
72
- "face_classifier.pkl",
73
- "decision_tree_model.sav",
74
- "classifier.sav",
75
- ]
76
- for filename in classifier_paths:
77
- path = os.path.join(current_path, filename)
78
- print("path :", path)
79
- if os.path.exists(path):
80
- return joblib.load(path)
81
- return None
82
-
83
-
84
- def _prepare_face(image):
85
- face = detected_face(image)
86
- if face == 0:
87
- face = Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2GRAY))
88
- return face
89
-
90
-
91
- def _handcrafted_embedding(face):
92
- gray = np.asarray(face.resize((100, 100)).convert("L"), dtype=np.float32) / 255.0
93
- resized = cv2.resize(gray, (32, 32)).flatten()
94
- hist = cv2.calcHist([(gray * 255).astype(np.uint8)], [0], None, [32], [0, 256]).flatten()
95
- hist = hist / max(float(hist.sum()), 1.0)
96
- gx = cv2.Sobel(gray, cv2.CV_32F, 1, 0, ksize=3)
97
- gy = cv2.Sobel(gray, cv2.CV_32F, 0, 1, ksize=3)
98
- mag, ang = cv2.cartToPolar(gx, gy, angleInDegrees=True)
99
- grad_hist = np.histogram(ang, bins=16, range=(0, 360), weights=mag)[0].astype(np.float32)
100
- grad_hist = grad_hist / max(float(grad_hist.sum()), 1.0)
101
- embedding = np.concatenate([resized, hist, grad_hist]).astype(np.float32)
102
- norm = np.linalg.norm(embedding)
103
- return embedding / norm if norm else embedding
104
-
105
-
106
- def _embedding(face):
107
- model, device = _load_siamese()
108
- if model is None:
109
- return _handcrafted_embedding(face)
110
-
111
- with torch.no_grad():
112
- tensor = trnscm(face).unsqueeze(0).to(device)
113
- output = model(tensor).detach().cpu().numpy().reshape(-1)
114
- norm = np.linalg.norm(output)
115
- return output / norm if norm else output
116
-
117
-
118
  #1) Images captured from mobile is passed as parameter to the below function in the API call. It returns the similarity measure between given images.
119
  #2) The image is passed to the function in base64 encoding, Code for decoding the image is provided within the function.
120
  #3) Define an object to your siamese network here in the function and load the weight from the trained network, set it in evaluation mode.
@@ -122,13 +52,31 @@ def _embedding(face):
122
  #5) For loading your model use the current_path+'your model file name', anyhow detailed example is given in comments to the function
123
  #Caution: Don't change the definition or function name; for loading the model use the current_path for path example is given in comments to the function
124
  def get_similarity(img1, img2):
125
- face1 = _prepare_face(img1)
126
- face2 = _prepare_face(img2)
127
- emb1 = _embedding(face1)
128
- emb2 = _embedding(face2)
129
- cosine_similarity = float(np.dot(emb1, emb2))
130
- cosine_similarity = max(min(cosine_similarity, 1.0), -1.0)
131
- return float(1.0 - cosine_similarity)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
 
133
  #1) Image captured from mobile is passed as parameter to this function in the API call, It returns the face class in the string form ex: "Person1"
134
  #2) The image is passed to the function in base64 encoding, Code to decode the image provided within the function
@@ -137,49 +85,12 @@ def get_similarity(img1, img2):
137
  #5) Along with the siamese, you need the classifier as well, which is to be finetuned with the faces that you are training
138
  ##Caution: Don't change the definition or function name; for loading the model use the current_path for path example is given in comments to the function
139
  def get_face_class(img1):
140
- face = _prepare_face(img1)
141
- emb = _embedding(face).reshape(1, -1)
142
- classifier_model = _load_classifier()
143
- if classifier_model is not None:
144
- model = classifier_model["model"]
145
- prediction = model.predict(emb)[0]
146
- if isinstance(prediction, (int, np.integer)) and 0 <= int(prediction) < len(classes):
147
- return classes[int(prediction)]
148
- return str(prediction)
149
-
150
- gallery_result = _nearest_gallery_match(emb.reshape(-1))
151
- if gallery_result is not None:
152
- name, distance = gallery_result
153
- return f"{name} (distance: {distance:.3f})"
154
-
155
- return "Unknown - add face_classifier.joblib or known_faces/<person> images"
156
-
157
-
158
- @lru_cache(maxsize=1)
159
- def _gallery_embeddings():
160
- gallery_dir = os.path.join(current_path, "known_faces")
161
- if not os.path.isdir(gallery_dir):
162
- return []
163
-
164
- gallery = []
165
- for person_name in sorted(os.listdir(gallery_dir)):
166
- person_dir = os.path.join(gallery_dir, person_name)
167
- if not os.path.isdir(person_dir):
168
- continue
169
- for filename in sorted(os.listdir(person_dir)):
170
- if not filename.lower().endswith((".jpg", ".jpeg", ".png", ".bmp", ".webp")):
171
- continue
172
- image = cv2.imread(os.path.join(person_dir, filename))
173
- if image is None:
174
- continue
175
- image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
176
- gallery.append((person_name, _embedding(_prepare_face(image))))
177
- return gallery
178
-
179
-
180
- def _nearest_gallery_match(query_embedding):
181
- gallery = _gallery_embeddings()
182
- if not gallery:
183
- return None
184
- distances = [(name, float(1.0 - np.dot(query_embedding, emb))) for name, emb in gallery]
185
- return min(distances, key=lambda item: item[1])
 
1
  import numpy as np
2
  import cv2
3
+ from matplotlib import pyplot as plt
4
  import torch
5
+ # In the below line,remove '.' while working on your local system. However Make sure that '.' is present before face_recognition_model while uploading to the server, Do not remove it.
6
  from .face_recognition_model import *
7
  from PIL import Image
8
+ import base64
9
+ import io
10
  import os
11
  import joblib
12
+ import pickle
13
+ # Add more imports if required
14
+
15
+
16
 
17
  ###########################################################################################################################################
18
  # Caution: Don't change any of the filenames, function names and definitions #
 
27
  #3) If no face is detected,then it returns zero(0).
28
 
29
  def detected_face(image):
30
+ eye_haar = current_path + '/haarcascade_eye.xml'
31
  face_haar = current_path + '/haarcascade_frontalface_default.xml'
32
  face_cascade = cv2.CascadeClassifier(face_haar)
33
+ eye_cascade = cv2.CascadeClassifier(eye_haar)
34
  gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
35
  faces = face_cascade.detectMultiScale(gray, 1.3, 5)
36
  face_areas=[]
 
45
  return required_image
46
 
47
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
  #1) Images captured from mobile is passed as parameter to the below function in the API call. It returns the similarity measure between given images.
49
  #2) The image is passed to the function in base64 encoding, Code for decoding the image is provided within the function.
50
  #3) Define an object to your siamese network here in the function and load the weight from the trained network, set it in evaluation mode.
 
52
  #5) For loading your model use the current_path+'your model file name', anyhow detailed example is given in comments to the function
53
  #Caution: Don't change the definition or function name; for loading the model use the current_path for path example is given in comments to the function
54
  def get_similarity(img1, img2):
55
+ device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
56
+
57
+ det_img1 = detected_face(img1)
58
+ det_img2 = detected_face(img2)
59
+ if(det_img1 == 0 or det_img2 == 0):
60
+ det_img1 = Image.fromarray(cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY))
61
+ det_img2 = Image.fromarray(cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY))
62
+ face1 = trnscm(det_img1).unsqueeze(0)
63
+ face2 = trnscm(det_img2).unsqueeze(0)
64
+ ##########################################################################################
65
+ ##Example for loading a model using weight state dictionary: ##
66
+ ## feature_net = light_cnn() #Example Network ##
67
+ ## model = torch.load(current_path + '/siamese_model.t7', map_location=device) ##
68
+ ## feature_net.load_state_dict(model['net_dict']) ##
69
+ ## ##
70
+ ##current_path + '/<network_definition>' is path of the saved model if present in ##
71
+ ##the same path as this file, we recommend to put in the same directory ##
72
+ ##########################################################################################
73
+ ##########################################################################################
74
+
75
+ # YOUR CODE HERE, load the model
76
+
77
+ # YOUR CODE HERE, return similarity measure using your model
78
+
79
+ return 0
80
 
81
  #1) Image captured from mobile is passed as parameter to this function in the API call, It returns the face class in the string form ex: "Person1"
82
  #2) The image is passed to the function in base64 encoding, Code to decode the image provided within the function
 
85
  #5) Along with the siamese, you need the classifier as well, which is to be finetuned with the faces that you are training
86
  ##Caution: Don't change the definition or function name; for loading the model use the current_path for path example is given in comments to the function
87
  def get_face_class(img1):
88
+ device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
89
+
90
+ det_img1 = detected_face(img1)
91
+ if(det_img1 == 0):
92
+ det_img1 = Image.fromarray(cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY))
93
+ ##YOUR CODE HERE, return face class here
94
+ ##Hint: you need a classifier finetuned for your classes, it takes o/p of siamese as i/p to it
95
+ ##Better Hint: Siamese experiment is covered in one of the labs
96
+ return "YET TO BE CODED"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/Hackathon_setup/face_recognition_model.py CHANGED
@@ -1,55 +1,31 @@
 
1
  import torch
 
2
  import torch.nn as nn
3
  import torch.nn.functional as F
4
  from torchvision import transforms
 
5
 
6
- def rgb2gray(image):
7
- return image.convert("L")
 
8
 
9
-
10
- trnscm = transforms.Compose([rgb2gray, transforms.Resize((100, 100)), transforms.ToTensor()])
11
-
12
- class Siamese(nn.Module):
13
  def __init__(self):
14
- super().__init__()
15
- self.features = nn.Sequential(
16
- nn.Conv2d(1, 16, kernel_size=5, padding=2),
17
- nn.BatchNorm2d(16),
18
- nn.ReLU(inplace=True),
19
- nn.MaxPool2d(2),
20
- nn.Conv2d(16, 32, kernel_size=3, padding=1),
21
- nn.BatchNorm2d(32),
22
- nn.ReLU(inplace=True),
23
- nn.MaxPool2d(2),
24
- nn.Conv2d(32, 64, kernel_size=3, padding=1),
25
- nn.BatchNorm2d(64),
26
- nn.ReLU(inplace=True),
27
- nn.MaxPool2d(2),
28
- )
29
- self.embedding = nn.Sequential(
30
- nn.Flatten(),
31
- nn.Linear(64 * 12 * 12, 256),
32
- nn.ReLU(inplace=True),
33
- nn.Dropout(0.25),
34
- nn.Linear(256, 128),
35
- )
36
 
37
  def forward(self, x):
38
- x = self.features(x)
39
- x = self.embedding(x)
40
- return F.normalize(x, p=2, dim=1)
41
 
42
  ##########################################################################################################
43
  ## Sample classification network (Specify if you are using a pytorch classifier during the training) ##
44
  ## classifier = nn.Sequential(nn.Linear(64, 64), nn.BatchNorm1d(64), nn.ReLU(), nn.Linear...) ##
45
  ##########################################################################################################
46
 
47
- classifier = nn.Sequential(
48
- nn.Linear(128, 64),
49
- nn.BatchNorm1d(64),
50
- nn.ReLU(inplace=True),
51
- nn.Linear(64, 7),
52
- )
53
 
54
  # Definition of classes as dictionary
55
- classes = ['Person1', 'Person2', 'Person3', 'Person4', 'Person5', 'Person6', 'Person7']
 
1
+ import math
2
  import torch
3
+ import torchvision
4
  import torch.nn as nn
5
  import torch.nn.functional as F
6
  from torchvision import transforms
7
+ # Add more imports if required
8
 
9
+ # Sample Transformation function
10
+ # YOUR CODE HERE for changing the Transformation values.
11
+ trnscm = transforms.Compose([transforms.Resize((100,100)), transforms.ToTensor()])
12
 
13
+ ##Example Network
14
+ class Siamese(torch.nn.Module):
 
 
15
  def __init__(self):
16
+ super(Siamese, self).__init__()
17
+ #YOUR CODE HERE
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
  def forward(self, x):
20
+ pass # remove 'pass' once you have written your code
21
+ #YOUR CODE HERE
 
22
 
23
  ##########################################################################################################
24
  ## Sample classification network (Specify if you are using a pytorch classifier during the training) ##
25
  ## classifier = nn.Sequential(nn.Linear(64, 64), nn.BatchNorm1d(64), nn.ReLU(), nn.Linear...) ##
26
  ##########################################################################################################
27
 
28
+ # YOUR CODE HERE for pytorch classifier
 
 
 
 
 
29
 
30
  # Definition of classes as dictionary
31
+ classes = ['person1','person2','person3','person4','person5','person6','person7']
app/Hackathon_setup/siamese_model.pth DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:540cd55c4c19e93208315ef83ed6eba15a929da696db72dc9e36623dc861d19f
3
- size 9674169
 
 
 
 
app/config.py CHANGED
@@ -1,17 +1,25 @@
1
- class Settings:
2
- API_V1_STR = "/api/v1"
3
 
 
 
 
 
 
 
 
4
  # BACKEND_CORS_ORIGINS is a comma-separated list of origins
5
  # e.g: http://localhost,http://localhost:4200,http://localhost:3000
6
- BACKEND_CORS_ORIGINS = [
7
- "http://localhost:3000",
8
- "http://localhost:8000",
9
- "http://localhost:7860",
10
- "https://localhost:3000",
11
- "https://localhost:8000",
12
- "https://localhost:7860",
13
  ]
14
 
15
- PROJECT_NAME = "Recognition API"
 
 
 
16
 
17
  settings = Settings()
 
1
+ import sys
2
+ from typing import List
3
 
4
+ from pydantic import AnyHttpUrl, BaseSettings
5
+
6
+ class Settings(BaseSettings):
7
+ API_V1_STR: str = "/api/v1"
8
+
9
+ # Meta
10
+
11
  # BACKEND_CORS_ORIGINS is a comma-separated list of origins
12
  # e.g: http://localhost,http://localhost:4200,http://localhost:3000
13
+ BACKEND_CORS_ORIGINS: List[AnyHttpUrl] = [
14
+ "http://localhost:3000", # type: ignore
15
+ "http://localhost:8000", # type: ignore
16
+ "https://localhost:3000", # type: ignore
17
+ "https://localhost:8000", # type: ignore
 
 
18
  ]
19
 
20
+ PROJECT_NAME: str = "Recognition API"
21
+
22
+ class Config:
23
+ case_sensitive = True
24
 
25
  settings = Settings()
app/main.py CHANGED
@@ -1,122 +1,133 @@
1
  import sys
2
  from pathlib import Path
3
- from uuid import uuid4
4
-
5
  sys.path.append(str(Path(__file__).resolve().parent.parent))
 
 
6
 
7
- from fastapi import FastAPI, HTTPException, Request, File, UploadFile
8
  from fastapi.staticfiles import StaticFiles
9
  from fastapi.templating import Jinja2Templates
10
  from fastapi.middleware.cors import CORSMiddleware
11
  from app.config import settings
 
12
  from app.Hackathon_setup import face_recognition, exp_recognition
13
 
14
  import numpy as np
15
  from PIL import Image
16
 
17
- BASE_DIR = Path(__file__).resolve().parent
18
- STATIC_DIR = BASE_DIR / "static"
19
- TEMPLATES_DIR = BASE_DIR / "templates"
20
- STATIC_DIR.mkdir(parents=True, exist_ok=True)
21
 
22
  app = FastAPI(
23
  title=settings.PROJECT_NAME, openapi_url=f"{settings.API_V1_STR}/openapi.json"
24
  )
25
 
26
  # To store files uploaded by users
27
- app.mount("/static", StaticFiles(directory=str(STATIC_DIR)), name="static")
28
 
29
  # To access Templates directory
30
- templates = Jinja2Templates(directory=str(TEMPLATES_DIR))
31
-
32
- def render_template(request: Request, template_name: str, context: dict | None = None):
33
- return templates.TemplateResponse(
34
- name=template_name,
35
- request=request,
36
- context=context or {}
37
- )
38
-
39
-
40
- def _file_extension(filename: str) -> str:
41
- suffix = Path(filename or "").suffix.lower()
42
- return suffix if suffix in {".jpg", ".jpeg", ".png", ".bmp", ".webp"} else ".jpg"
43
-
44
-
45
- async def save_upload_image(upload: UploadFile) -> tuple[np.ndarray, str]:
46
- if not upload.content_type or "image" not in upload.content_type:
47
- raise HTTPException(status_code=400, detail="Please upload a valid image file.")
48
-
49
- contents = await upload.read()
50
- filename = f"{uuid4().hex}{_file_extension(upload.filename)}"
51
- filepath = STATIC_DIR / filename
52
- filepath.write_bytes(contents)
53
-
54
- try:
55
- image = Image.open(filepath).convert("RGB")
56
- except Exception as exc:
57
- filepath.unlink(missing_ok=True)
58
- raise HTTPException(status_code=400, detail="The uploaded file could not be read as an image.") from exc
59
 
60
- return np.asarray(image).astype(np.uint8), f"../static/{filename}"
 
 
 
61
 
62
 
63
  #################################### Home Page endpoints #################################################
64
  @app.get("/")
65
  async def root(request: Request):
66
- return render_template(request, "index.html")
67
 
68
 
69
  #################################### Face Similarity endpoints #################################################
70
  @app.get("/similarity/")
71
  async def similarity_root(request: Request):
72
- return render_template(request, "similarity.html")
73
 
74
 
75
  @app.post("/predict_similarity/")
76
  async def create_upload_files(request: Request, file1: UploadFile = File(...), file2: UploadFile = File(...)):
77
- img1, simi_filename1 = await save_upload_image(file1)
78
- img2, simi_filename2 = await save_upload_image(file2)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  result = face_recognition.get_similarity(img1, img2)
 
80
 
81
- return render_template(request, "predict_similarity.html", {
82
- "result": np.round(result, 3),
83
- "simi_filename1": simi_filename1,
84
- "simi_filename2": simi_filename2,
85
- })
86
 
87
 
88
  #################################### Face Recognition endpoints #################################################
89
  @app.get("/face_recognition/")
90
  async def face_recognition_root(request: Request):
91
- return render_template(request, "face_recognition.html")
92
 
93
 
94
  @app.post("/predict_face_recognition/")
95
  async def create_upload_files(request: Request, file3: UploadFile = File(...)):
96
- img1, face_rec_filename = await save_upload_image(file3)
 
 
 
 
 
 
 
 
 
 
97
  result = face_recognition.get_face_class(img1)
 
98
 
99
- return render_template(request, "predict_face_recognition.html", {
100
- "result": result,
101
- "face_rec_filename": face_rec_filename,
102
- })
103
 
104
 
105
  #################################### Expresion Recognition endpoints #################################################
106
  @app.get("/expr_recognition/")
107
  async def expr_recognition_root(request: Request):
108
- return render_template(request, "expr_recognition.html")
109
 
110
 
111
  @app.post("/predict_expr_recognition/")
112
  async def create_upload_files(request: Request, file4: UploadFile = File(...)):
113
- img1, expr_rec_filename = await save_upload_image(file4)
 
 
 
 
 
 
 
 
 
 
114
  result = exp_recognition.get_expression(img1)
 
115
 
116
- return render_template(request, "predict_expr_recognition.html", {
117
- "result": result,
118
- "expr_rec_filename": expr_rec_filename,
119
- })
120
 
121
 
122
 
@@ -134,4 +145,4 @@ if settings.BACKEND_CORS_ORIGINS:
134
  # Start app
135
  if __name__ == "__main__":
136
  import uvicorn
137
- uvicorn.run(app, host="0.0.0.0", port=7860)
 
1
  import sys
2
  from pathlib import Path
 
 
3
  sys.path.append(str(Path(__file__).resolve().parent.parent))
4
+ #print(sys.path)
5
+ from typing import Any
6
 
7
+ from fastapi import FastAPI, Request, APIRouter, File, UploadFile
8
  from fastapi.staticfiles import StaticFiles
9
  from fastapi.templating import Jinja2Templates
10
  from fastapi.middleware.cors import CORSMiddleware
11
  from app.config import settings
12
+ from app import __version__
13
  from app.Hackathon_setup import face_recognition, exp_recognition
14
 
15
  import numpy as np
16
  from PIL import Image
17
 
 
 
 
 
18
 
19
  app = FastAPI(
20
  title=settings.PROJECT_NAME, openapi_url=f"{settings.API_V1_STR}/openapi.json"
21
  )
22
 
23
  # To store files uploaded by users
24
+ app.mount("/static", StaticFiles(directory="app/static"), name="static")
25
 
26
  # To access Templates directory
27
+ templates = Jinja2Templates(directory="app/templates")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
 
29
+ simi_filename1 = None
30
+ simi_filename2 = None
31
+ face_rec_filename = None
32
+ expr_rec_filename = None
33
 
34
 
35
  #################################### Home Page endpoints #################################################
36
  @app.get("/")
37
  async def root(request: Request):
38
+ return templates.TemplateResponse("index.html", {'request': request,})
39
 
40
 
41
  #################################### Face Similarity endpoints #################################################
42
  @app.get("/similarity/")
43
  async def similarity_root(request: Request):
44
+ return templates.TemplateResponse("similarity.html", {'request': request,})
45
 
46
 
47
  @app.post("/predict_similarity/")
48
  async def create_upload_files(request: Request, file1: UploadFile = File(...), file2: UploadFile = File(...)):
49
+ global simi_filename1
50
+ global simi_filename2
51
+
52
+ if 'image' in file1.content_type:
53
+ contents = await file1.read()
54
+ simi_filename1 = 'app/static/' + file1.filename
55
+ with open(simi_filename1, 'wb') as f:
56
+ f.write(contents)
57
+
58
+ if 'image' in file2.content_type:
59
+ contents = await file2.read()
60
+ simi_filename2 = 'app/static/' + file2.filename
61
+ with open(simi_filename2, 'wb') as f:
62
+ f.write(contents)
63
+
64
+ img1 = Image.open(simi_filename1)
65
+ img1 = np.array(img1).reshape(img1.size[1], img1.size[0], 3).astype(np.uint8)
66
+
67
+ img2 = Image.open(simi_filename2)
68
+ img2 = np.array(img2).reshape(img2.size[1], img2.size[0], 3).astype(np.uint8)
69
+
70
  result = face_recognition.get_similarity(img1, img2)
71
+ #print(result)
72
 
73
+ return templates.TemplateResponse("predict_similarity.html", {"request": request,
74
+ "result": np.round(result, 3),
75
+ "simi_filename1": '../static/'+file1.filename,
76
+ "simi_filename2": '../static/'+file2.filename,})
 
77
 
78
 
79
  #################################### Face Recognition endpoints #################################################
80
  @app.get("/face_recognition/")
81
  async def face_recognition_root(request: Request):
82
+ return templates.TemplateResponse("face_recognition.html", {'request': request,})
83
 
84
 
85
  @app.post("/predict_face_recognition/")
86
  async def create_upload_files(request: Request, file3: UploadFile = File(...)):
87
+ global face_rec_filename
88
+
89
+ if 'image' in file3.content_type:
90
+ contents = await file3.read()
91
+ face_rec_filename = 'app/static/' + file3.filename
92
+ with open(face_rec_filename, 'wb') as f:
93
+ f.write(contents)
94
+
95
+ img1 = Image.open(face_rec_filename)
96
+ img1 = np.array(img1).reshape(img1.size[1], img1.size[0], 3).astype(np.uint8)
97
+
98
  result = face_recognition.get_face_class(img1)
99
+ print(result)
100
 
101
+ return templates.TemplateResponse("predict_face_recognition.html", {"request": request,
102
+ "result": result,
103
+ "face_rec_filename": '../static/'+file3.filename,})
 
104
 
105
 
106
  #################################### Expresion Recognition endpoints #################################################
107
  @app.get("/expr_recognition/")
108
  async def expr_recognition_root(request: Request):
109
+ return templates.TemplateResponse("expr_recognition.html", {'request': request,})
110
 
111
 
112
  @app.post("/predict_expr_recognition/")
113
  async def create_upload_files(request: Request, file4: UploadFile = File(...)):
114
+ global expr_rec_filename
115
+
116
+ if 'image' in file4.content_type:
117
+ contents = await file4.read()
118
+ expr_rec_filename = 'app/static/' + file4.filename
119
+ with open(expr_rec_filename, 'wb') as f:
120
+ f.write(contents)
121
+
122
+ img1 = Image.open(expr_rec_filename)
123
+ img1 = np.array(img1).reshape(img1.size[1], img1.size[0], 3).astype(np.uint8)
124
+
125
  result = exp_recognition.get_expression(img1)
126
+ print(result)
127
 
128
+ return templates.TemplateResponse("predict_expr_recognition.html", {"request": request,
129
+ "result": result,
130
+ "expr_rec_filename": '../static/'+file4.filename,})
 
131
 
132
 
133
 
 
145
  # Start app
146
  if __name__ == "__main__":
147
  import uvicorn
148
+ uvicorn.run(app, host="0.0.0.0", port=8001)
app/static/Angelina_001.jpg DELETED
Binary file (36 kB)
 
app/static/Angelina_002.jpg DELETED
Binary file (38.8 kB)
 
app/static/Angelina_003.jpg DELETED
Binary file (33.8 kB)
 
app/static/Angelina_004.jpg DELETED
Binary file (5.68 kB)
 
app/static/Angelina_005.jpg DELETED
Binary file (35.7 kB)
 
app/static/Brad_001.jpg DELETED
Binary file (36.7 kB)
 
app/static/Brad_002.jpg DELETED
Binary file (37.5 kB)
 
app/static/Brad_003.jpg DELETED
Binary file (22 kB)
 
app/static/Brad_004.jpg DELETED
Binary file (30.1 kB)
 
app/static/Brad_005.jpg DELETED
Binary file (20.8 kB)
 
app/static/Denzel_001.jpg DELETED
Binary file (29.8 kB)
 
app/static/Denzel_002.jpg DELETED
Binary file (21 kB)
 
app/static/Denzel_003.jpg DELETED
Binary file (32.6 kB)
 
app/static/Denzel_004.jpg DELETED
Binary file (20.7 kB)
 
app/static/Denzel_005.jpg DELETED
Binary file (18.5 kB)
 
app/static/Hugh_001.jpg DELETED
Binary file (33.8 kB)
 
app/static/Hugh_002.jpg DELETED
Binary file (29.1 kB)
 
app/static/Hugh_003.jpg DELETED
Binary file (28.5 kB)
 
app/static/Hugh_004.jpg DELETED
Binary file (24.9 kB)
 
app/static/Hugh_005.jpg DELETED
Binary file (29.7 kB)
 
app/static/Jennifer_001.jpg DELETED
Binary file (33.7 kB)
 
app/static/Jennifer_002.jpg DELETED
Binary file (26.9 kB)
 
app/static/Jennifer_003.jpg DELETED
Binary file (66.6 kB)
 
app/static/Jennifer_004.jpg DELETED
Binary file (49.9 kB)
 
app/static/Jennifer_005.jpg DELETED
Binary file (39.4 kB)
 
app/static/Johnny_001.jpg DELETED
Binary file (24.9 kB)
 
app/static/Johnny_002.jpg DELETED
Binary file (34.2 kB)
 
app/static/Johnny_003.jpg DELETED
Binary file (5.08 kB)
 
app/static/Johnny_004.jpg DELETED
Binary file (33.5 kB)
 
app/static/Johnny_005.jpg DELETED
Binary file (36.5 kB)
 
app/static/Kate_001.jpg DELETED
Binary file (35.8 kB)
 
app/static/Kate_002.jpg DELETED
Binary file (26.7 kB)
 
app/static/Kate_003.jpg DELETED
Binary file (29.6 kB)
 
app/static/Kate_004.jpg DELETED
Binary file (41.8 kB)
 
app/static/Kate_005.jpg DELETED
Binary file (29.1 kB)
 
app/static/Leonardo_001.jpg DELETED
Binary file (23.6 kB)
 
app/static/Leonardo_002.jpg DELETED
Binary file (20.7 kB)
 
app/static/Leonardo_003.jpg DELETED
Binary file (24.1 kB)