diff --git a/API/database.py b/API/database.py index 6e31cd7..ccdfc98 100644 --- a/API/database.py +++ b/API/database.py @@ -1,6 +1,7 @@ -from pymongo import MongoClient from datetime import datetime +from pymongo import MongoClient + class Database: def __init__(self, uri="mongodb://localhost:27017/", db_name="ImageDB"): @@ -13,11 +14,11 @@ def find(self, collection, query=None): def insert_one(self, collection, document): return self.db[collection].insert_one(document) - def find_one(self, collection,filter, projection=None): - return self.db[collection].find_one(filter=filter ,projection=projection) - + def find_one(self, collection, filter, projection=None): + return self.db[collection].find_one(filter=filter, projection=projection) + def find_one_and_delete(self, collection, query): return self.db[collection].find_one_and_delete(query) - + def update_one(self, collection, query, update): return self.db[collection].update_one(query, update) diff --git a/API/route.py b/API/route.py index d884cc6..b0efca9 100644 --- a/API/route.py +++ b/API/route.py @@ -12,6 +12,7 @@ from PIL import Image from pydantic import BaseModel from pymongo import MongoClient + from API.database import Database # Create a logger object @@ -33,7 +34,7 @@ # db = client["ImageDB"] client = Database() -collection="faceEntries" +collection = "faceEntries" # Models for the data to be sent and received by the server @@ -73,13 +74,15 @@ async def create_new_faceEntry(Employee: Employee): image_filename, detector_backend="mtcnn", enforce_detection=False ) # Calculate the embeddings of the face image - plt.imsave(f"Images/Faces/{Name}.jpg", face_image_data[0]['face']) + plt.imsave(f"Images/Faces/{Name}.jpg", face_image_data[0]["face"]) embeddings = DeepFace.represent( image_filename, model_name="Facenet", detector_backend="mtcnn" ) os.remove(image_filename) # Store the data in the database - client.insert_one(collection, { + client.insert_one( + collection, + { "EmployeeCode": EmployeeCode, "Name": Name, "gender": gender, @@ -87,9 +90,10 @@ async def create_new_faceEntry(Employee: Employee): "time": time, "embeddings": embeddings, "Image": encoded_image, - }) + }, + ) # db.faceEntries.insert_one( - + # ) return {"message": "Face entry created successfully"} @@ -116,7 +120,8 @@ async def get_employees(): async def read_employee(EmployeeCode: int): try: # logger.info(f"Start {EmployeeCode}") - items = client.find_one(collection, + items = client.find_one( + collection, filter={"EmployeeCode": EmployeeCode}, projection={ "Name": True, @@ -146,8 +151,8 @@ async def read_employee(EmployeeCode: int): async def update_employees(EmployeeCode: int, Employee: UpdateEmployee): try: # logger.warning("Updating Start") - user_id = client.find_one(collection, - {"EmployeeCode": EmployeeCode}, projection={"_id": True} + user_id = client.find_one( + collection, {"EmployeeCode": EmployeeCode}, projection={"_id": True} ) print(user_id) if not user_id: @@ -155,7 +160,8 @@ async def update_employees(EmployeeCode: int, Employee: UpdateEmployee): Employee_data = Employee.model_dump(by_alias=True, exclude_unset=True) # logger.info(f"Employee data to update: {Employee_data}") try: - update_result = client.update_one(collection, + update_result = client.update_one( + collection, filter={"_id": ObjectId(user_id["_id"])}, update={"$set": Employee_data}, ) diff --git a/FaceRec/app/main/Employee.py b/FaceRec/app/main/Employee.py index 76e27e8..a652834 100644 --- a/FaceRec/app/main/Employee.py +++ b/FaceRec/app/main/Employee.py @@ -94,23 +94,27 @@ def submit_form(): } url = "http://127.0.0.1:8000/create_new_faceEntry" try: - resp = requests.post(url=url, json={ - "EmployeeCode": 134, - "Name": "Name", - "gender": "gender", - "Department": "Department", - "Image": "your_image", - }) + resp = requests.post( + url=url, + json={ + "EmployeeCode": 134, + "Name": "Name", + "gender": "gender", + "Department": "Department", + "Image": "your_image", + }, + ) resp.status_code except requests.exceptions.RequestException as e: print(f"Request failed: {e}") jsonify({"message": "Successfully executed"}) print("Executed.") - if resp.status_code==200: + if resp.status_code == 200: return redirect("DisplayingEmployees") else: return jsonify({"message": "Failed to execute"}) + # To edit an employee details @flk_blueprint.route("/edit/", methods=["POST", "GET"]) def edit(EmployeeCode): diff --git a/requirements.txt b/requirements.txt index f1815fe..4ce1e20 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,44 +1,26 @@ -absl-py==2.0.0 -aiohttp==3.9.1 -aiosignal==1.3.1 -annotated-types==0.6.0 -anyio==4.2.0 -asttokens==2.4.1 -astunparse==1.6.3 -attrs==23.2.0 absl-py==2.1.0 annotated-types==0.6.0 anyio==4.2.0 astunparse==1.6.3 beautifulsoup4==4.12.2 -black==24.2.0 blinker==1.7.0 cachetools==5.3.2 certifi==2023.11.17 -cffi==1.16.0 charset-normalizer==3.3.2 click==8.1.7 colorama==0.4.6 -comm==0.2.1 contourpy==1.2.0 -coverage==7.4.3 -cryptography==41.0.7 cycler==0.12.1 -debugpy==1.8.0 -decorator==5.1.1 deepface==0.0.81 Deprecated==1.2.14 dnspython==2.4.2 -docker==7.0.0 exceptiongroup==1.2.0 -executing==2.0.1 fastapi==0.108.0 filelock==3.13.1 fire==0.5.0 Flask==3.0.0 flatbuffers==23.5.26 fonttools==4.47.2 -frozenlist==1.4.1 gast==0.5.4 gdown==4.7.3 google-auth==2.26.2 @@ -51,59 +33,39 @@ h5py==3.10.0 httpcore==1.0.2 httpx==0.26.0 idna==3.6 +importlib-metadata==7.0.1 +importlib-resources==6.1.1 iniconfig==2.0.0 -ipykernel==6.29.0 -ipython==8.20.0 -isort==5.13.2 itsdangerous==2.1.2 -jedi==0.19.1 Jinja2==3.1.3 -jupyter_client==8.6.0 -jupyter_core==5.7.1 keras==2.15.0 kiwisolver==1.4.5 libclang==16.0.6 Markdown==3.5.2 MarkupSafe==2.1.3 matplotlib==3.8.2 -matplotlib-inline==0.1.6 ml-dtypes==0.2.0 mtcnn==0.1.1 -multidict==6.0.4 -mypy-extensions==1.0.0 -nest-asyncio==1.5.9 numpy==1.26.3 oauthlib==3.2.2 opencv-python==4.9.0.80 opt-einsum==3.3.0 packaging==23.2 pandas==2.1.4 -parso==0.8.3 -pathspec==0.12.1 pillow==10.2.0 -platformdirs==4.1.0 pluggy==1.3.0 -prompt-toolkit==3.0.43 protobuf==4.23.4 -psutil==5.9.7 -pure-eval==0.2.2 pyasn1==0.5.1 pyasn1-modules==0.3.0 -pycparser==2.21 pydantic==2.5.3 pydantic_core==2.14.6 -Pygments==2.17.2 pymongo==4.6.1 pyparsing==3.1.1 PySocks==1.7.1 pytest==7.4.4 -pytest-cov==4.1.0 python-dateutil==2.8.2 python-multipart==0.0.6 pytz==2023.3.post1 -pyvespa==0.39.0 -pywin32==306 -pyzmq==25.1.2 requests==2.31.0 requests-oauthlib==1.3.1 retina-face==0.0.13 @@ -111,28 +73,19 @@ rsa==4.9 six==1.16.0 sniffio==1.3.0 soupsieve==2.5 -stack-data==0.6.3 starlette==0.32.0.post1 -tenacity==8.2.3 tensorboard==2.15.1 tensorboard-data-server==0.7.2 tensorflow==2.15.0 tensorflow-estimator==2.15.0 -tensorflow-intel==2.15.0 tensorflow-io-gcs-filesystem==0.31.0 termcolor==2.4.0 -tokenize-rt==5.2.0 tomli==2.0.1 -tornado==6.4 tqdm==4.66.1 -traitlets==5.14.1 typing_extensions==4.9.0 tzdata==2023.4 urllib3==2.1.0 uvicorn==0.25.0 -wcwidth==0.2.13 Werkzeug==3.0.1 wrapt==1.14.1 -yarl==1.9.4 - zipp==3.17.0 \ No newline at end of file diff --git a/route/route.py b/route/route.py index 253cb31..100979a 100644 --- a/route/route.py +++ b/route/route.py @@ -1,24 +1,26 @@ -from fastapi import FastAPI, File, UploadFile -from fastapi.responses import FileResponse import os +import uuid from datetime import datetime -from pymongo import MongoClient from random import randint -import uuid + from deepface import DeepFace +from fastapi import FastAPI, File, UploadFile +from fastapi.responses import FileResponse from matplotlib import pyplot as plt +from pymongo import MongoClient IMAGEDIR = "test-faces/" -mongodb_uri ='mongodb://localhost:27017/' +mongodb_uri = "mongodb://localhost:27017/" port = 8000 -client = MongoClient(mongodb_uri,port) +client = MongoClient(mongodb_uri, port) db = client["ImageDB"] faceEntries = db["faceEntries"] app = FastAPI() + # deprecated @app.post("/upload/") async def register_face(file: UploadFile = File(...)): @@ -26,7 +28,7 @@ async def register_face(file: UploadFile = File(...)): file.filename = f"{uuid.uuid4()}.jpg" contents = await file.read() - #save the file + # save the file with open(f"{IMAGEDIR}{file.filename}", "wb") as f: f.write(contents) # db.images.insert_one({"filename": file.filename, "contents": contents}) @@ -34,7 +36,9 @@ async def register_face(file: UploadFile = File(...)): @app.post("/create_new_faceEntry") -async def create_new_faceEntry(id:int, age: int, gender: str, image: UploadFile = File(...)): +async def create_new_faceEntry( + id: int, age: int, gender: str, image: UploadFile = File(...) +): # Generate a unique ID # id = uuid.uuid4() @@ -49,26 +53,35 @@ async def create_new_faceEntry(id:int, age: int, gender: str, image: UploadFile f.write(image_data) # Extract the face from the image - face_image_data = DeepFace.extract_faces(f"../Images/dbImages/{image.filename}", detector_backend="mtcnn") + face_image_data = DeepFace.extract_faces( + f"../Images/dbImages/{image.filename}", detector_backend="mtcnn" + ) # Save the face image in a specified directory - plt.imsave(f"../Images/Faces/{image.filename}", face_image_data[0]['face']) + plt.imsave(f"../Images/Faces/{image.filename}", face_image_data[0]["face"]) # Calculate the embeddings of the face image - embeddings = DeepFace.represent(f"../Images/dbImages/{image.filename}", model_name="Facenet", detector_backend="mtcnn") + embeddings = DeepFace.represent( + f"../Images/dbImages/{image.filename}", + model_name="Facenet", + detector_backend="mtcnn", + ) # Store the data in the database - db.faceEntries.insert_one({ - "id": id, - "age": age, - "gender": gender, - "time": time, - "embeddings": embeddings, - # "face-img": face_image_data, - }) + db.faceEntries.insert_one( + { + "id": id, + "age": age, + "gender": gender, + "time": time, + "embeddings": embeddings, + # "face-img": face_image_data, + } + ) return {"message": "Face entry created successfully"} + @app.get("/show/") async def read_random_file(): @@ -77,9 +90,10 @@ async def read_random_file(): random_index = randint(0, len(files) - 1) path = f"{IMAGEDIR}{files[random_index]}" - + return FileResponse(path) + @app.delete("/delete/{filename}") async def delete_file(filename: str): os.remove(f"{IMAGEDIR}/{filename}") diff --git a/testing/test_face_cycle.py b/testing/test_face_cycle.py index 102a01d..93562db 100644 --- a/testing/test_face_cycle.py +++ b/testing/test_face_cycle.py @@ -1,20 +1,26 @@ import base64 from unittest.mock import MagicMock, patch -from API.database import Database + from fastapi.testclient import TestClient +from API.database import Database from API.route import router client = TestClient(router) - @patch("API.database.Database.find_one_and_delete") @patch("API.database.Database.update_one") @patch("API.database.Database.find_one") @patch("API.database.Database.find") @patch("API.database.Database.insert_one") -def test_face_lifecycle(mock_insert_one: MagicMock, mock_find: MagicMock, mock_find_one: MagicMock, mock_update_one: MagicMock, mock_find_one_and_delete: MagicMock): +def test_face_lifecycle( + mock_insert_one: MagicMock, + mock_find: MagicMock, + mock_find_one: MagicMock, + mock_update_one: MagicMock, + mock_find_one_and_delete: MagicMock, +): # Register two new faces mock_doc = { "_id": "65e6284d01f95cd96ea334a7", diff --git a/testing/test_register_face.py b/testing/test_register_face.py index 4414397..f51be4a 100644 --- a/testing/test_register_face.py +++ b/testing/test_register_face.py @@ -13,9 +13,7 @@ def test_register_face(): # Open a test image file in binary mode IMAGEDIR = "test-faces/" - with open( - "./test-faces/devansh.jpg", "rb" - ) as image_file: + with open("./test-faces/devansh.jpg", "rb") as image_file: encoded_string = base64.b64encode(image_file.read()).decode("utf-8") response = client.post( "/create_new_faceEntry",