This commit is contained in:
Valér Jakubčo 2025-05-16 11:53:34 +01:00
parent a49f009d43
commit 1d2865d361
10 changed files with 239 additions and 42 deletions

View File

@ -5,9 +5,9 @@ After=network.target
[Service]
Type=simple
User={{USER}}
WorkingDirectory=/home/valer/dp_prakticka/src
EnvironmentFile=/home/valer/dp_prakticka/src/.env
ExecStart=/home/valer/env_python_dp/bin/python3.10 /home/valer/dp_prakticka/src/face_rec_no_gui.py
WorkingDirectory=/home/valer/recognition_system/src
EnvironmentFile=/home/valer/recognition_system/src/.env
ExecStart=/home/valer/recognition_system/src/biometric_system/bin/python3.10 /home/valer/recognition_system/src/face_rec_no_gui.py
Restart=always
RestartSec=5

View File

@ -5,9 +5,11 @@ After=network.target
[Service]
Type=simple
User={{USER}}
WorkingDirectory=/home/valer/dp_prakticka/src
EnvironmentFile=/home/valer/dp_prakticka/src/.env
ExecStart=/home/valer/env_python_dp/bin/python3.10 /home/valer/dp_prakticka/src/app.py
WorkingDirectory=/home/valer/recognition_system/src
EnvironmentFile=/home/valer/recognition_system/src/.env
ExecStart=/home/valer/recognition_system/src/biometric_system/bin/python3.10 /home/valer/recognition_system/src/app.py
Environment="PATH=/home/valer/recognition_system/src/biometric_system/bin"
Environment="PYTHONUNBUFFERED=1"
Restart=always
RestartSec=5

View File

@ -5,11 +5,14 @@ import subprocess
import pickle
import dlib
import face_recognition
import subprocess
import sys
import numpy as np
from flask import Flask, render_template, Response, request, redirect, url_for, session, flash
from functools import wraps
from db_connector import log_recognition, get_recognition_logs
from config import FLASK_SECRET_KEY
from cryptography.fernet import Fernet
app = Flask(__name__)
app.secret_key = FLASK_SECRET_KEY
@ -58,13 +61,65 @@ def run_face():
return redirect(url_for("add_face"))
script = "enroll_no_gui.py"
try:
result = subprocess.run(["python3", script, face_name, "--auto"],
venv_python = "./biometric_system/bin/python3.10"
result = subprocess.run([venv_python, script, face_name, "--auto"],
capture_output=True, text=True, timeout=300)
output = result.stdout if result.stdout else result.stderr
except Exception as e:
output = str(e)
return render_template("result.html", output=output)
@app.route("/run_face_live")
@login_required
def run_face_live():
face_name = request.args.get("face_name", "")
venv_python = "/home/valer/recognition_system/src/biometric_system/bin/python3.10"
def generate():
env = os.environ.copy()
env["PYTHONUNBUFFERED"] = "1"
try:
subprocess.run(["sudo", "systemctl", "stop", "face_rec"], check=True)
print("✅ face_rec_service stopped")
yield "data: [face_rec_service stopped]\n\n"
except subprocess.CalledProcessError as e:
error_msg = f"[ERROR] Could not stop service: {e}"
print(error_msg)
yield f"data: {error_msg}\n\n"
yield "data: [Aborting enrollment.]\n\n"
return
try:
process = subprocess.Popen(
[sys.executable, "enroll_no_gui.py", face_name, "--auto"],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True,
bufsize=1,
env=env
)
for line in iter(process.stdout.readline, ''):
print(line, end='')
yield f"data: {line}\n\n"
process.stdout.close()
process.wait()
except Exception as e:
yield f"data: [ERROR during enrollment: {e}]\n\n"
print(f"[ERROR] during subprocess: {e}")
try:
subprocess.run(["sudo", "systemctl", "start", "face_rec"], check=True)
print("✅ face_rec_service started")
yield "data: [face_rec_service started]\n\n"
except subprocess.CalledProcessError as e:
error_msg = f"[ERROR] Could not start service: {e}"
print(error_msg)
yield f"data: {error_msg}\n\n"
return Response(generate(), mimetype='text/event-stream')
@app.route("/delete_person")
@login_required
def delete_person():
@ -79,7 +134,8 @@ def run_delete_person():
return redirect(url_for("delete_person"))
script = "remove_face.py"
try:
result = subprocess.run(["python3", script, person_name],
venv_python = "./biometric_system/bin/python3.10"
result = subprocess.run([venv_python, script, person_name],
capture_output=True, text=True, timeout=60)
output = result.stdout if result.stdout else result.stderr
except Exception as e:
@ -89,14 +145,30 @@ def run_delete_person():
@app.route("/list_people")
@login_required
def list_people():
key = os.getenv("ENCODINGS_KEY")
fernet = Fernet(key)
with open("encodings.pickle", "rb") as enc_file:
encrypted_data = enc_file.read()
try:
with open("encodings.pickle", "rb") as f:
data = pickle.load(f)
decrypted_data = fernet.decrypt(encrypted_data)
data = pickle.loads(decrypted_data)
names = data.get("names", [])
unique_names = sorted(set(names))
except Exception as e:
print(f"[ERROR] {e}")
print(f"[ERROR] Failed to decrypt or unpickle: {e}")
names = []
unique_names = sorted(set(names))
#try:
# with open("encodings.pickle", "rb") as f:
# data = pickle.load(f)
# names = data.get("names", [])
#except Exception as e:
# print(f"[ERROR] {e}")
# names = []
#unique_names = sorted(set(names))
#print(unique_names)
return render_template("list_people.html", people=unique_names)
@app.route("/logs")
@ -110,10 +182,19 @@ def gen_frames_raw():
if not cap.isOpened():
print("Error: Could not open camera.")
return
while True:
ret, frame = cap.read()
if not ret:
continue
# OPTIONAL
# rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# face_locations = face_recognition.face_locations(rgb_frame)
# for (top, right, bottom, left) in face_locations:
# cv2.rectangle(frame, (left, top), (right, bottom), (0, 255, 0), 2)
ret, buffer = cv2.imencode('.jpg', frame)
if not ret:
continue

View File

@ -12,6 +12,6 @@ SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
ENCODINGS_PATH = os.path.join(SCRIPT_DIR, "encodings.pickle")
LANDMARKS_PATH = os.path.join(SCRIPT_DIR, "shape_predictor_68_face_landmarks.dat")
THRESHOLD = 0.4
THRESHOLD = 0.3
COOLDOWN = 15
CV_SCALER = 4

View File

@ -8,12 +8,16 @@ import dlib
from imutils import face_utils
import pickle
from cryptography.fernet import Fernet
from dotenv import load_dotenv
if "ENCODINGS_KEY" not in os.environ:
print("Please set the ENCODINGS_KEY environment variable with your encryption key.")
exit(1)
key = os.environ.get("ENCODINGS_KEY").encode()
#if "ENCODINGS_KEY" not in os.environ:
# print("Please set the ENCODINGS_KEY environment variable with your encryption key.")
# exit(1)
#key = os.environ.get("ENCODINGS_KEY").encode()
load_dotenv()
key = os.getenv("ENCODINGS_KEY")
fernet = Fernet(key)
def encrypt_data(data):
@ -102,7 +106,8 @@ def capture_photos(name, auto=False):
print(f"Photo capture completed. {photo_count} photos saved for {name}.")
print("[INFO] Running model training script with encryption...")
subprocess.run(["python", "model_training.py"])
venv_python = "./biometric_system/bin/python3.10"
subprocess.run([venv_python, "model_training.py"])
print("[INFO] Model training complete. Exiting...")
if __name__ == "__main__":

View File

@ -5,15 +5,18 @@ import face_recognition
import pickle
import cv2
from cryptography.fernet import Fernet
from dotenv import load_dotenv
if "ENCODINGS_KEY" not in os.environ:
print("Please set the ENCODINGS_KEY environment variable with your encryption key.")
exit(1)
key = os.environ.get("ENCODINGS_KEY").encode()
#if "ENCODINGS_KEY" not in os.environ:
# print("Please set the ENCODINGS_KEY environment variable with your encryption key.")
# exit(1)
#key = os.environ.get("ENCODINGS_KEY").encode()
load_dotenv()
key = os.getenv("ENCODINGS_KEY")
fernet = Fernet(key)
encodings_path = "encodings-cnn_large.pickle"
train_path = "datasets_web/dataset/learning"
encodings_path = "encodings.pickle"
train_path = "dataset"
if os.path.exists(encodings_path):
print("[INFO] Loading existing encodings...")

View File

@ -16,7 +16,9 @@ numpy==2.2.3
opencv-python==4.11.0.86
pillow==11.1.0
pycparser==2.22
pymysql==1.1.1
pyrealsense2==2.55.1.6486
pyserial==3.5
PyYAML==6.0.2
python-dotenv==1.1.0
Werkzeug==3.1.3

View File

@ -1,9 +1,55 @@
import machine
import time
import sys
# At the top of your script
from machine import Pin, PWM
import rp2
import array, time, sys
servo_pin = machine.Pin(15)
pwm = machine.PWM(servo_pin)
# Setup LED
NUM_LEDS = 16
PIN_NUM = 22
brightness = 0.2
@rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT, autopull=True, pull_thresh=24)
def ws2812():
T1 = 2
T2 = 5
T3 = 3
wrap_target()
label("bitloop")
out(x, 1) .side(0) [T3 - 1]
jmp(not_x, "do_zero") .side(1) [T1 - 1]
jmp("bitloop") .side(1) [T2 - 1]
label("do_zero")
nop() .side(0) [T2 - 1]
wrap()
sm = rp2.StateMachine(0, ws2812, freq=8_000_000, sideset_base=Pin(PIN_NUM))
sm.active(1)
ar = array.array("I", [0 for _ in range(NUM_LEDS)])
def pixels_show():
dimmer_ar = array.array("I", [0 for _ in range(NUM_LEDS)])
for i, c in enumerate(ar):
r = int(((c >> 8) & 0xFF) * brightness)
g = int(((c >> 16) & 0xFF) * brightness)
b = int((c & 0xFF) * brightness)
dimmer_ar[i] = (g << 16) + (r << 8) + b
sm.put(dimmer_ar, 8)
time.sleep_ms(10)
def pixels_set(i, color):
ar[i] = (color[1]<<16) + (color[0]<<8) + color[2]
def pixels_fill(color):
for i in range(len(ar)):
pixels_set(i, color)
# Color constants
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
# Setup Servo
servo_pin = Pin(15)
pwm = PWM(servo_pin)
pwm.freq(50)
def set_angle(angle):
@ -22,11 +68,17 @@ def move_servo_smoothly(start_angle, end_angle, step=1, delay=0.02):
time.sleep(delay)
def open_door():
move_servo_smoothly(0, 180, step=2, delay=0.03)
time.sleep(5)
pixels_fill(WHITE)
pixels_show()
move_servo_smoothly(180, 0, step=2, delay=0.03)
time.sleep(5)
move_servo_smoothly(0, 180, step=2, delay=0.03)
pixels_fill(BLACK)
pixels_show()
# Wait for command
while True:
command = sys.stdin.readline().strip()
if command == "run":
open_door()
open_door()

View File

@ -1,13 +1,66 @@
{% extends "base.html" %}
{% block title %}Add Face{% endblock %}
{% block content %}
<h1 class="mb-4">Add a New Face</h1>
<p>Enter the name of the person and click the button below to run the Add Face script.</p>
<form method="post" action="{{ url_for('run_face') }}">
<div class="mb-3">
<label for="face_name" class="form-label">Name</label>
<input type="text" class="form-control" id="face_name" name="face_name" placeholder="Enter name" required>
</div>
<button type="submit" class="btn btn-primary">Run Add Face Script</button>
</form>
<h1 class="mb-4">Add a New Face</h1>
<p>Enter the name of the person and click the button below to run the Add Face script.</p>
<form id="faceForm" method="post">
<div class="mb-3">
<label for="face_name" class="form-label">Name</label>
<input type="text" class="form-control" id="face_name" name="face_name" placeholder="Enter name" required>
</div>
<button type="submit" class="btn btn-primary">Run Add Face Script</button>
</form>
<!-- Loading animation -->
<div id="loading" class="mt-3" style="display: none;">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Loading...</span>
</div>
<span class="ms-2">Processing face data...</span>
</div>
<!-- Row for side-by-side display -->
<div class="row mt-4">
<!-- Output log -->
<div class="col-md-6 mb-4">
<h3>Live Script Output</h3>
<pre id="output" style="background-color: #f8f9fa; padding: 1rem; height: 300px; overflow-y: scroll;"></pre>
</div>
<!-- Live video feed -->
<div class="col-md-6 mb-4">
<h3>Camera Feed</h3>
<img src="{{ url_for('video_feed') }}" class="img-fluid" alt="Live Stream" style="max-height: 300px;">
</div>
</div>
<script>
const form = document.getElementById("faceForm");
const output = document.getElementById("output");
const loading = document.getElementById("loading");
form.addEventListener("submit", function (e) {
e.preventDefault();
output.textContent = "";
loading.style.display = "block";
const formData = new FormData(form);
const name = formData.get("face_name");
const eventSource = new EventSource(`/run_face_live?face_name=${encodeURIComponent(name)}`);
eventSource.onmessage = function (event) {
output.textContent += event.data + "\n";
output.scrollTop = output.scrollHeight;
};
eventSource.onerror = function () {
eventSource.close();
loading.style.display = "none";
output.textContent += "\n[Stream ended or error occurred]";
};
});
</script>
{% endblock %}

View File

@ -3,7 +3,6 @@
{% block content %}
<h1 class="mb-4">Live Video Stream</h1>
<div class="text-center">
<img src="{{ url_for('video_feed') }}" class="img-fluid" alt="Live Stream">
</div>
<hr>
<h2 class="mt-4">Recognition Logs</h2>