Spaces:
Running
Running
| # built-in dependencies | |
| from typing import Union, cast, Any, Tuple, Dict | |
| # 3rd party dependencies | |
| from flask import Blueprint, request | |
| from numpy.typing import NDArray | |
| # project dependencies | |
| from deepface import __version__ | |
| from deepface.api.src.modules.core import service | |
| from deepface.api.src.dependencies.variables import Variables | |
| from deepface.api.src.dependencies.container import Container | |
| from deepface.commons import image_utils | |
| from deepface.commons.logger import Logger | |
| logger = Logger() | |
| blueprint = Blueprint("routes", __name__) | |
| # pylint: disable=no-else-return, broad-except | |
| def home() -> str: | |
| return f"<h1>Welcome to DeepFace API v{__version__}!</h1>" | |
| def extract_image_from_request(img_key: str) -> Union[str, NDArray[Any]]: | |
| """ | |
| Extracts an image from the request either from json or a multipart/form-data file. | |
| Args: | |
| img_key (str): The key used to retrieve the image data | |
| from the request (e.g., 'img1'). | |
| Returns: | |
| img (str or np.ndarray): Given image detail (base64 encoded string, image path or url) | |
| or the decoded image as a numpy array. | |
| """ | |
| # Check if the request is multipart/form-data (file input) | |
| if request.files: | |
| # request.files is instance of werkzeug.datastructures.ImmutableMultiDict | |
| # file is instance of werkzeug.datastructures.FileStorage | |
| file = request.files.get(img_key) | |
| if file is None: | |
| raise ValueError(f"Request form data doesn't have {img_key}") | |
| if file.filename == "": | |
| raise ValueError(f"No file uploaded for '{img_key}'") | |
| np_img: NDArray[Any] = image_utils.load_image_from_file_storage(file) | |
| return np_img | |
| # Check if the request is coming as base64, file path or url from json or form data | |
| elif request.is_json or request.form: | |
| input_args = request.get_json() or request.form.to_dict() | |
| if input_args is None: | |
| raise ValueError("empty input set passed") | |
| # this can be base64 encoded image, and image path or url | |
| str_img: str = cast(str, input_args.get(img_key)) | |
| if not str_img: | |
| raise ValueError(f"'{img_key}' not found in either json or form data request") | |
| return str_img | |
| # If neither JSON nor file input is present | |
| raise ValueError(f"'{img_key}' not found in request in either json or form data") | |
| def represent() -> Tuple[Dict[str, Any], int]: | |
| # load injected container | |
| container: Container = blueprint.container # type: ignore[attr-defined] | |
| if not container.auth_service.validate(request.headers): | |
| return {"message": "Invalid or missing authentication token"}, 401 | |
| input_args = (request.is_json and request.get_json()) or ( | |
| request.form and request.form.to_dict() | |
| ) | |
| try: | |
| img = extract_image_from_request("img") | |
| except Exception as err: | |
| return {"exception": str(err)}, 400 | |
| max_faces = input_args.get("max_faces") | |
| obj, status_code = service.represent( | |
| img_path=img, | |
| model_name=input_args.get("model_name", "VGG-Face"), | |
| detector_backend=input_args.get("detector_backend", "opencv"), | |
| enforce_detection=bool(input_args.get("enforce_detection", True)), | |
| align=bool(input_args.get("align", True)), | |
| anti_spoofing=bool(input_args.get("anti_spoofing", False)), | |
| max_faces=int(max_faces) if max_faces is not None else None, | |
| ) | |
| logger.debug(obj) | |
| return obj, status_code | |
| def verify() -> Tuple[Dict[str, Any], int]: | |
| # load injected container | |
| container: Container = blueprint.container # type: ignore[attr-defined] | |
| if not container.auth_service.validate(request.headers): | |
| return {"message": "Invalid or missing authentication token"}, 401 | |
| input_args = (request.is_json and request.get_json()) or ( | |
| request.form and request.form.to_dict() | |
| ) | |
| try: | |
| img1 = extract_image_from_request("img1") | |
| except Exception as err: | |
| return {"exception": str(err)}, 400 | |
| try: | |
| img2 = extract_image_from_request("img2") | |
| except Exception as err: | |
| return {"exception": str(err)}, 400 | |
| verification, status_code = service.verify( | |
| img1_path=img1, | |
| img2_path=img2, | |
| model_name=input_args.get("model_name", "VGG-Face"), | |
| detector_backend=input_args.get("detector_backend", "opencv"), | |
| distance_metric=input_args.get("distance_metric", "cosine"), | |
| align=bool(input_args.get("align", True)), | |
| enforce_detection=bool(input_args.get("enforce_detection", True)), | |
| anti_spoofing=bool(input_args.get("anti_spoofing", False)), | |
| ) | |
| logger.debug(verification) | |
| return verification, status_code | |
| def analyze() -> Tuple[Dict[str, Any], int]: | |
| # load injected container | |
| container: Container = blueprint.container # type: ignore[attr-defined] | |
| if not container.auth_service.validate(request.headers): | |
| return {"message": "Invalid or missing authentication token"}, 401 | |
| input_args = (request.is_json and request.get_json()) or ( | |
| request.form and request.form.to_dict() | |
| ) | |
| try: | |
| img = extract_image_from_request("img") | |
| except Exception as err: | |
| return {"exception": str(err)}, 400 | |
| actions = input_args.get("actions", ["age", "gender", "emotion", "race"]) | |
| # actions is the only argument instance of list or tuple | |
| # if request is form data, input args can either be text or file | |
| if isinstance(actions, str): | |
| actions = ( | |
| actions.replace("[", "") | |
| .replace("]", "") | |
| .replace("(", "") | |
| .replace(")", "") | |
| .replace('"', "") | |
| .replace("'", "") | |
| .replace(" ", "") | |
| .split(",") | |
| ) | |
| demographies, status_code = service.analyze( | |
| img_path=img, | |
| actions=actions, | |
| detector_backend=input_args.get("detector_backend", "opencv"), | |
| enforce_detection=bool(input_args.get("enforce_detection", True)), | |
| align=bool(input_args.get("align", True)), | |
| anti_spoofing=bool(input_args.get("anti_spoofing", False)), | |
| ) | |
| logger.debug(demographies) | |
| return demographies, status_code | |
| def register() -> Tuple[Dict[str, Any], int]: | |
| # load injected variables and container | |
| variables: Variables = blueprint.variables # type: ignore[attr-defined] | |
| container: Container = blueprint.container # type: ignore[attr-defined] | |
| if not container.auth_service.validate(request.headers): | |
| return {"message": "Invalid or missing authentication token"}, 401 | |
| if variables.conection_details is None: | |
| return { | |
| "error": "Database connection details must be provided in `DEEPFACE_CONNECTION_DETAILS`" | |
| " environment variables" | |
| }, 500 | |
| input_args = (request.is_json and request.get_json()) or ( | |
| request.form and request.form.to_dict() | |
| ) | |
| try: | |
| img = extract_image_from_request("img") | |
| except Exception as err: | |
| return {"exception": str(err)}, 400 | |
| result, status_code = service.register( | |
| img=img, | |
| img_name=input_args.get("img_name"), | |
| model_name=input_args.get("model_name", "VGG-Face"), | |
| detector_backend=input_args.get("detector_backend", "opencv"), | |
| enforce_detection=bool(input_args.get("enforce_detection", True)), | |
| align=bool(input_args.get("align", True)), | |
| l2_normalize=bool(input_args.get("l2_normalize", False)), | |
| expand_percentage=int(input_args.get("expand_percentage", 0)), | |
| normalization=input_args.get("normalization", "base"), | |
| anti_spoofing=bool(input_args.get("anti_spoofing", False)), | |
| database_type=variables.database_type, | |
| connection_details=variables.conection_details, | |
| ) | |
| if status_code == 200: | |
| logger.info("An image has been registered to the database.") | |
| else: | |
| logger.error("An error occurred while registering an image to the database.") | |
| return result, status_code | |
| def search() -> Tuple[Dict[str, Any], int]: | |
| # load injected variables and container | |
| variables: Variables = blueprint.variables # type: ignore[attr-defined] | |
| container: Container = blueprint.container # type: ignore[attr-defined] | |
| if not container.auth_service.validate(request.headers): | |
| return {"message": "Invalid or missing authentication token"}, 401 | |
| if variables.conection_details is None: | |
| return { | |
| "error": "Database connection details must be provided in `DEEPFACE_CONNECTION_DETAILS`" | |
| " environment variables" | |
| }, 500 | |
| input_args = (request.is_json and request.get_json()) or ( | |
| request.form and request.form.to_dict() | |
| ) | |
| try: | |
| img = extract_image_from_request("img") | |
| except Exception as err: | |
| return {"exception": str(err)}, 400 | |
| return service.search( | |
| img=img, | |
| model_name=input_args.get("model_name", "VGG-Face"), | |
| detector_backend=input_args.get("detector_backend", "opencv"), | |
| enforce_detection=bool(input_args.get("enforce_detection", True)), | |
| align=bool(input_args.get("align", True)), | |
| distance_metric=input_args.get("distance_metric", "cosine"), | |
| l2_normalize=bool(input_args.get("l2_normalize", False)), | |
| database_type=variables.database_type, | |
| connection_details=variables.conection_details, | |
| search_method=input_args.get("search_method", "exact"), | |
| expand_percentage=int(input_args.get("expand_percentage", 0)), | |
| normalization=input_args.get("normalization", "base"), | |
| anti_spoofing=bool(input_args.get("anti_spoofing", False)), | |
| similarity_search=bool(input_args.get("similarity_search", False)), | |
| k=int(input_args.get("k", 5)) if input_args.get("k") is not None else None, | |
| ) | |
| def build_index() -> Tuple[Dict[str, Any], int]: | |
| # load injected variables and container | |
| variables: Variables = blueprint.variables # type: ignore[attr-defined] | |
| container: Container = blueprint.container # type: ignore[attr-defined] | |
| if not container.auth_service.validate(request.headers): | |
| return {"message": "Invalid or missing authentication token"}, 401 | |
| if variables.conection_details is None: | |
| return { | |
| "error": "Database connection details must be provided in `DEEPFACE_CONNECTION_DETAILS`" | |
| " environment variables" | |
| }, 500 | |
| input_args = (request.is_json and request.get_json()) or ( | |
| request.form and request.form.to_dict() | |
| ) | |
| return service.build_index( | |
| model_name=input_args.get("model_name", "VGG-Face"), | |
| detector_backend=input_args.get("detector_backend", "opencv"), | |
| align=bool(input_args.get("align", True)), | |
| l2_normalize=bool(input_args.get("l2_normalize", False)), | |
| database_type=variables.database_type, | |
| connection_details=variables.conection_details, | |
| ) | |