vinay0123 commited on
Commit
f18f5be
·
verified ·
1 Parent(s): 184f404

Upload 5 files

Browse files
Files changed (5) hide show
  1. Dockerfile +25 -0
  2. Procfile.txt +1 -0
  3. app.py +388 -0
  4. haarcascade_frontalface_default.xml +0 -0
  5. requirements.txt +11 -0
Dockerfile ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Base image
2
+ FROM python:3.9-slim
3
+
4
+ # Set working directory
5
+ WORKDIR /app
6
+
7
+ # Copy requirement files
8
+ COPY requirements.txt .
9
+
10
+ # Install dependencies
11
+ RUN pip install --no-cache-dir -r requirements.txt
12
+
13
+ # Copy the rest of the code
14
+ COPY . .
15
+
16
+ # Expose port (Spaces expects 7860 or 5000)
17
+ EXPOSE 7860
18
+
19
+ # Set environment variable for Flask
20
+ ENV FLASK_APP=app.py
21
+ ENV FLASK_RUN_PORT=7860
22
+ ENV FLASK_RUN_HOST=0.0.0.0
23
+
24
+ # Run the Flask app
25
+ CMD ["flask", "run"]
Procfile.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ web: gunicorn app:app
app.py ADDED
@@ -0,0 +1,388 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import base64
2
+ import os
3
+ import cv2
4
+ import numpy as np
5
+ from flask import Flask, request, jsonify
6
+ from mtcnn.mtcnn import MTCNN
7
+ from keras_facenet import FaceNet
8
+ from sklearn.metrics.pairwise import cosine_similarity
9
+ from flask_cors import CORS
10
+ from flask_pymongo import PyMongo
11
+ from ultralytics import YOLO
12
+ from bson.objectid import ObjectId # Import ObjectId for MongoDB
13
+ import tensorflow as tf
14
+ from tensorflow.keras.models import Sequential
15
+ from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense
16
+ from sklearn.preprocessing import LabelEncoder
17
+ from datetime import datetime
18
+
19
+ app = Flask(__name__)
20
+ CORS(app)
21
+
22
+ # Initialize MTCNN detector and FaceNet model
23
+ detector = MTCNN()
24
+ embedder = FaceNet()
25
+
26
+ # Configure MongoDB
27
+ app.config["MONGO_URI"] = "mongodb+srv://nanduvinay719:76qqKRX4zC97yQun@travis.744fuyn.mongodb.net/?retryWrites=true&w=majority&appName=travis" #config setting
28
+ # Update with your MongoDB URI
29
+ mongo = PyMongo(app)#initialize
30
+ haar_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
31
+
32
+ def create_cnn_embedding_model():
33
+ model = Sequential([
34
+ Conv2D(32, (3, 3), activation='relu', input_shape=(160, 160, 1)),
35
+ MaxPooling2D(2, 2),
36
+ Conv2D(64, (3, 3), activation='relu'),
37
+ MaxPooling2D(2, 2),
38
+ Flatten(),
39
+ Dense(512, activation='relu'),
40
+ Dense(512, activation='linear') # Final dense layer to produce a 512-dimensional embedding
41
+ ])
42
+ return model
43
+ cnn_model = create_cnn_embedding_model()
44
+ cnn_model.compile(optimizer='adam', loss='mse')
45
+ # Using MSE loss as we are not training for classification
46
+ def cosine(embedding1, embedding2):
47
+ dot_product = np.dot(embedding1, embedding2)
48
+ norm1 = np.linalg.norm(embedding1)
49
+ norm2 = np.linalg.norm(embedding2)
50
+ similarity = dot_product / (norm1 * norm2)
51
+ return similarity
52
+ @app.route('/CNN-login', methods=['POST'])
53
+ def cnnlogin():
54
+ # Check for uploaded image
55
+ if 'image' not in request.files:
56
+ return jsonify({"error": "No image provided"}), 400
57
+
58
+ file = request.files['image']
59
+ rollnumber = request.form['rollnumber']
60
+ rollnumber = rollnumber.upper()
61
+
62
+ if not rollnumber:
63
+ return jsonify({"error": "Roll number is required"}), 400
64
+
65
+ # Fetch user data from MongoDB
66
+ user_data = mongo.db.data.find_one({"RollNumber": rollnumber}, {"CNN_embeddings": 1, "username": 1})
67
+ if user_data is None:
68
+ return jsonify({"error": "User not found"}), 404
69
+ stored_cnn_embedding = np.array(user_data["CNN_embeddings"])# Convert stored embeddings to NumPy array
70
+ username = user_data["username"]
71
+ print(username)
72
+ # Decode image
73
+ image_data = file.read()
74
+ image_array = np.frombuffer(image_data, np.uint8)
75
+ image = cv2.imdecode(image_array, cv2.IMREAD_COLOR)
76
+ if image is None:
77
+ return jsonify({"error": "Invalid image"}), 400
78
+ # Initialize Haar Cascade
79
+
80
+ # Detect the face using Haar Cascade
81
+ gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
82
+ faces = haar_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(100, 100))
83
+ if len(faces) == 0:
84
+ return jsonify({"error": "No face detected"}), 400
85
+
86
+ # Process the first detected face
87
+ x, y, w, h = faces[0]
88
+ cropped_face = cv2.resize(image[y:y+h, x:x+w], (160, 160))
89
+
90
+ # Preprocess face for CNN model
91
+ gray_face = cv2.cvtColor(cropped_face, cv2.COLOR_BGR2GRAY).reshape(160, 160, 1)
92
+ normalized_face = np.expand_dims(gray_face, axis=-1)
93
+ normalized_face = np.expand_dims(normalized_face, axis=0)
94
+ normalized_face = normalized_face / 255.0 # Normalize pixel values to [0, 1]
95
+ # Generate embedding using the CNN model
96
+ cnn_embedding = cnn_model.predict(normalized_face)[0]
97
+ print("CNN shape: ",cnn_embedding.shape,"Stored shape: ",stored_cnn_embedding.shape)
98
+ # Compare the embedding with stored embeddings
99
+ similarity = cosine(cnn_embedding, stored_cnn_embedding)
100
+ print(f"Similarity: {similarity}")
101
+
102
+ # Set a threshold for recognition
103
+ recognition_threshold = 0.94 # Adjust this threshold as needed
104
+ if similarity > recognition_threshold:
105
+ return jsonify({"name": username, "probability": float(similarity)}), 200
106
+ else:
107
+ return jsonify({"error": "Face not recognized", "probability": float(similarity)}), 401
108
+
109
+ @app.route('/login', methods=['POST'])
110
+ def recognizeLogin():
111
+ if 'image' not in request.files:
112
+ return jsonify({"error": "No image provided"}), 400
113
+
114
+ file = request.files['image']
115
+ name = request.form["rollnumber"]
116
+ name = name.upper()
117
+ image_data = file.read()
118
+ image_array = np.frombuffer(image_data, np.uint8)
119
+ image = cv2.imdecode(image_array, cv2.IMREAD_COLOR)
120
+ if image is None:
121
+ return jsonify({"error": "Invalid image"}), 400
122
+ results = recognize_faces_in_image(image)
123
+ print(results[0])
124
+ print(results[0]['name'],name)
125
+ if (results[0]['name']==name):
126
+ print("done")
127
+ today = datetime.now().strftime("%Y-%m-%d")
128
+ mongo.db.attendance1.update_one(
129
+ {'username': results[0]['name']},
130
+ {'$set': {today: True}}, # Mark as present for today
131
+ upsert=True
132
+ )
133
+ return jsonify({"name": name, "probability": results[0]['probability']}), 200
134
+ else:
135
+ return jsonify({'name':"user not recognised"})
136
+
137
+ @app.route('/register', methods=['POST'])
138
+ def register():
139
+ rollnumber = request.form["RollNumber"]
140
+ username = request.form['Username']
141
+ fathername = request.form["FatherName"]
142
+ phoneno = request.form["phoneNumber"]
143
+ facenet_embeddings, cnn_embeddings = [], []
144
+ stored_image = None # To store the first grayscale image
145
+
146
+ print(username)
147
+ # Check if user already exists
148
+ existing_user = mongo.db.data.find_one({"username": username}, {"_id": 0})
149
+ if existing_user:
150
+ return jsonify({"error": f"User '{username}' already exists"}), 400
151
+
152
+ # Process uploaded images
153
+ for i in range(5): # Expecting 5 images
154
+ try:
155
+ image_file = request.files[f'image{i}']
156
+ except KeyError:
157
+ return jsonify({"error": f"Missing image{i} in the request"}), 400
158
+
159
+ image_data = image_file.read()
160
+ image_array = np.frombuffer(image_data, np.uint8)
161
+ image = cv2.imdecode(image_array, cv2.IMREAD_COLOR)
162
+
163
+ # Face detection using MTCNN for FaceNet
164
+ mtcnn_faces = detector.detect_faces(image)
165
+ if mtcnn_faces:
166
+ # Get the first detected face for FaceNet embedding
167
+ x, y, w, h = mtcnn_faces[0]['box']
168
+ x, y = max(0, x), max(0, y)
169
+ cropped_face = cv2.resize(image[y:y+h, x:x+w], (160, 160))
170
+ rgb_face = cv2.cvtColor(cropped_face, cv2.COLOR_BGR2RGB)
171
+
172
+ # Get FaceNet embedding
173
+ facenet_embedding = embedder.embeddings(np.expand_dims(rgb_face, axis=0)).flatten()
174
+ facenet_embeddings.append(facenet_embedding)
175
+ # Face detection using Haar Cascade for CNN
176
+ gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
177
+ haar_faces = haar_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(100, 100))
178
+ if len(haar_faces) > 0:
179
+ x, y, w, h = haar_faces[0]
180
+ cropped_face = cv2.resize(image[y:y+h, x:x+w], (160, 160))
181
+ gray_face = cv2.cvtColor(cropped_face, cv2.COLOR_BGR2GRAY).reshape(160, 160, 1)
182
+ normalized_face=np.expand_dims(gray_face, axis=-1) #dimnesion
183
+ normalized_face=np.expand_dims(normalized_face, axis=0) #batch
184
+ normalized_face = normalized_face / 255.0 #0-1
185
+ # Get CNN embedding
186
+ cnn_embedding = cnn_model.predict(normalized_face)[0]
187
+ cnn_embeddings.append(cnn_embedding)
188
+ # Save the first grayscale face as base64
189
+ if stored_image is None:
190
+ _, buffer = cv2.imencode('.jpg', cv2.cvtColor(cropped_face, cv2.COLOR_BGR2GRAY))
191
+ stored_image = base64.b64encode(buffer).decode('utf-8')
192
+
193
+ if not facenet_embeddings or not cnn_embeddings:
194
+ return jsonify({"error": "No valid faces detected in the uploaded images"}), 400
195
+
196
+ # Calculate mean embeddings
197
+ mean_facenet_embedding = np.mean(facenet_embeddings, axis=0).astype(float).tolist()
198
+ mean_cnn_embedding = np.mean(cnn_embeddings, axis=0).astype(float).tolist()
199
+ cnn_model.save_weights('cnn_model.weights.h5')
200
+ # Create user data
201
+ id = mongo.db.data.count_documents({}) + 1
202
+ user_data = {
203
+ 'RollNumber': rollnumber,
204
+ 'username': username,
205
+ 'FatherName': fathername,
206
+ 'phoneNumber': phoneno,
207
+ 'embeddings': mean_facenet_embedding,
208
+ 'CNN_embeddings': mean_cnn_embedding,
209
+ 'stored_image': stored_image,
210
+ 'id': id
211
+ }
212
+
213
+ # Insert into MongoDB
214
+ mongo.db.data.insert_one(user_data)
215
+ mongo.db.attendance1.insert_one({"username": rollnumber, "id": id})
216
+ # Reload embeddings
217
+ reload_embeddings()
218
+
219
+ return jsonify({"message": "User registered successfully!"}), 201
220
+
221
+ # Load embeddings from MongoDB for recognition
222
+ @app.route('/get_users', methods=['GET'])
223
+ def get_users():
224
+ users = list(mongo.db.data.find({}, {"id": 1, "username": 1})) # Fetch only _id and username
225
+ user_count = len(users)
226
+ return jsonify({"users": [user['username'] for user in users], "count": user_count})
227
+
228
+ def load_embeddings_from_db():
229
+ users = list(mongo.db.data.find())
230
+ face_data = []# facenet embeddings
231
+ labels = [] # id 1,2,3,..
232
+ names = {} #dict of id and roll number
233
+ # {"1":vinay,"2":shahank}
234
+ for user in users:
235
+ face_data.append(user["embeddings"])
236
+ labels.append(user['id']) # Keep the ObjectId
237
+ names[user['id']] = user['RollNumber'] # Use ObjectId as key
238
+
239
+ return (face_data, labels, names) if face_data else ([], [], {})
240
+
241
+ # Load face embeddings from MongoDB initially
242
+ face_data, labels, names = load_embeddings_from_db()
243
+ cnn_model.load_weights('cnn_model.weights.h5')
244
+
245
+
246
+
247
+ # Reload embeddings to update after a new registration
248
+ def reload_embeddings():
249
+ global face_data, labels, names
250
+ cnn_model.load_weights('cnn_model.weights.h5')
251
+ face_data, labels, names = load_embeddings_from_db()
252
+
253
+ # Recognize faces using MongoDB-stored embeddings
254
+ model = YOLO('yolov5s.pt') # Replace with your YOLO model path
255
+
256
+
257
+ @app.route('/crowd', methods=['POST'])
258
+ def upload_image():
259
+ if 'image' not in request.files:
260
+ return jsonify({'error': 'No image provided'}), 400
261
+
262
+ # Read the image from the request
263
+ file = request.files['image']
264
+ img_array = np.frombuffer(file.read(), np.uint8)
265
+ img = cv2.imdecode(img_array, cv2.IMREAD_COLOR)
266
+
267
+ # Perform YOLO detection
268
+ results = model.predict(source=img, conf=0.5)
269
+ print(results)# Confidence threshold
270
+ detections = results[0].boxes.xyxy # Bounding boxes
271
+ labels = results[0].boxes.cls.cpu().numpy() # Class labels
272
+ human_boxes = [box for box, label in zip(detections, labels) if int(label) == 0] # Filter humans
273
+
274
+ # Draw bounding boxes for humans only
275
+ human_count = 0
276
+ for box in human_boxes:
277
+ x1, y1, x2, y2 = map(int, box[:4])
278
+ cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2)
279
+ human_count += 1
280
+
281
+ # Convert the processed image to Base64
282
+ _, buffer = cv2.imencode('.jpg', img)
283
+ encoded_image = base64.b64encode(buffer).decode('utf-8')
284
+
285
+ return jsonify({'count': human_count, 'image': encoded_image})
286
+
287
+ def recognize_faces_in_image(image):
288
+ if len(face_data) == 0:
289
+ return [{"name": "No registered faces", "probability": 0.0}]
290
+
291
+ faces = detector.detect_faces(image)
292
+ results = []
293
+ for face in faces:
294
+ x, y, width, height = face['box']
295
+ cropped_face = cv2.resize(image[y:y+height, x:x+width], (160, 160))
296
+
297
+ # Convert cropped face to RGB
298
+ rgb_face = cv2.cvtColor(cropped_face, cv2.COLOR_BGR2RGB)
299
+ embedding = embedder.embeddings(np.expand_dims(rgb_face, axis=0)).flatten() # Use RGB face here
300
+
301
+ # Compare with stored embeddings in MongoDB
302
+ similarities = cosine_similarity([embedding], face_data)
303
+ idx = np.argmax(similarities)
304
+ best_match = similarities[0][idx]
305
+
306
+ if best_match > 0.7:
307
+ recognized_id = labels[idx] # Get the ObjectId
308
+ recognized_name = names[recognized_id] # Use ObjectId to get the username
309
+ results.append({"name": recognized_name, "probability": float(best_match)})
310
+ else:
311
+ results.append({"name": "Unknown", "probability": float(best_match)})
312
+ return results
313
+
314
+ @app.route('/users/<username>/images', methods=['GET'])
315
+ def get_user_images(username):
316
+ username = str(username).upper()
317
+ details = mongo.db.data.find_one({"username": username},{"_id":0,"embeddings":0,"CNN_embeddings":0})
318
+ if not details:
319
+ details = mongo.db.data.find_one({"RollNumber": username},{"_id":0,"embeddings":0,"CNN_embeddings":0})
320
+ if not details:
321
+ return jsonify({"error": "User not found"}), 404
322
+ print(details["RollNumber"])
323
+ # Retrieve the stored image in base64 format
324
+ return jsonify({"details": details})
325
+
326
+ #multi face
327
+ @app.route('/recognize', methods=['POST'])
328
+ def recognize():
329
+ if 'image' not in request.files:
330
+ return jsonify({"error": "No image provided"}), 400
331
+ file = request.files['image']
332
+ image_data = file.read()
333
+ image_array = np.frombuffer(image_data, np.uint8)
334
+ image = cv2.imdecode(image_array, cv2.IMREAD_COLOR)
335
+
336
+ if image is None:
337
+ return jsonify({"error": "Invalid image"}), 400
338
+
339
+ results = recognize_faces_in_image(image)
340
+ today = datetime.now().strftime("%Y-%m-%d")
341
+ for result in results:
342
+ if result['name'] != "Unknown": # Only log attendance for recognized users
343
+ mongo.db.attendance1.update_one(
344
+ {'username': result['name']},
345
+ {'$set': {today: True}}, # Mark as present for today
346
+ upsert=True
347
+ )
348
+ return jsonify(results)
349
+
350
+ # user multi face
351
+ @app.route('/user_recognize', methods=['POST'])
352
+ def user_recognize():
353
+ if 'image' not in request.files:
354
+ return jsonify({"error": "No image provided"},), 400
355
+
356
+ file = request.files['image']
357
+ image_data = file.read()
358
+ image_array = np.frombuffer(image_data, np.uint8)
359
+ image = cv2.imdecode(image_array, cv2.IMREAD_COLOR)
360
+
361
+ if image is None:
362
+ return jsonify({"error": "Invalid image"}), 400
363
+
364
+ results = recognize_faces_in_image(image)
365
+ return jsonify(results)
366
+
367
+ @app.route('/user_attendance/<username>', methods=['GET'])
368
+ def get_user_attendance(username):
369
+ # Check if the user exists in the database
370
+ user = mongo.db.data.find_one({'RollNumber': username})
371
+ if user is None:
372
+ return jsonify({"error": "User not found"}), 404
373
+ print(user['username'])
374
+ # Fetch the attendance data for the user
375
+ attendance = mongo.db.attendance1.find_one({'username': username}, {'_id': 0,"username":0,"id":0})
376
+ print(attendance)
377
+ if attendance is None:
378
+ return jsonify({"error": "No attendance data found"}), 404
379
+
380
+ # Return the attendance data
381
+ return jsonify(attendance)
382
+
383
+ #attendance
384
+ @app.route('/attendance',methods=['GET'])
385
+ def get_attendance():
386
+ records = list(mongo.db.attendance1.find({}, {"_id": 0}))
387
+ return jsonify({"attendance": records})
388
+
haarcascade_frontalface_default.xml ADDED
The diff for this file is too large to render. See raw diff
 
requirements.txt ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Flask
2
+ Flask-Cors
3
+ Flask-PyMongo
4
+ numpy
5
+ opencv-python
6
+ mtcnn
7
+ keras-facenet
8
+ scikit-learn
9
+ ultralytics
10
+ tensorflow
11
+ pillow # Required by TensorFlow and MTCNN