Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
from database import db, User

def create_user(username, password, is_admin=False):
"""Creates a new user and adds them to the database."""
if User.query.filter_by(username=username).first():
raise ValueError(f"User '{username}' already exists.")

new_user = User(username=username, is_admin=is_admin)
new_user.set_password(password)

db.session.add(new_user)
db.session.commit()
return new_user

def get_user_by_username(username):
"""Retrieves a user by their username."""
return User.query.filter_by(username=username).first()

def get_user_by_id(user_id):
"""Retrieves a user by their ID."""
return User.query.get(int(user_id))

def update_user_profile(user_id, new_username=None, new_password=None, is_admin=None):
"""Updates a user's profile information."""
user = get_user_by_id(user_id)
if not user:
raise ValueError(f"User with ID '{user_id}' not found.")

if new_username:
# Check if the new username is already taken
if User.query.filter_by(username=new_username).first() and new_username != user.username:
raise ValueError(f"Username '{new_username}' is already taken.")
user.username = new_username

if new_password:
user.set_password(new_password)

if is_admin is not None:
user.is_admin = is_admin

db.session.commit()
return user

def delete_user(user_id):
"""Deletes a user from the database."""
user = get_user_by_id(user_id)
if user:
db.session.delete(user)
db.session.commit()
return True
return False

def get_all_users():
"""Returns a list of all users."""
return User.query.all()
19 changes: 19 additions & 0 deletions database.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash, check_password_hash

db = SQLAlchemy()

class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
password_hash = db.Column(db.String(128))
is_admin = db.Column(db.Boolean, default=False)

def set_password(self, password):
self.password_hash = generate_password_hash(password)

def check_password(self, password):
return check_password_hash(self.password_hash, password)

def __repr__(self):
return f'<User {self.username}>'
134 changes: 58 additions & 76 deletions dependencies/Facerec.py
Original file line number Diff line number Diff line change
@@ -1,79 +1,61 @@
import os, glob, cv2, face_recognition
import face_recognition
import cv2
import numpy as np
import logging
import os

class Facerec:
def __init__(self):
self.known_face_encodings = []
self.known_face_names = []

# Resize frame for a faster speed
self.frame_resizing = 0.5

def load_encoding_images(self, images_path):
self.__init__()
"""
Load encoding images from path
:param images_path:
:return:
"""
# Load Images
f_types = (os.path.join(images_path,"*.jpg"), os.path.join(images_path,'*.png'))
images_path = []
for files in f_types:
images_path.extend(glob.glob(files))

print("{} encoding images found.".format(len(images_path)))

# Store image encoding and names
for img_path in images_path:
img = cv2.imread(img_path)
rgb_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# Get the filename only from the initial file path.
basename = os.path.basename(img_path)
(filename, ext) = os.path.splitext(basename)
# Get encoding
try:
img_encoding = face_recognition.face_encodings(rgb_img)[0]
except IndexError:
print(f"no face detected on {filename}")

# Store file name and file encoding
try:
self.known_face_encodings.append(img_encoding)
except UnboundLocalError:
logging.warning("no face detected in any of the images, please check your users folder")
self.known_face_names.append(filename)
print("Encoding images loaded")

def detect_known_faces(self, frame):
small_frame = cv2.resize(frame, (0, 0), fx=self.frame_resizing, fy=self.frame_resizing)
# Find all the faces and face encodings in the current frame of video
# Convert the image from BGR color (which OpenCV uses) to RGB color (which face_recognition uses)
rgb_small_frame = cv2.cvtColor(small_frame, cv2.COLOR_BGR2RGB)
face_locations = face_recognition.face_locations(rgb_small_frame)
face_encodings = face_recognition.face_encodings(rgb_small_frame, face_locations)

face_names = []
for face_encoding in face_encodings:
# See if the face is a match for the known face(s)
matches = face_recognition.compare_faces(self.known_face_encodings, face_encoding)
name = "Unknown"

# # If a match was found in known_face_encodings, just use the first one.
# if True in matches:
# first_match_index = matches.index(True)
# name = known_face_names[first_match_index]

# Or instead, use the known face with the smallest distance to the new face
face_distances = face_recognition.face_distance(self.known_face_encodings, face_encoding)
best_match_index = np.argmin(face_distances)
if matches[best_match_index]:
name = self.known_face_names[best_match_index]
face_names.append(name)

# Convert to numpy array to adjust coordinates with frame resizing quickly
face_locations = np.array(face_locations)
face_locations = face_locations / self.frame_resizing
return face_locations.astype(int), face_names
def __init__(self):
self.known_face_encodings = []
self.known_face_names = []

def load_encoding_images(self, users, images_path):
"""
Load encoding images from a list of user objects.
:param users: A list of User objects from the database.
:param images_path: The path to the directory containing the face images.
"""
self.known_face_encodings = []
self.known_face_names = []

for user in users:
image_path = os.path.join(images_path, f"{user.id}.jpg")
if os.path.exists(image_path):
try:
img = face_recognition.load_image_file(image_path)
encodings = face_recognition.face_encodings(img)
if encodings:
encoding = encodings[0]
self.known_face_encodings.append(encoding)
self.known_face_names.append(user.username)
except Exception as e:
print(f"Error loading encoding for user {user.username}: {e}")

def detect_known_faces(self, frame):
# Resize frame of video to 1/4 size for faster face recognition processing
small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25)
# Convert the image from BGR color (which OpenCV uses) to RGB color (which face_recognition uses)
rgb_small_frame = cv2.cvtColor(small_frame, cv2.COLOR_BGR2RGB)

# Find all the faces and face encodings in the current frame of video
face_locations = face_recognition.face_locations(rgb_small_frame)
face_encodings = face_recognition.face_encodings(rgb_small_frame, face_locations)

face_names = []
for face_encoding in face_encodings:
# See if the face is a match for the known face(s)
matches = face_recognition.compare_faces(self.known_face_encodings, face_encoding)
name = "Unknown"

# Or instead, use the known face with the smallest distance to the new face
face_distances = face_recognition.face_distance(self.known_face_encodings, face_encoding)
if len(face_distances) > 0:
best_match_index = np.argmin(face_distances)
if matches[best_match_index]:
name = self.known_face_names[best_match_index]

face_names.append(name)

# Scale back up face locations since the frame we detected in was scaled to 1/4 size
face_locations = np.array(face_locations)
face_locations = face_locations * 4
return face_locations.astype(int), face_names
Loading