diff --git a/FaceRec/app/main/Edit.py b/FaceRec/app/main/Edit.py index e5956de..4749798 100644 --- a/FaceRec/app/main/Edit.py +++ b/FaceRec/app/main/Edit.py @@ -9,7 +9,7 @@ import requests from flask import Blueprint from flask import Response as flask_response -from flask import redirect, render_template, request +from flask import flash, g, redirect, render_template, request from PIL import Image from FaceRec.config import Config @@ -21,191 +21,180 @@ static_folder="../../static/", ) +# Global variable for video capture cap = cv2.VideoCapture(0) -# function for displaying live video -def display_live_video(): - """ - Generator for displaying live video from the camera. +def initialize_camera(): + """Initialize the camera resource if it's not already opened.""" + global cap + if not cap.isOpened(): + cap.open(0) + + +def release_camera(): + """Release the camera resource when no longer needed.""" + global cap + if cap.isOpened(): + cap.release() + - Yields frames as JPEG images. - """ +def validate_input(data: dict) -> bool: + """Validates the input form data.""" + if not data.get("EmployeeCode").isdigit(): + flash("Invalid EmployeeCode. It should be numeric.") + return False + if not data.get("Name"): + flash("Name cannot be empty.") + return False + if not data.get("gender"): + flash("Gender cannot be empty.") + return False + if not data.get("Department"): + flash("Department cannot be empty.") + return False + return True + + +def display_live_video(): + """Generator for displaying live video from the camera.""" + initialize_camera() # Ensure camera is initialized while True: - success, frame = cap.read() # Read a frame from the camera + success, frame = cap.read() if not success: break frame = cv2.flip(frame, 1) ret, buffer = cv2.imencode(".jpg", frame) - frame = buffer.tobytes if not ret: break yield ( b"--frame\r\n" - b"Content-Type: image/jpeg\r\n\r\n" + - bytearray(buffer) + b"\r\n\r\n" + b"Content-Type: image/jpeg\r\n\r\n" + buffer.tobytes() + b"\r\n\r\n" ) -# Route for displaying video @Edit_blueprint.route("/video_feed") def video_feed(): - """Route for displaying live video from the camera. - - Returns a multipart response with a JPEG image for each frame from the camera. - """ + """Route for displaying live video from the camera.""" return flask_response( display_live_video(), - mimetype="multipart/x-mixed-replace;boundary=frame", + mimetype="multipart/x-mixed-replace; boundary=frame", ) -# Route for capturing image from video -@Edit_blueprint.route("/capture", methods=["GET", "POST"]) +@Edit_blueprint.route("/capture", methods=["POST"]) def capture(): - """Route for capturing an image from the video feed. - - This route is used to capture a single frame from the video feed and save it to a file. - The frame is flipped horizontally before saving. - - The image is stored in a file specified by the `Config.image_data_file` variable. - - The response is a redirect to the "Image" route, which displays the captured image. - - The request is expected to be a POST request with the following form data: - - EmployeeCode: The employee code for the person in the image. - - Name: The name of the person in the image. - - gender: The gender of the person in the image. - - Department: The department of the person in the image. - """ - global EmployeeCode - global Name - global gender - global Dept - global encoded_image - EmployeeCode = request.form.get("EmployeeCode", "") - Name = request.form.get("Name", "") - gender = request.form.get("gender", "") - Dept = request.form.get("Department", "") - ret, frame = cap.read(True) - frame = cv2.flip(frame, 1) - _, buffer = cv2.imencode(".jpg", frame) - encoded_image = base64.b64encode(buffer).decode("utf-8") - with open(Config.image_data_file, "w") as file: - json.dump({"base64_image": encoded_image}, file) + """Route for capturing an image from the video feed.""" + form_data = { + "EmployeeCode": request.form.get("EmployeeCode", ""), + "Name": request.form.get("Name", ""), + "gender": request.form.get("gender", ""), + "Department": request.form.get("Department", ""), + } + + if not validate_input(form_data): + return redirect("capture") + + try: + initialize_camera() # Ensure camera is initialized + ret, frame = cap.read() + if not ret: + flash("Failed to capture the image.") + return redirect("capture") + + frame = cv2.flip(frame, 1) + _, buffer = cv2.imencode(".jpg", frame) + encoded_image = base64.b64encode(buffer).decode("utf-8") + + g.employee_data = form_data + g.encoded_image = encoded_image + + with open(Config.image_data_file, "w") as file: + json.dump({"base64_image": encoded_image}, file) + except Exception as e: + flash(f"Error capturing image: {e}") + return redirect("capture") + return redirect("Image") -# Route to display captured image @Edit_blueprint.route("/Image", methods=["GET"]) def display_image(): - """Route to display the captured image. - - This route reads the image data from a file specified by the - `Config.image_data_file` variable and displays it in the template. - - The image is saved to a file in the directory specified by the - `Config.upload_image_path` variable. - - The most recent image is displayed. - - The image is displayed in the template with the name "image_path". - - Returns: - A rendered template with the image path. - """ - if os.path.exists(Config.image_data_file): - with open(Config.image_data_file) as file: - image_data = json.load(file) - encoded_image = image_data.get("base64_image", "") - decoded_image_data = base64.b64decode(encoded_image) - image = Image.open(io.BytesIO(decoded_image_data)) - filename = "final.png" - image.save( - os.path.join( - Config.upload_image_path[0], - filename, - ), - quality=100, - ) - image = sorted( - os.listdir(Config.upload_image_path[0]), - key=lambda x: os.path.getatime( - os.path.join(Config.upload_image_path[0], x), - ), - reverse=True, - ) - if image: - recent_image = image[0] - image_path = os.path.join(Config.upload_image_path[0], recent_image) - else: - recent_image = None - image_path = os.path.join(Config.upload_image_path[0], recent_image) - print("done") + """Route to display the captured image.""" + try: + if os.path.exists(Config.image_data_file): + with open(Config.image_data_file) as file: + image_data = json.load(file) + + encoded_image = image_data.get("base64_image", "") + decoded_image_data = base64.b64decode(encoded_image) + image = Image.open(io.BytesIO(decoded_image_data)) + + filename = "final.png" + image.save(os.path.join( + Config.upload_image_path[0], filename), quality=100) + + image_files = sorted( + os.listdir(Config.upload_image_path[0]), + key=lambda x: os.path.getatime( + os.path.join(Config.upload_image_path[0], x) + ), + reverse=True, + ) + recent_image = image_files[0] if image_files else None + else: + recent_image = None + except Exception as e: + flash(f"Error loading image: {e}") + return render_template("index.html", image_path=None) + + image_path = ( + os.path.join(Config.upload_image_path[0], recent_image) + if recent_image + else None + ) return render_template("index.html", image_path=image_path) @Edit_blueprint.route("/edit/", methods=["POST", "GET"]) def edit(EmployeeCode): - """Edit an existing employee. - - This route allows users to edit an existing employee record. The - employee is identified by the EmployeeCode, which is a required - parameter. - - The route accepts both GET and POST requests. A GET request will - retrieve the employee data from the database and display it in - the template. A POST request will update the employee data in the - database with the values provided in the form. - - The form data is expected to contain the following fields: - - - Name - - gender - - Department + """Edit an existing employee.""" + if request.method == "POST": + form_data = { + "Name": request.form["Name"], + "gender": request.form["Gender"], + "Department": request.form["Department"], + } - The image is expected to be stored in the `Config.image_data_file` - file. + if not validate_input(form_data): + return redirect(f"/edit/{EmployeeCode}") - The most recent image is displayed. + try: + with open(Config.image_data_file) as file: + image_data = json.load(file) - The image is displayed in the template with the name "image_path". + encoded_image = image_data.get("base64_image", "") + payload = {**form_data, "Image": encoded_image} - Returns: - A rendered template with the image path if the request is a - GET, or a redirect to the home page if the request is a POST. - """ - if request.method == "POST": - Name = request.form["Name"] - gender = request.form["Gender"] - Department = request.form["Department"] - with open(Config.image_data_file) as file: - image_data = json.load(file) - encoded_image = image_data.get("base64_image", "") - payload = { - "Name": Name, - "gender": gender, - "Department": Department, - "Image": encoded_image, - } - # logger.info(payload) - try: - url = requests.put( - f"http://127.0.0.1:8000/update/{EmployeeCode}", - json=payload, + response = requests.put( + f"http://127.0.0.1:8000/update/{EmployeeCode}", json=payload ) - url.status_code - # logger.info(url.json()) - + if response.status_code != 200: + flash(f"Failed to update employee: {response.status_code}") return redirect("/") - except requests.exceptions.RequestException as e: - print(f"Request failed: {e}") - response = requests.get(f"http://127.0.0.1:8000/read/{EmployeeCode}") - # logger.info(response.status_code) - # logger.info(response.json()) - if response.status_code == 200: - employee_data = response.json() - return render_template("edit.html", employee_data=employee_data) - else: - return f"Error {response.status_code}: Failed to retrieve employee data." + flash(f"Request failed: {e}") + return redirect(f"/edit/{EmployeeCode}") + + try: + response = requests.get(f"http://127.0.0.1:8000/read/{EmployeeCode}") + if response.status_code == 200: + employee_data = response.json() + return render_template("edit.html", employee_data=employee_data) + else: + flash( + f"Error {response.status_code}: Failed to retrieve employee data.") + return render_template("edit.html", employee_data=None) + except requests.exceptions.RequestException as e: + flash(f"Error fetching employee data: {e}") + return render_template("edit.html", employee_data=None)