Akshayram1 commited on
Commit
aefcb0d
·
verified ·
1 Parent(s): b88e42d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +102 -99
app.py CHANGED
@@ -2,149 +2,157 @@ import os
2
  import cv2
3
  import mediapipe as mp
4
  import streamlit as st
5
- from PIL import Image
6
  import numpy as np
7
- import face_recognition
8
  import pandas as pd
9
  from datetime import datetime
10
 
 
 
 
 
11
  # Initialize MediaPipe
12
  mp_face_detection = mp.solutions.face_detection
13
  mp_drawing = mp.solutions.drawing_utils
14
 
15
- # Function to create user database directory if it doesn't exist
16
  def initialize_database():
17
  if not os.path.exists("database"):
18
  os.makedirs("database")
19
  if not os.path.exists("database/records.csv"):
20
- df = pd.DataFrame(columns=['name', 'image_path', 'encoding', 'date_added'])
21
  df.to_csv("database/records.csv", index=False)
 
 
22
 
23
- # Function to compute face encoding
24
- def get_face_encoding(image):
25
- rgb_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
26
- encodings = face_recognition.face_encodings(rgb_image)
27
- if encodings:
28
- return encodings[0]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  return None
30
 
31
- # Function to add face to database
 
 
 
 
 
 
 
 
32
  def add_to_database(image, name):
33
  initialize_database()
34
 
35
- # Get face encoding
36
- encoding = get_face_encoding(image)
37
- if encoding is None:
 
38
  return None, "No face detected in the image"
39
 
40
- # Save image to database folder
41
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
42
  image_path = f"database/{name}_{timestamp}.jpg"
43
  cv2.imwrite(image_path, image)
44
 
45
- # Update records
46
  df = pd.read_csv("database/records.csv")
 
47
  new_record = pd.DataFrame({
48
  'name': [name],
49
  'image_path': [image_path],
50
- 'encoding': [encoding.tolist()],
51
  'date_added': [datetime.now().strftime("%Y-%m-%d %H:%M:%S")]
52
  })
53
  df = pd.concat([df, new_record], ignore_index=True)
54
  df.to_csv("database/records.csv", index=False)
 
 
 
55
  return image_path, "Successfully added to database"
56
 
57
- def find_best_match(face_encoding, known_encodings, known_names, tolerance=0.6):
58
- """
59
- Find the best match for a face encoding among known encodings
60
- Returns name and confidence score of the best match, or None if no match found
61
- """
62
- if not known_encodings or not known_names:
63
- return None, 0
64
-
65
- # Calculate face distances
66
- face_distances = face_recognition.face_distance(known_encodings, face_encoding)
67
-
68
- if len(face_distances) > 0:
69
- best_match_index = np.argmin(face_distances)
70
- best_match_distance = face_distances[best_match_index]
71
-
72
- # Convert distance to confidence score (0-100%)
73
- confidence = (1 - best_match_distance) * 100
74
-
75
- # Only return match if distance is below tolerance
76
- if best_match_distance <= tolerance:
77
- return known_names[best_match_index], confidence
78
-
79
- return None, 0
80
 
81
- # Function to detect faces and perform recognition
82
  def detect_and_recognize_faces(image, output_folder="output"):
83
  if not os.path.exists(output_folder):
84
  os.makedirs(output_folder)
85
 
86
- # Convert image to RGB
87
- rgb_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
 
 
 
 
 
88
 
89
- # Get face locations and encodings
90
- face_locations = face_recognition.face_locations(rgb_image, model="cnn")
91
- face_encodings = face_recognition.face_encodings(rgb_image, face_locations)
92
 
93
  face_images = []
94
  face_results = []
95
- recognition_details = []
96
 
97
- # Load database
98
- try:
99
- df = pd.read_csv("database/records.csv")
100
- if not df.empty:
101
- known_encodings = [np.array(eval(enc)) for enc in df['encoding']]
102
- known_names = df['name'].tolist()
103
- else:
104
- known_encodings = []
105
- known_names = []
106
- except Exception as e:
107
- st.error(f"Error loading database: {str(e)}")
108
- known_encodings = []
109
- known_names = []
110
-
111
- # Process each detected face
112
- for idx, (face_location, face_encoding) in enumerate(zip(face_locations, face_encodings)):
113
- top, right, bottom, left = face_location
114
-
115
- # Extract and save face image
116
- face_image = image[top:bottom, left:right]
117
  face_images.append(face_image)
118
 
119
- face_output_path = os.path.join(output_folder, f"face_{idx+1}.jpg")
120
- cv2.imwrite(face_output_path, face_image)
121
 
122
- # Find best match
123
- matched_name, confidence = find_best_match(face_encoding, known_encodings, known_names)
124
-
125
- if matched_name and confidence > 0:
126
- result = f"Match: {matched_name}\nConfidence: {confidence:.1f}%"
127
- color = (36, 255, 12) # Green for match
128
- else:
129
- result = "No match in database"
130
- color = (0, 0, 255) # Red for no match
 
 
 
 
 
 
 
 
 
131
 
132
  face_results.append(result)
133
- recognition_details.append({
134
- 'location': (left, top, right, bottom),
135
- 'color': color,
136
- 'text': result.split('\n')[0]
137
- })
138
 
139
- # Draw results on image
140
- for detail in recognition_details:
141
- left, top, right, bottom = detail['location']
142
- # Draw rectangle around face
143
- cv2.rectangle(image, (left, top), (right, bottom), detail['color'], 2)
144
- # Draw text above face
145
- cv2.putText(image, detail['text'],
146
- (left, max(0, top - 10)),
147
- cv2.FONT_HERSHEY_SIMPLEX, 0.6, detail['color'], 2)
 
148
 
149
  return image, face_images, face_results
150
 
@@ -170,7 +178,6 @@ st.header("Face Detection and Recognition")
170
  uploaded_file = st.file_uploader("Choose an image for recognition", type=["jpg", "jpeg", "png"], key="recognition_uploader")
171
 
172
  if uploaded_file is not None:
173
- # Load and process image
174
  file_bytes = np.asarray(bytearray(uploaded_file.read()), dtype=np.uint8)
175
  image = cv2.imdecode(file_bytes, 1)
176
 
@@ -184,10 +191,9 @@ if uploaded_file is not None:
184
  caption="Processed Image",
185
  use_column_width=True)
186
 
187
- # Display extracted faces and results
188
  if face_images:
189
  st.subheader("Detected Faces")
190
- cols = st.columns(min(len(face_images), 4)) # Limit to 4 columns max
191
  for idx, (face, result, col) in enumerate(zip(face_images, face_results, cols)):
192
  with col:
193
  st.image(cv2.cvtColor(face, cv2.COLOR_BGR2RGB),
@@ -201,20 +207,17 @@ if uploaded_file is not None:
201
  if st.sidebar.checkbox("Show Database Contents"):
202
  try:
203
  df = pd.read_csv("database/records.csv")
204
- display_df = df.drop('encoding', axis=1) # Don't show encodings
205
- st.sidebar.dataframe(display_df)
206
  except:
207
  st.sidebar.write("Database is empty or not initialized.")
208
 
209
  # Add clear database button
210
  if st.sidebar.button("Clear Database"):
211
  try:
212
- # Remove all files in database directory
213
  for file in os.listdir("database"):
214
  file_path = os.path.join("database", file)
215
  if os.path.isfile(file_path):
216
  os.remove(file_path)
217
- # Reinitialize database
218
  initialize_database()
219
  st.sidebar.success("Database cleared successfully!")
220
  except Exception as e:
 
2
  import cv2
3
  import mediapipe as mp
4
  import streamlit as st
 
5
  import numpy as np
 
6
  import pandas as pd
7
  from datetime import datetime
8
 
9
+ # Initialize face detector
10
+ face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
11
+ recognizer = cv2.face.LBPHFaceRecognizer_create()
12
+
13
  # Initialize MediaPipe
14
  mp_face_detection = mp.solutions.face_detection
15
  mp_drawing = mp.solutions.drawing_utils
16
 
 
17
  def initialize_database():
18
  if not os.path.exists("database"):
19
  os.makedirs("database")
20
  if not os.path.exists("database/records.csv"):
21
+ df = pd.DataFrame(columns=['name', 'image_path', 'label', 'date_added'])
22
  df.to_csv("database/records.csv", index=False)
23
+ if not os.path.exists("database/recognizer"):
24
+ os.makedirs("database/recognizer")
25
 
26
+ def prepare_training_data():
27
+ df = pd.read_csv("database/records.csv")
28
+ if df.empty:
29
+ return None
30
+
31
+ faces = []
32
+ labels = []
33
+ label_names = {}
34
+
35
+ for index, row in df.iterrows():
36
+ image_path = row['image_path']
37
+ label = row['label']
38
+ name = row['name']
39
+ label_names[label] = name
40
+
41
+ if os.path.exists(image_path):
42
+ image = cv2.imread(image_path)
43
+ gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
44
+ face_rects = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5)
45
+
46
+ for (x, y, w, h) in face_rects:
47
+ face = gray[y:y+h, x:x+w]
48
+ faces.append(face)
49
+ labels.append(label)
50
+
51
+ if faces:
52
+ return faces, np.array(labels), label_names
53
  return None
54
 
55
+ def train_recognizer():
56
+ data = prepare_training_data()
57
+ if data is not None:
58
+ faces, labels, label_names = data
59
+ recognizer.train(faces, labels)
60
+ recognizer.save("database/recognizer/trained_model.yml")
61
+ return True
62
+ return False
63
+
64
  def add_to_database(image, name):
65
  initialize_database()
66
 
67
+ gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
68
+ faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5)
69
+
70
+ if len(faces) == 0:
71
  return None, "No face detected in the image"
72
 
 
73
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
74
  image_path = f"database/{name}_{timestamp}.jpg"
75
  cv2.imwrite(image_path, image)
76
 
 
77
  df = pd.read_csv("database/records.csv")
78
+ new_label = len(df) if not df.empty else 0
79
  new_record = pd.DataFrame({
80
  'name': [name],
81
  'image_path': [image_path],
82
+ 'label': [new_label],
83
  'date_added': [datetime.now().strftime("%Y-%m-%d %H:%M:%S")]
84
  })
85
  df = pd.concat([df, new_record], ignore_index=True)
86
  df.to_csv("database/records.csv", index=False)
87
+
88
+ train_recognizer()
89
+
90
  return image_path, "Successfully added to database"
91
 
92
+ def get_status_color(confidence):
93
+ if confidence >= 70:
94
+ return (0, 255, 0) # Green for high confidence
95
+ elif confidence >= 50:
96
+ return (0, 255, 255) # Yellow for medium confidence
97
+ else:
98
+ return (0, 0, 255) # Red for low confidence
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
 
 
100
  def detect_and_recognize_faces(image, output_folder="output"):
101
  if not os.path.exists(output_folder):
102
  os.makedirs(output_folder)
103
 
104
+ try:
105
+ recognizer.read("database/recognizer/trained_model.yml")
106
+ except:
107
+ return image, [], ["No trained model available"]
108
+
109
+ df = pd.read_csv("database/records.csv")
110
+ label_to_name = dict(zip(df['label'], df['name']))
111
 
112
+ gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
113
+ faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5)
 
114
 
115
  face_images = []
116
  face_results = []
 
117
 
118
+ for (x, y, w, h) in faces:
119
+ face_image = image[y:y+h, x:x+w]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  face_images.append(face_image)
121
 
122
+ face_path = os.path.join(output_folder, f"face_{len(face_images)}.jpg")
123
+ cv2.imwrite(face_path, face_image)
124
 
125
+ face_gray = gray[y:y+h, x:x+w]
126
+ try:
127
+ label, confidence = recognizer.predict(face_gray)
128
+ confidence = min(100, 100 * (1 - (confidence / 300)))
129
+
130
+ if confidence >= 50:
131
+ name = label_to_name.get(label, "Unknown")
132
+ result = f"Match: {name}\nConfidence: {confidence:.1f}%"
133
+ if confidence < 70:
134
+ result += "\nPlease Verify (Not Sure)"
135
+ else:
136
+ result = "No match in database\nPlease Verify"
137
+
138
+ color = get_status_color(confidence)
139
+
140
+ except:
141
+ result = "Recognition error"
142
+ color = (0, 0, 255)
143
 
144
  face_results.append(result)
 
 
 
 
 
145
 
146
+ # Draw rectangle
147
+ cv2.rectangle(image, (x, y), (x+w, y+h), color, 2)
148
+
149
+ # Draw text with multiple lines
150
+ text_lines = result.split('\n')
151
+ y_offset = y - 10
152
+ for line in text_lines:
153
+ cv2.putText(image, line, (x, y_offset),
154
+ cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2)
155
+ y_offset -= 20 # Move up for next line
156
 
157
  return image, face_images, face_results
158
 
 
178
  uploaded_file = st.file_uploader("Choose an image for recognition", type=["jpg", "jpeg", "png"], key="recognition_uploader")
179
 
180
  if uploaded_file is not None:
 
181
  file_bytes = np.asarray(bytearray(uploaded_file.read()), dtype=np.uint8)
182
  image = cv2.imdecode(file_bytes, 1)
183
 
 
191
  caption="Processed Image",
192
  use_column_width=True)
193
 
 
194
  if face_images:
195
  st.subheader("Detected Faces")
196
+ cols = st.columns(min(len(face_images), 4))
197
  for idx, (face, result, col) in enumerate(zip(face_images, face_results, cols)):
198
  with col:
199
  st.image(cv2.cvtColor(face, cv2.COLOR_BGR2RGB),
 
207
  if st.sidebar.checkbox("Show Database Contents"):
208
  try:
209
  df = pd.read_csv("database/records.csv")
210
+ st.sidebar.dataframe(df)
 
211
  except:
212
  st.sidebar.write("Database is empty or not initialized.")
213
 
214
  # Add clear database button
215
  if st.sidebar.button("Clear Database"):
216
  try:
 
217
  for file in os.listdir("database"):
218
  file_path = os.path.join("database", file)
219
  if os.path.isfile(file_path):
220
  os.remove(file_path)
 
221
  initialize_database()
222
  st.sidebar.success("Database cleared successfully!")
223
  except Exception as e: