0% found this document useful (0 votes)
20 views8 pages

From Pi

This document outlines a face recognition system that utilizes DeepFace for facial recognition and email notifications for unknown face detection. It includes configurations for email alerts, RFID integration, and logging, along with functions for initializing a face database, processing video frames, enrolling new faces, and sending email alerts. The main function captures video frames, processes them for face recognition, and provides a user interface for enrolling faces and adjusting similarity thresholds.

Uploaded by

mseif1573
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
20 views8 pages

From Pi

This document outlines a face recognition system that utilizes DeepFace for facial recognition and email notifications for unknown face detection. It includes configurations for email alerts, RFID integration, and logging, along with functions for initializing a face database, processing video frames, enrolling new faces, and sending email alerts. The main function captures video frames, processes them for face recognition, and provides a user interface for enrolling faces and adjusting similarity thresholds.

Uploaded by

mseif1573
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 8

import cv2

import os
import numpy as np
import threading
import time
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from deepface import DeepFace
from queue import Queue, Empty
import datetime
import logging

# Configuration
DATABASE_FOLDER = "database"
MODEL_NAME = "ArcFace"
DETECTOR_BACKEND = "ssd" # Faster than retinaface
FRAME_SKIP = 4 # Process every Nth frame
MAX_QUEUE_SIZE = 2
SIMILARITY_THRESHOLD = 0.65

# Email Configuration
EMAIL_ENABLED = True
EMAIL_FROM = "[email protected]" # Your email address
EMAIL_PASSWORD = "uvfbgvkicjtzzpvp" # Use app password for Gmail
EMAIL_TO = "[email protected] , [email protected]" # Recipient email
EMAIL_SMTP_SERVER = "smtp.gmail.com"
EMAIL_SMTP_PORT = 587
EMAIL_COOLDOWN = 60 # Seconds between emails

# RFID Configuration
RFID_ENABLED = True
RFID_PORT = "COM3" # Change to your RFID reader's serial port
RFID_BAUDRATE = 9600
RFID_EMERGENCY_CODES = [
"1234567890", # Add your RFID tag IDs here
"0987654321"
]

# Set up logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
filename='face_recognition.log'
)
logger = logging.getLogger(__name__)

# Global variables
face_database = []
processing_queue = Queue(maxsize=MAX_QUEUE_SIZE)
current_results = []
is_running = True
frame_count = 0
fps = 0
last_fps_update = time.time()
fps_counter = 0
last_email_time = 0
unknown_faces_detected = False
# Initialize database
def init_database():
if not os.path.exists(DATABASE_FOLDER):
os.makedirs(DATABASE_FOLDER)

files = [f for f in os.listdir(DATABASE_FOLDER) if f.lower().endswith((".jpg",


".jpeg", ".png"))]
loaded = 0

for filename in files:


path = os.path.join(DATABASE_FOLDER, filename)
try:
img = cv2.imread(path)
if img is None:
continue

# Resize large images


if max(img.shape[0], img.shape[1]) > 800:
scale = 800 / max(img.shape[0], img.shape[1])
img = cv2.resize(img, (0, 0), fx=scale, fy=scale)

result = DeepFace.represent(
img_path=img,
model_name=MODEL_NAME,
detector_backend=DETECTOR_BACKEND,
enforce_detection=True,
align=True
)

if result:
face_database.append({
"name": os.path.splitext(filename)[0],
"embedding": result[0]["embedding"]
})
loaded += 1
except Exception as e:
logger.error(f"Error loading {filename}: {str(e)}")
continue

logger.info(f"Loaded {loaded} faces from database")


print(f"Loaded {loaded} faces from database")

# Process frames in background


def process_frames():
global current_results, unknown_faces_detected

while is_running:
try:
frame = processing_queue.get(timeout=0.5)

# Detect faces
faces = DeepFace.extract_faces(
img_path=frame,
detector_backend=DETECTOR_BACKEND,
enforce_detection=False,
align=True
)
results = []
unknown_detected = False

for face in faces:


if face["confidence"] < 0.9: # Skip low confidence detections
continue

region = face["facial_area"]
x, y, w, h = region["x"], region["y"], region["w"], region["h"]

# Skip if database is empty


if not face_database:
results.append((x, y, w, h, "Unknown", 0, frame))
unknown_detected = True
continue

# Extract face region


face_img = frame[max(0, y):min(frame.shape[0], y+h),
max(0, x):min(frame.shape[1], x+w)]

# Skip tiny faces


if face_img.shape[0] < 20 or face_img.shape[1] < 20:
continue

try:
# Get embedding
embedding = DeepFace.represent(
img_path=face_img,
model_name=MODEL_NAME,
detector_backend="skip",
enforce_detection=False,
align=False
)[0]["embedding"]

# Find best match using vectorized operations


db_embeddings = np.array([entry["embedding"] for entry in
face_database])
names = [entry["name"] for entry in face_database]

# Calculate cosine similarity


similarities = np.dot(db_embeddings, embedding) / (
np.linalg.norm(db_embeddings, axis=1) *
np.linalg.norm(embedding)
)

# Get best match


if similarities.size > 0:
best_idx = np.argmax(similarities)
score = (similarities[best_idx] + 1) / 2 # Convert to 0-1

if score > SIMILARITY_THRESHOLD:


label = names[best_idx]
results.append((x, y, w, h, label, score, None))
else:
label = "Unknown"
# Save frame with unknown face for email
results.append((x, y, w, h, label, score,
frame.copy()))
unknown_detected = True
except Exception as e:
logger.error(f"Error processing face: {str(e)}")
results.append((x, y, w, h, "Unknown", 0, frame.copy()))
unknown_detected = True

# Update results
current_results = results
unknown_faces_detected = unknown_detected

# If unknown face detected, trigger email notification


if unknown_detected:
send_email_notification()

processing_queue.task_done()

except Empty:
pass
except Exception as e:
logger.error(f"Process frame error: {str(e)}")
print(f"Error: {str(e)}")
try:
processing_queue.task_done()
except:
pass

# Enroll a new face


def enroll_face(frame, name):
try:
# Detect face
faces = DeepFace.extract_faces(
img_path=frame,
detector_backend=DETECTOR_BACKEND,
enforce_detection=True,
align=True
)

if not faces or faces[0]["confidence"] < 0.9:


logger.warning("No good quality face detected for enrollment")
print("No good quality face detected")
return False

# Save face image


filename = f"{name}_{int(time.time())}.jpg"
path = os.path.join(DATABASE_FOLDER, filename)

# Extract face with margin


face = faces[0]
region = face["facial_area"]
x, y, w, h = region["x"], region["y"], region["w"], region["h"]
margin_x, margin_y = int(w * 0.2), int(h * 0.2)

# Ensure bounds
x1 = max(0, x - margin_x)
y1 = max(0, y - margin_y)
x2 = min(frame.shape[1], x + w + margin_x)
y2 = min(frame.shape[0], y + h + margin_y)

# Save image
face_img = frame[y1:y2, x1:x2]
cv2.imwrite(path, face_img)

# Add to database
embedding = DeepFace.represent(
img_path=face_img,
model_name=MODEL_NAME,
detector_backend=DETECTOR_BACKEND,
enforce_detection=True
)[0]["embedding"]

face_database.append({
"name": name,
"embedding": embedding
})

logger.info(f"Enrolled new face: {name}")


print(f"Enrolled: {name}")
return True

except Exception as e:
logger.error(f"Enrollment failed: {str(e)}")
print(f"Enrollment failed: {str(e)}")
return False

# Send email with face image


def send_email_notification():
global last_email_time

if not EMAIL_ENABLED:
return

# Check cooldown
current_time = time.time()
if current_time - last_email_time < EMAIL_COOLDOWN:
return

last_email_time = current_time

# Prepare email in a separate thread to avoid blocking


threading.Thread(target=_send_email_worker).start()

def _send_email_worker():
try:
# Find first unknown face with image
unknown_face = None
for face in current_results:
if face[4] == "Unknown" and face[6] is not None:
unknown_face = face
break

if unknown_face is None:
logger.warning("No unknown face image found for email")
return

# Extract face data


x, y, w, h, _, _, frame = unknown_face

# Create a timestamp
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# Prepare the email
msg = MIMEMultipart()
msg['From'] = EMAIL_FROM
msg['To'] = EMAIL_TO
msg['Subject'] = f"⚠️ SECURITY ALERT: Unknown Person Detected -
{timestamp}"

# Email body
body = f"""
<html>
<body>
<h2>Security Alert: Unknown Person Detected</h2>
<p><b>Time:</b> {timestamp}</p>
<p>An unknown person has been detected by the security system.</p>
<p>Please see the attached image for details.</p>
</body>
</html>
"""
msg.attach(MIMEText(body, 'html'))

# Save image with rectangle


alert_img = frame.copy()
cv2.rectangle(alert_img, (x, y), (x+w, y+h), (0, 0, 255), 2)
cv2.putText(alert_img, "Unknown", (x, y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5,
(0, 0, 255), 2)

# Convert image to attachment


_, img_encoded = cv2.imencode('.jpg', alert_img)
img_bytes = img_encoded.tobytes()

# Attach image
img_attach = MIMEImage(img_bytes)
img_attach.add_header('Content-Disposition', 'attachment',
filename=f'unknown_person_{timestamp}.jpg')
msg.attach(img_attach)

# Send email
server = smtplib.SMTP(EMAIL_SMTP_SERVER, EMAIL_SMTP_PORT)
server.starttls()
server.login(EMAIL_FROM, EMAIL_PASSWORD)
server.send_message(msg)
server.quit()

logger.info(f"Email alert sent at {timestamp}")


print(f"Email alert sent at {timestamp}")

except Exception as e:
logger.error(f"Email sending failed: {str(e)}")
print(f"Email sending failed: {str(e)}")

# Main function
def main():
global is_running, frame_count, fps, last_fps_update, fps_counter,
SIMILARITY_THRESHOLD

# Initialize
init_database()

# Start processing thread


process_thread = threading.Thread(target=process_frames, daemon=True)
process_thread.start()

# Initialize camera
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)

try:
cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc(*'MJPG'))
except:
pass

# Create unknown faces directory for storing images


unknown_dir = "unknown_faces"
if not os.path.exists(unknown_dir):
os.makedirs(unknown_dir)

# Main loop
while True:
# Capture frame
ret, frame = cap.read()
if not ret:
break

# Update FPS
fps_counter += 1
now = time.time()
if now - last_fps_update >= 1.0:
fps = fps_counter
fps_counter = 0
last_fps_update = now

# Process every Nth frame


frame_count += 1
if frame_count % FRAME_SKIP == 0 and not processing_queue.full():
processing_queue.put(frame.copy())

# Draw results
for x, y, w, h, label, conf, _ in current_results:
# Set color based on recognition
color = (0, 255, 0) if label != "Unknown" else (0, 0, 255)

# Draw rectangle
cv2.rectangle(frame, (x, y), (x+w, y+h), color, 2)

# Draw label with confidence


text = f"{label} ({conf*100:.1f}%)" if label != "Unknown" else
"Unknown"
cv2.putText(frame, text, (x, y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5,
color, 2)

# Draw HUD
cv2.putText(frame, f"FPS: {fps}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7,
(0, 255, 0), 2)
cv2.putText(frame, f"Thresh: {SIMILARITY_THRESHOLD:.2f}", (10, 60),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)

# Show unknown face notification status


if unknown_faces_detected:
cv2.putText(frame, "ALERT: Unknown face detected", (frame.shape[1] -
300, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2)

# Draw help text


cv2.putText(frame, "E:enroll +/-:thresh Q:quit", (10, 90),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1)

# Show frame
cv2.imshow('Face Recognition', frame)

# Handle keyboard input


key = cv2.waitKey(1) & 0xFF
if key == ord('q'):
break
elif key == ord('e'):
name = input("Enter name: ").strip()
if name:
threading.Thread(target=enroll_face, args=(frame.copy(),
name)).start()
elif key == ord('+') or key == ord('='):
SIMILARITY_THRESHOLD = min(0.95, SIMILARITY_THRESHOLD + 0.05)
elif key == ord('-'):
SIMILARITY_THRESHOLD = max(0.3, SIMILARITY_THRESHOLD - 0.05)

# Cleanup
is_running = False
if process_thread.is_alive():
process_thread.join(timeout=1.0)
cap.release()
cv2.destroyAllWindows()

if __name__ == "__main__":
main()

You might also like