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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +99 -102
app.py CHANGED
@@ -2,157 +2,149 @@ import os
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,6 +170,7 @@ st.header("Face Detection and Recognition")
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,9 +184,10 @@ if uploaded_file is not None:
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,17 +201,20 @@ if uploaded_file is not None:
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:
 
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
  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
  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
  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: