45 lines
1.5 KiB
Python
45 lines
1.5 KiB
Python
from __future__ import annotations
|
|
|
|
from flask import Blueprint, current_app, jsonify, request
|
|
|
|
from app.models import Person, Role
|
|
from app.services.attendance import last_presence_summary
|
|
from app.services.recognition import RecognitionUnavailable, recognize_faces
|
|
from app.services.security import roles_required
|
|
|
|
bp = Blueprint("recognition", __name__, url_prefix="/recognition")
|
|
|
|
|
|
@bp.post("/identify")
|
|
@roles_required(Role.ADMIN, Role.OPERATOR)
|
|
def identify():
|
|
image = request.form.get("image", "")
|
|
if not image:
|
|
return jsonify({"error": "No image was provided."}), 400
|
|
|
|
people = Person.query.filter_by(active=True).all()
|
|
try:
|
|
result = recognize_faces(image, people, tolerance=current_app.config["FACE_MATCH_TOLERANCE"])
|
|
except RecognitionUnavailable as exc:
|
|
return jsonify({"error": str(exc)}), 503
|
|
except ValueError as exc:
|
|
return jsonify({"error": str(exc)}), 400
|
|
|
|
faces = []
|
|
for face in result.faces:
|
|
if not face.person:
|
|
faces.append({"matched": False, "confidence": None})
|
|
continue
|
|
faces.append(
|
|
{
|
|
"matched": True,
|
|
"person_id": face.person.id,
|
|
"full_name": face.person.full_name,
|
|
"employee_id": face.person.employee_id,
|
|
"confidence": round(face.confidence, 3) if face.confidence is not None else None,
|
|
"last_presence": last_presence_summary(face.person),
|
|
}
|
|
)
|
|
|
|
return jsonify({"faces": faces, "annotated_image": result.annotated_image})
|