-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from devansh-shah-11/merge-code-mark-1
Merge code mark 1
- Loading branch information
Showing
33 changed files
with
2,013 additions
and
71 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,7 +26,7 @@ jobs: | |
- name: Install dependencies | ||
run: | | ||
python -m pip install --upgrade pip | ||
pip install flake8 pytest | ||
pip install flake8 pytest pytest-cov | ||
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi | ||
- name: Lint with flake8 | ||
run: | | ||
|
@@ -36,4 +36,10 @@ jobs: | |
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics | ||
- name: Test with pytest | ||
run: | | ||
pytest | ||
pytest --cov . | ||
continue-on-error: true | ||
- name: Upload coverage reports to Codecov | ||
uses: codecov/[email protected] | ||
with: | ||
token: ${{ secrets.CODECOV_TOKEN }} | ||
slug: devansh-shah-11/FaceRec |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,142 @@ | ||
# Byte-compiled / optimized / DLL files | ||
__pycache__/ | ||
*.py[cod] | ||
*$py.class | ||
|
||
# C extensions | ||
*.so | ||
|
||
# Distribution / packaging | ||
.Python | ||
build/ | ||
develop-eggs/ | ||
dist/ | ||
downloads/ | ||
eggs/ | ||
.eggs/ | ||
lib/ | ||
lib64/ | ||
parts/ | ||
sdist/ | ||
var/ | ||
wheels/ | ||
share/python-wheels/ | ||
*.egg-info/ | ||
.installed.cfg | ||
*.egg | ||
MANIFEST | ||
|
||
# PyInstaller | ||
# Usually these files are written by a python script from a template | ||
# before PyInstaller builds the exe, so as to inject date/other infos into it. | ||
*.manifest | ||
*.spec | ||
|
||
# Installer logs | ||
pip-log.txt | ||
pip-delete-this-directory.txt | ||
|
||
# Unit test / coverage reports | ||
htmlcov/ | ||
.tox/ | ||
.nox/ | ||
.coverage | ||
.coverage.* | ||
.cache | ||
nosetests.xml | ||
coverage.xml | ||
*.cover | ||
*.py,cover | ||
.hypothesis/ | ||
.pytest_cache/ | ||
cover/ | ||
|
||
# Translations | ||
*.mo | ||
*.pot | ||
|
||
# Django stuff: | ||
*.log | ||
local_settings.py | ||
db.sqlite3 | ||
db.sqlite3-journal | ||
|
||
# Flask stuff: | ||
instance/ | ||
.webassets-cache | ||
|
||
# Scrapy stuff: | ||
.scrapy | ||
|
||
# Sphinx documentation | ||
docs/_build/ | ||
|
||
# PyBuilder | ||
.pybuilder/ | ||
target/ | ||
|
||
# Jupyter Notebook | ||
.ipynb_checkpoints | ||
|
||
# IPython | ||
profile_default/ | ||
ipython_config.py | ||
|
||
# pyenv | ||
# For a library or package, you might want to ignore these files since the code is | ||
# intended to run in multiple environments; otherwise, check them in: | ||
# .python-version | ||
|
||
# pipenv | ||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. | ||
# However, in case of collaboration, if having platform-specific dependencies or dependencies | ||
# having no cross-platform support, pipenv may install dependencies that don't work, or not | ||
# install all needed dependencies. | ||
#Pipfile.lock | ||
|
||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow | ||
__pypackages__/ | ||
|
||
# Celery stuff | ||
celerybeat-schedule | ||
celerybeat.pid | ||
|
||
# SageMath parsed files | ||
*.sage.py | ||
|
||
# Environments | ||
.env | ||
.venv | ||
env/ | ||
venv/ | ||
ENV/ | ||
env.bak/ | ||
venv.bak/ | ||
|
||
# Spyder project settings | ||
.spyderproject | ||
.spyproject | ||
|
||
# Rope project settings | ||
.ropeproject | ||
|
||
# mkdocs documentation | ||
/site | ||
|
||
# mypy | ||
.mypy_cache/ | ||
.dmypy.json | ||
dmypy.json | ||
|
||
# Pyre type checker | ||
.pyre/ | ||
|
||
# pytype static type analyzer | ||
.pytype/ | ||
|
||
# Cython debug symbols | ||
cython_debug/ | ||
venv/ | ||
*.pyc | ||
.vscode/ | ||
__pycache__/ | ||
__pyc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import uvicorn | ||
from fastapi import FastAPI | ||
|
||
from API import route | ||
|
||
Fastapp = FastAPI() | ||
# API Router | ||
Fastapp.include_router(route.router) | ||
|
||
|
||
@Fastapp.get("/") | ||
def read_root(): | ||
return {"Hello": "FASTAPI"} | ||
|
||
|
||
# function to run server of FastAPI | ||
def run_fastapi_app(): | ||
uvicorn.run(Fastapp, host="127.0.0.1", port=8000) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
from datetime import datetime | ||
|
||
from pymongo import MongoClient | ||
|
||
|
||
class Database: | ||
def __init__(self, uri="mongodb://localhost:27017/", db_name="ImageDB"): | ||
self.client = MongoClient(uri) | ||
self.db = self.client[db_name] | ||
|
||
def find(self, collection, query=None): | ||
return self.db[collection].find(query) | ||
|
||
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_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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
import base64 | ||
import json | ||
import logging | ||
import os | ||
from datetime import datetime | ||
from io import BytesIO | ||
|
||
from bson import ObjectId | ||
from deepface import DeepFace | ||
from fastapi import APIRouter, Form, HTTPException, Response | ||
from matplotlib import pyplot as plt | ||
from PIL import Image | ||
from pydantic import BaseModel | ||
from pymongo import MongoClient | ||
|
||
from API.database import Database | ||
|
||
# Create a logger object | ||
logger = logging.getLogger(__name__) | ||
# Create a file handler | ||
handler = logging.FileHandler("log.log") | ||
handler.setLevel(logging.INFO) | ||
# Create a logging format | ||
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") | ||
handler.setFormatter(formatter) | ||
|
||
router = APIRouter() | ||
|
||
# To create connection with Mongodb | ||
# mongodb_uri = "mongodb://localhost:27017/" | ||
# port = 8000 | ||
# client = MongoClient(mongodb_uri, port) | ||
|
||
# db = client["ImageDB"] | ||
client = Database() | ||
|
||
collection = "faceEntries" | ||
|
||
|
||
# Models for the data to be sent and received by the server | ||
class Employee(BaseModel): | ||
EmployeeCode: int | ||
Name: str | ||
gender: str | ||
Department: str | ||
Image: str | ||
|
||
|
||
class UpdateEmployee(BaseModel): | ||
Name: str | ||
gender: str | ||
Department: str | ||
Image: str | ||
|
||
|
||
# To create new entries of employee | ||
@router.post("/create_new_faceEntry") | ||
async def create_new_faceEntry(Employee: Employee): | ||
Name = Employee.Name | ||
EmployeeCode = Employee.EmployeeCode | ||
gender = Employee.gender | ||
Department = Employee.Department | ||
encoded_image = Employee.Image | ||
time = datetime.now() | ||
img_recovered = base64.b64decode(encoded_image) # decode base64string | ||
# print(img_recovered) | ||
pil_image = Image.open(BytesIO(img_recovered)) | ||
image_filename = f"{Name}.png" | ||
pil_image.save(image_filename) | ||
# print path of the current working directory | ||
pil_image.save(f"Images\dbImages\{Name}.jpg") | ||
# Extract the face from the image | ||
face_image_data = DeepFace.extract_faces( | ||
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"]) | ||
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, | ||
{ | ||
"EmployeeCode": EmployeeCode, | ||
"Name": Name, | ||
"gender": gender, | ||
"Department": Department, | ||
"time": time, | ||
"embeddings": embeddings, | ||
"Image": encoded_image, | ||
}, | ||
) | ||
# db.faceEntries.insert_one( | ||
|
||
# ) | ||
return {"message": "Face entry created successfully"} | ||
|
||
|
||
# To display all records | ||
@router.get("/Data/", response_model=list[Employee]) | ||
async def get_employees(): | ||
employees_mongo = client.find(collection) | ||
employees = [ | ||
Employee( | ||
EmployeeCode=int(employee.get("EmployeeCode", 0)), | ||
Name=employee.get("Name", "N/A"), | ||
gender=employee.get("gender", "N/A"), | ||
Department=employee.get("Department", "N/A"), | ||
Image=employee.get("Image", "N/A"), | ||
) | ||
for employee in employees_mongo | ||
] | ||
return employees | ||
|
||
|
||
# To display specific record info | ||
@router.get("/read/{EmployeeCode}", response_class=Response) | ||
async def read_employee(EmployeeCode: int): | ||
try: | ||
# logger.info(f"Start {EmployeeCode}") | ||
items = client.find_one( | ||
collection, | ||
filter={"EmployeeCode": EmployeeCode}, | ||
projection={ | ||
"Name": True, | ||
"gender": True, | ||
"Department": True, | ||
"Image": True, | ||
"_id": False, | ||
}, | ||
) | ||
if items: | ||
json_items = json.dumps(items) | ||
return Response( | ||
content=bytes(json_items, "utf-8"), media_type="application/json" | ||
) | ||
else: | ||
return Response( | ||
content=json.dumps({"message": "Employee not found"}), | ||
media_type="application/json", | ||
status_code=404, | ||
) | ||
except Exception as e: | ||
print(e) | ||
|
||
|
||
# For updating existing record | ||
@router.put("/update/{EmployeeCode}", response_model=str) | ||
async def update_employees(EmployeeCode: int, Employee: UpdateEmployee): | ||
try: | ||
# logger.warning("Updating Start") | ||
user_id = client.find_one( | ||
collection, {"EmployeeCode": EmployeeCode}, projection={"_id": True} | ||
) | ||
print(user_id) | ||
if not user_id: | ||
raise HTTPException(status_code=404, detail="Employee not found") | ||
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, | ||
filter={"_id": ObjectId(user_id["_id"])}, | ||
update={"$set": Employee_data}, | ||
) | ||
if update_result.modified_count == 0: | ||
raise HTTPException(status_code=400, detail="No data was updated") | ||
return "Updated Successfully" | ||
except Exception as e: | ||
# logger.error(f"Error while updating: {e}") | ||
raise HTTPException(status_code=500, detail="Internal server error") | ||
except Exception as e: | ||
# logger.error(f"Error while fetching user_id: {e}") | ||
raise HTTPException(status_code=500, detail="Internal server error") | ||
|
||
|
||
# To delete employee record | ||
@router.delete("/delete/{EmployeeCode}") | ||
async def delete_employees(EmployeeCode: int): | ||
print(EmployeeCode) | ||
client.find_one_and_delete(collection, {"EmployeeCode": EmployeeCode}) | ||
|
||
return {"Message": "Successfully Deleted"} |
Oops, something went wrong.