tanuj-maheshwari / Face-Recognition-API

Python based API service that performs "facial search" on a database of images.
3 stars 1 forks source link
fastapi solid-principles

Face Recognition API

Submitter name: Tanuj Maheshwari

Roll No.: 2019CSB1125

Course: CS305 (Software Engineering)

Python based API service that performs "facial search" on a database of images.

What does this program do?

This is a Python API, built using FastAPI, that can be used to perform "facial search" on images stored on the server in a Relational Database (specifically MySQL) to get the top-k matches for all the faces in an input image.

The application uses ageitgey's facial recognition library for facial matching.

A description of how this program works (i.e. its logic)

Multi-Processing

As the processing of images in batch upload is computationally a very heavy task, multiprocessing has been used.

The parent process creates a child process pool of 8 processes using the multiprocessing.Pool() Python API. Similar multiprocessing has also been used to retrieve top k image matches (which is further optimsed using min-heap instead of simple sorting).

The server runs on gunicorn (which is a wrapper for uvicorn), which supports a multithreaded server. Hence, simultaneous calls can be made to the endpoints.

In the command below, 4 workers have been used. Hence, upto 4 processes can run concurently (other processes will be queued until the outstanding requests are completed).

SOLID principles applied

The application follows SOLID principles so that further extension is easy and intutive. Such principles have been used throughout the assignment, and some of the prime examples are explained below :-

Database

The database has been implemented through 4 classes :-

Image

Image related operations are done using 4 classes :-

API

The API functions are implemnted using two classes :-

API endpoints

How to compile and run this program

Prerequisites and Setup

To run the server

To run the server, open a terminal in the directory and run :-

python3 -m gunicorn app:app --workers 4 --worker-class uvicorn.workers.UvicornWorker --bind 127.0.0.1:8000

Kill the server by pressing Ctrl + C.

NOTE

  • It might be possible that MySQL server is failing to connect. The issue can be solved by restarting the MySQL server using :-

    sudo service mysql restart
  • gunicorn might not be able to connect to the given port (as either there might already be some processes running on the port, or some other gunicorn forked processes might be active). To solve the issue, you can do the following :-

    • Kill all the running gunicorn services, using :-

      killall gunicorn
    • Kill the processes running on the port, using :-

      sudo kill `sudo lsof -t -i:8000`

      Make sure not to kill processes on well defined ports (such as port 3306 where MySQL runs)

    • Change the port where the app is to be deployed in the gunicorn command

To run pytests

To run the pytests provided within the implementation, open a terminal in the folder location and run :-

python3 -m pytest

NOTE: To successfully run the tests (without failure), the IMAGE_DATASET table should not exist in the database. If it does, drop the table and then run the tests.

SIDENOTES :-

  1. To upload the LFW dataset, uncomment line 13, 14 and 16 in test_app.py, and comment line 15. Also download the LFW dataset, a copy of which is available here, and place it inside the test_images folder. (Note that the API will not work for the original LFW downloaded file because it contains a .tar file inside of a .zip file)

    Note that the test might fail, as the number of images inserted depends from system to system. But all the well defined images will be inserted in the database.

  2. To test an image in LFW dataset, uncoment line 36 and 39, and comment line 35 and 38, after ensuring that the LFW dataset is already inserted in the dataset

To generate code coverage report

Code coverage is implemented using Coverage.py module. To generate coverage report, do the follwoing steps :-

  1. Run the pytest using coverage run

    python3 -m coverage run --source=. -m pytest
  2. Generate coverage report

    python3 -m coverage report
  3. To generate detailed coverage report with hit/miss sections, run :-

    python3 -m coverage html

Snapshot of a sample run

Pytest

Below is a snapshot of passed pytest tests.

Pytest Report

Coverage report

The unit tests provided cover 87% of the code. Below is a snapshot of the code coverage report.

Coverage Report