changes
This commit is contained in:
parent
a49f009d43
commit
1d2865d361
@ -5,9 +5,9 @@ After=network.target
|
|||||||
[Service]
|
[Service]
|
||||||
Type=simple
|
Type=simple
|
||||||
User={{USER}}
|
User={{USER}}
|
||||||
WorkingDirectory=/home/valer/dp_prakticka/src
|
WorkingDirectory=/home/valer/recognition_system/src
|
||||||
EnvironmentFile=/home/valer/dp_prakticka/src/.env
|
EnvironmentFile=/home/valer/recognition_system/src/.env
|
||||||
ExecStart=/home/valer/env_python_dp/bin/python3.10 /home/valer/dp_prakticka/src/face_rec_no_gui.py
|
ExecStart=/home/valer/recognition_system/src/biometric_system/bin/python3.10 /home/valer/recognition_system/src/face_rec_no_gui.py
|
||||||
Restart=always
|
Restart=always
|
||||||
RestartSec=5
|
RestartSec=5
|
||||||
|
|
||||||
|
@ -5,9 +5,11 @@ After=network.target
|
|||||||
[Service]
|
[Service]
|
||||||
Type=simple
|
Type=simple
|
||||||
User={{USER}}
|
User={{USER}}
|
||||||
WorkingDirectory=/home/valer/dp_prakticka/src
|
WorkingDirectory=/home/valer/recognition_system/src
|
||||||
EnvironmentFile=/home/valer/dp_prakticka/src/.env
|
EnvironmentFile=/home/valer/recognition_system/src/.env
|
||||||
ExecStart=/home/valer/env_python_dp/bin/python3.10 /home/valer/dp_prakticka/src/app.py
|
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
|
Restart=always
|
||||||
RestartSec=5
|
RestartSec=5
|
||||||
|
|
||||||
|
93
src/app.py
93
src/app.py
@ -5,11 +5,14 @@ import subprocess
|
|||||||
import pickle
|
import pickle
|
||||||
import dlib
|
import dlib
|
||||||
import face_recognition
|
import face_recognition
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from flask import Flask, render_template, Response, request, redirect, url_for, session, flash
|
from flask import Flask, render_template, Response, request, redirect, url_for, session, flash
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
from db_connector import log_recognition, get_recognition_logs
|
from db_connector import log_recognition, get_recognition_logs
|
||||||
from config import FLASK_SECRET_KEY
|
from config import FLASK_SECRET_KEY
|
||||||
|
from cryptography.fernet import Fernet
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
app.secret_key = FLASK_SECRET_KEY
|
app.secret_key = FLASK_SECRET_KEY
|
||||||
@ -58,13 +61,65 @@ def run_face():
|
|||||||
return redirect(url_for("add_face"))
|
return redirect(url_for("add_face"))
|
||||||
script = "enroll_no_gui.py"
|
script = "enroll_no_gui.py"
|
||||||
try:
|
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)
|
capture_output=True, text=True, timeout=300)
|
||||||
output = result.stdout if result.stdout else result.stderr
|
output = result.stdout if result.stdout else result.stderr
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
output = str(e)
|
output = str(e)
|
||||||
return render_template("result.html", output=output)
|
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")
|
@app.route("/delete_person")
|
||||||
@login_required
|
@login_required
|
||||||
def delete_person():
|
def delete_person():
|
||||||
@ -79,7 +134,8 @@ def run_delete_person():
|
|||||||
return redirect(url_for("delete_person"))
|
return redirect(url_for("delete_person"))
|
||||||
script = "remove_face.py"
|
script = "remove_face.py"
|
||||||
try:
|
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)
|
capture_output=True, text=True, timeout=60)
|
||||||
output = result.stdout if result.stdout else result.stderr
|
output = result.stdout if result.stdout else result.stderr
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -89,14 +145,30 @@ def run_delete_person():
|
|||||||
@app.route("/list_people")
|
@app.route("/list_people")
|
||||||
@login_required
|
@login_required
|
||||||
def list_people():
|
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:
|
try:
|
||||||
with open("encodings.pickle", "rb") as f:
|
decrypted_data = fernet.decrypt(encrypted_data)
|
||||||
data = pickle.load(f)
|
data = pickle.loads(decrypted_data)
|
||||||
names = data.get("names", [])
|
names = data.get("names", [])
|
||||||
|
unique_names = sorted(set(names))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"[ERROR] {e}")
|
print(f"[ERROR] Failed to decrypt or unpickle: {e}")
|
||||||
names = []
|
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)
|
return render_template("list_people.html", people=unique_names)
|
||||||
|
|
||||||
@app.route("/logs")
|
@app.route("/logs")
|
||||||
@ -110,10 +182,19 @@ def gen_frames_raw():
|
|||||||
if not cap.isOpened():
|
if not cap.isOpened():
|
||||||
print("Error: Could not open camera.")
|
print("Error: Could not open camera.")
|
||||||
return
|
return
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
ret, frame = cap.read()
|
ret, frame = cap.read()
|
||||||
if not ret:
|
if not ret:
|
||||||
continue
|
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)
|
ret, buffer = cv2.imencode('.jpg', frame)
|
||||||
if not ret:
|
if not ret:
|
||||||
continue
|
continue
|
||||||
|
@ -12,6 +12,6 @@ SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
|||||||
ENCODINGS_PATH = os.path.join(SCRIPT_DIR, "encodings.pickle")
|
ENCODINGS_PATH = os.path.join(SCRIPT_DIR, "encodings.pickle")
|
||||||
LANDMARKS_PATH = os.path.join(SCRIPT_DIR, "shape_predictor_68_face_landmarks.dat")
|
LANDMARKS_PATH = os.path.join(SCRIPT_DIR, "shape_predictor_68_face_landmarks.dat")
|
||||||
|
|
||||||
THRESHOLD = 0.4
|
THRESHOLD = 0.3
|
||||||
COOLDOWN = 15
|
COOLDOWN = 15
|
||||||
CV_SCALER = 4
|
CV_SCALER = 4
|
||||||
|
@ -8,12 +8,16 @@ import dlib
|
|||||||
from imutils import face_utils
|
from imutils import face_utils
|
||||||
import pickle
|
import pickle
|
||||||
from cryptography.fernet import Fernet
|
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)
|
fernet = Fernet(key)
|
||||||
|
|
||||||
def encrypt_data(data):
|
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(f"Photo capture completed. {photo_count} photos saved for {name}.")
|
||||||
|
|
||||||
print("[INFO] Running model training script with encryption...")
|
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...")
|
print("[INFO] Model training complete. Exiting...")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
@ -5,15 +5,18 @@ import face_recognition
|
|||||||
import pickle
|
import pickle
|
||||||
import cv2
|
import cv2
|
||||||
from cryptography.fernet import Fernet
|
from cryptography.fernet import Fernet
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
if "ENCODINGS_KEY" not in os.environ:
|
#if "ENCODINGS_KEY" not in os.environ:
|
||||||
print("Please set the ENCODINGS_KEY environment variable with your encryption key.")
|
# print("Please set the ENCODINGS_KEY environment variable with your encryption key.")
|
||||||
exit(1)
|
# exit(1)
|
||||||
key = os.environ.get("ENCODINGS_KEY").encode()
|
#key = os.environ.get("ENCODINGS_KEY").encode()
|
||||||
|
load_dotenv()
|
||||||
|
key = os.getenv("ENCODINGS_KEY")
|
||||||
fernet = Fernet(key)
|
fernet = Fernet(key)
|
||||||
|
|
||||||
encodings_path = "encodings-cnn_large.pickle"
|
encodings_path = "encodings.pickle"
|
||||||
train_path = "datasets_web/dataset/learning"
|
train_path = "dataset"
|
||||||
|
|
||||||
if os.path.exists(encodings_path):
|
if os.path.exists(encodings_path):
|
||||||
print("[INFO] Loading existing encodings...")
|
print("[INFO] Loading existing encodings...")
|
||||||
|
@ -16,7 +16,9 @@ numpy==2.2.3
|
|||||||
opencv-python==4.11.0.86
|
opencv-python==4.11.0.86
|
||||||
pillow==11.1.0
|
pillow==11.1.0
|
||||||
pycparser==2.22
|
pycparser==2.22
|
||||||
|
pymysql==1.1.1
|
||||||
pyrealsense2==2.55.1.6486
|
pyrealsense2==2.55.1.6486
|
||||||
pyserial==3.5
|
pyserial==3.5
|
||||||
PyYAML==6.0.2
|
PyYAML==6.0.2
|
||||||
|
python-dotenv==1.1.0
|
||||||
Werkzeug==3.1.3
|
Werkzeug==3.1.3
|
||||||
|
68
src/servo.py
68
src/servo.py
@ -1,9 +1,55 @@
|
|||||||
import machine
|
# At the top of your script
|
||||||
import time
|
from machine import Pin, PWM
|
||||||
import sys
|
import rp2
|
||||||
|
import array, time, sys
|
||||||
|
|
||||||
servo_pin = machine.Pin(15)
|
# Setup LED
|
||||||
pwm = machine.PWM(servo_pin)
|
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)
|
pwm.freq(50)
|
||||||
|
|
||||||
def set_angle(angle):
|
def set_angle(angle):
|
||||||
@ -22,11 +68,17 @@ def move_servo_smoothly(start_angle, end_angle, step=1, delay=0.02):
|
|||||||
time.sleep(delay)
|
time.sleep(delay)
|
||||||
|
|
||||||
def open_door():
|
def open_door():
|
||||||
move_servo_smoothly(0, 180, step=2, delay=0.03)
|
pixels_fill(WHITE)
|
||||||
time.sleep(5)
|
pixels_show()
|
||||||
move_servo_smoothly(180, 0, step=2, delay=0.03)
|
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:
|
while True:
|
||||||
command = sys.stdin.readline().strip()
|
command = sys.stdin.readline().strip()
|
||||||
if command == "run":
|
if command == "run":
|
||||||
open_door()
|
open_door()
|
||||||
|
|
||||||
|
@ -1,13 +1,66 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% block title %}Add Face{% endblock %}
|
{% block title %}Add Face{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1 class="mb-4">Add a New Face</h1>
|
<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>
|
<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">
|
<form id="faceForm" method="post">
|
||||||
<label for="face_name" class="form-label">Name</label>
|
<div class="mb-3">
|
||||||
<input type="text" class="form-control" id="face_name" name="face_name" placeholder="Enter name" required>
|
<label for="face_name" class="form-label">Name</label>
|
||||||
</div>
|
<input type="text" class="form-control" id="face_name" name="face_name" placeholder="Enter name" required>
|
||||||
<button type="submit" class="btn btn-primary">Run Add Face Script</button>
|
</div>
|
||||||
</form>
|
<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 %}
|
{% endblock %}
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<h1 class="mb-4">Live Video Stream</h1>
|
<h1 class="mb-4">Live Video Stream</h1>
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<img src="{{ url_for('video_feed') }}" class="img-fluid" alt="Live Stream">
|
|
||||||
</div>
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
<h2 class="mt-4">Recognition Logs</h2>
|
<h2 class="mt-4">Recognition Logs</h2>
|
||||||
|
Loading…
Reference in New Issue
Block a user