diff --git a/uniface/__init__.py b/uniface/__init__.py index b494472..1e2a2d8 100644 --- a/uniface/__init__.py +++ b/uniface/__init__.py @@ -22,6 +22,7 @@ from uniface.model_store import verify_model_weights from uniface.visualization import draw_detections from .attribute import AgeGender + try: from .attribute import Emotion except ImportError: diff --git a/uniface/attribute/__init__.py b/uniface/attribute/__init__.py index 62bb82d..24e9bb7 100644 --- a/uniface/attribute/__init__.py +++ b/uniface/attribute/__init__.py @@ -2,7 +2,8 @@ # Author: Yakhyokhuja Valikhujaev # GitHub: https://github.com/yakhyo -from typing import Dict, Any, List, Union +from typing import Any, Dict, List, Union + import numpy as np from uniface.attribute.age_gender import AgeGender diff --git a/uniface/attribute/base.py b/uniface/attribute/base.py index f3697da..33b548a 100644 --- a/uniface/attribute/base.py +++ b/uniface/attribute/base.py @@ -4,6 +4,7 @@ from abc import ABC, abstractmethod from typing import Any + import numpy as np diff --git a/uniface/attribute/emotion.py b/uniface/attribute/emotion.py index 8602b60..b82ffb8 100644 --- a/uniface/attribute/emotion.py +++ b/uniface/attribute/emotion.py @@ -2,15 +2,16 @@ # Author: Yakhyokhuja Valikhujaev # GitHub: https://github.com/yakhyo +from typing import List, Tuple, Union + import cv2 -import torch import numpy as np -from typing import Tuple, Union, List +import torch from uniface.attribute.base import Attribute -from uniface.log import Logger from uniface.constants import DDAMFNWeights from uniface.face_utils import face_alignment +from uniface.log import Logger from uniface.model_store import verify_model_weights __all__ = ["Emotion"] @@ -77,7 +78,7 @@ class Emotion(Attribute): torch.Tensor: The preprocessed image tensor ready for inference. """ landmark = np.asarray(landmark) - + aligned_image, _ = face_alignment(image, landmark) # Convert BGR to RGB, resize, normalize, and convert to a CHW tensor @@ -151,7 +152,7 @@ if __name__ == "__main__": # Predict attributes using the landmark emotion, confidence = emotion_predictor.predict(frame, landmark) - + # Prepare text and draw on the frame label = f"{emotion} ({confidence:.2f})" cv2.rectangle(frame, (x1, y1), (x2, y2), (255, 0, 0), 2) @@ -167,4 +168,4 @@ if __name__ == "__main__": # Release resources cap.release() cv2.destroyAllWindows() - print("Inference stopped.") \ No newline at end of file + print("Inference stopped.") diff --git a/uniface/common.py b/uniface/common.py index 9133203..4c3064c 100644 --- a/uniface/common.py +++ b/uniface/common.py @@ -2,12 +2,12 @@ # Author: Yakhyokhuja Valikhujaev # GitHub: https://github.com/yakhyo -import cv2 -import math import itertools -import numpy as np +import math +from typing import List, Tuple -from typing import Tuple, List +import cv2 +import numpy as np def resize_image(frame, target_shape: Tuple[int, int] = (640, 640)) -> Tuple[np.ndarray, float]: diff --git a/uniface/constants.py b/uniface/constants.py index de6b806..dcd4857 100644 --- a/uniface/constants.py +++ b/uniface/constants.py @@ -5,6 +5,7 @@ from enum import Enum from typing import Dict + # fmt: off class SphereFaceWeights(str, Enum): """ diff --git a/uniface/detection/__init__.py b/uniface/detection/__init__.py index 95ce09d..24be71c 100644 --- a/uniface/detection/__init__.py +++ b/uniface/detection/__init__.py @@ -3,12 +3,13 @@ # GitHub: https://github.com/yakhyo -import numpy as np -from typing import Tuple, Dict, Any, List +from typing import Any, Dict, List + +import numpy as np -from .scrfd import SCRFD from .base import BaseDetector from .retinaface import RetinaFace +from .scrfd import SCRFD # Global cache for detector instances _detector_cache: Dict[str, BaseDetector] = {} @@ -38,7 +39,7 @@ def detect_faces(image: np.ndarray, method: str = 'retinaface', **kwargs) -> Lis ... print(f"BBox: {face['bbox']}") """ method_name = method.lower() - + sorted_kwargs = sorted(kwargs.items()) cache_key = f"{method_name}_{str(sorted_kwargs)}" diff --git a/uniface/detection/base.py b/uniface/detection/base.py index 509a06d..18f3893 100644 --- a/uniface/detection/base.py +++ b/uniface/detection/base.py @@ -6,9 +6,10 @@ Base classes for face detection. """ -import numpy as np from abc import ABC, abstractmethod -from typing import Tuple, Dict, Any +from typing import Any, Dict, Tuple + +import numpy as np class BaseDetector(ABC): diff --git a/uniface/detection/retinaface.py b/uniface/detection/retinaface.py index 659c0e4..f1fcbef 100644 --- a/uniface/detection/retinaface.py +++ b/uniface/detection/retinaface.py @@ -2,23 +2,17 @@ # Author: Yakhyokhuja Valikhujaev # GitHub: https://github.com/yakhyo +from typing import Any, Dict, List, Literal, Tuple + import numpy as np -from typing import Tuple, List, Literal, Dict, Any - +from uniface.constants import RetinaFaceWeights from uniface.log import Logger from uniface.model_store import verify_model_weights -from uniface.constants import RetinaFaceWeights from uniface.onnx_utils import create_onnx_session from .base import BaseDetector -from .utils import ( - non_max_supression, - resize_image, - decode_boxes, - generate_anchors, - decode_landmarks -) +from .utils import decode_boxes, decode_landmarks, generate_anchors, non_max_supression, resize_image class RetinaFace(BaseDetector): diff --git a/uniface/detection/utils.py b/uniface/detection/utils.py index f93eeca..af89c43 100644 --- a/uniface/detection/utils.py +++ b/uniface/detection/utils.py @@ -2,12 +2,12 @@ # Author: Yakhyokhuja Valikhujaev # GitHub: https://github.com/yakhyo -import cv2 -import math import itertools -import numpy as np +import math +from typing import List, Tuple -from typing import Tuple, List +import cv2 +import numpy as np def resize_image(frame, target_shape: Tuple[int, int] = (640, 640)) -> Tuple[np.ndarray, float]: diff --git a/uniface/face_utils.py b/uniface/face_utils.py index d50a95d..6e5a357 100644 --- a/uniface/face_utils.py +++ b/uniface/face_utils.py @@ -2,11 +2,11 @@ # Author: Yakhyokhuja Valikhujaev # GitHub: https://github.com/yakhyo +from typing import Tuple, Union + import cv2 import numpy as np from skimage.transform import SimilarityTransform -from typing import Tuple, Union - __all__ = ["face_alignment", "compute_similarity", "bbox_center_alignment", "transform_points_2d"] diff --git a/uniface/landmark/__init__.py b/uniface/landmark/__init__.py index fcc3953..ad81c70 100644 --- a/uniface/landmark/__init__.py +++ b/uniface/landmark/__init__.py @@ -2,8 +2,8 @@ # Author: Yakhyokhuja Valikhujaev # GitHub: https://github.com/yakhyo -from .models import Landmark106 from .base import BaseLandmarker +from .models import Landmark106 def create_landmarker(method: str = '2d106det', **kwargs) -> BaseLandmarker: diff --git a/uniface/landmark/base.py b/uniface/landmark/base.py index ade7710..98e30f4 100644 --- a/uniface/landmark/base.py +++ b/uniface/landmark/base.py @@ -3,6 +3,7 @@ # GitHub: https://github.com/yakhyo from abc import ABC, abstractmethod + import numpy as np diff --git a/uniface/landmark/models.py b/uniface/landmark/models.py index 40c3cf8..a31c592 100644 --- a/uniface/landmark/models.py +++ b/uniface/landmark/models.py @@ -2,15 +2,17 @@ # Author: Yakhyokhuja Valikhujaev # GitHub: https://github.com/yakhyo -import cv2 -import numpy as np from typing import Tuple -from uniface.log import Logger +import cv2 +import numpy as np + from uniface.constants import LandmarkWeights -from uniface.model_store import verify_model_weights from uniface.face_utils import bbox_center_alignment, transform_points_2d +from uniface.log import Logger +from uniface.model_store import verify_model_weights from uniface.onnx_utils import create_onnx_session + from .base import BaseLandmarker __all__ = ['Landmark'] diff --git a/uniface/model_store.py b/uniface/model_store.py index 615c850..8d0a02a 100644 --- a/uniface/model_store.py +++ b/uniface/model_store.py @@ -2,14 +2,14 @@ # Author: Yakhyokhuja Valikhujaev # GitHub: https://github.com/yakhyo -import os import hashlib +import os + import requests from tqdm import tqdm -from uniface.log import Logger import uniface.constants as const - +from uniface.log import Logger __all__ = ['verify_model_weights'] diff --git a/uniface/recognition/__init__.py b/uniface/recognition/__init__.py index 9f13e32..6de7fcd 100644 --- a/uniface/recognition/__init__.py +++ b/uniface/recognition/__init__.py @@ -2,12 +2,12 @@ # Author: Yakhyokhuja Valikhujaev # GitHub: https://github.com/yakhyo -from typing import Dict -from .models import ArcFace, MobileFace, SphereFace -from .base import BaseRecognizer -from uniface.constants import ArcFaceWeights, MobileFaceWeights, SphereFaceWeights -def create_recognizer(method: str = 'arcface', **kwargs) -> BaseRecognizer: +from .base import BaseRecognizer +from .models import ArcFace, MobileFace, SphereFace + + +def create_recognizer(method: str = "arcface", **kwargs) -> BaseRecognizer: """ Factory function to create face recognizers. @@ -44,20 +44,21 @@ def create_recognizer(method: str = 'arcface', **kwargs) -> BaseRecognizer: """ method = method.lower() - if method == 'arcface': + if method == "arcface": return ArcFace(**kwargs) - elif method == 'mobileface': + elif method == "mobileface": return MobileFace(**kwargs) - elif method == 'sphereface': + elif method == "sphereface": return SphereFace(**kwargs) else: - available = ['arcface', 'mobileface', 'sphereface'] + available = ["arcface", "mobileface", "sphereface"] raise ValueError(f"Unsupported method: '{method}'. Available: {available}") + __all__ = [ "create_recognizer", "ArcFace", "MobileFace", "SphereFace", "BaseRecognizer", -] \ No newline at end of file +] diff --git a/uniface/recognition/base.py b/uniface/recognition/base.py index e38cbca..2829e30 100644 --- a/uniface/recognition/base.py +++ b/uniface/recognition/base.py @@ -3,13 +3,14 @@ # GitHub: https://github.com/yakhyo from abc import ABC, abstractmethod +from dataclasses import dataclass +from typing import List, Tuple, Union + import cv2 import numpy as np -from dataclasses import dataclass -from typing import Tuple, Union, List -from uniface.log import Logger from uniface.face_utils import face_alignment +from uniface.log import Logger from uniface.onnx_utils import create_onnx_session diff --git a/uniface/recognition/models.py b/uniface/recognition/models.py index e1e0e3c..58aed89 100644 --- a/uniface/recognition/models.py +++ b/uniface/recognition/models.py @@ -6,6 +6,7 @@ from typing import Optional from uniface.constants import ArcFaceWeights, MobileFaceWeights, SphereFaceWeights from uniface.model_store import verify_model_weights + from .base import BaseRecognizer, PreprocessConfig __all__ = ["ArcFace", "MobileFace", "SphereFace"] diff --git a/uniface/visualization.py b/uniface/visualization.py index d7a8068..2a5f192 100644 --- a/uniface/visualization.py +++ b/uniface/visualization.py @@ -2,9 +2,10 @@ # Author: Yakhyokhuja Valikhujaev # GitHub: https://github.com/yakhyo +from typing import List, Union + import cv2 import numpy as np -from typing import List, Union def draw_detections( @@ -12,7 +13,7 @@ def draw_detections( bboxes: Union[np.ndarray, List[List[float]]], scores: Union[np.ndarray, List[float]], landmarks: Union[np.ndarray, List[List[List[float]]]], - vis_threshold: float = 0.6 + vis_threshold: float = 0.6, ): """ Draws bounding boxes, scores, and landmarks from separate lists onto an image. @@ -42,8 +43,9 @@ def draw_detections( cv2.rectangle(image, tuple(bbox[:2]), tuple(bbox[2:]), (0, 0, 255), thickness) # Draw score - cv2.putText(image, f"{score:.2f}", (bbox[0], bbox[1] - 10), - cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), thickness) + cv2.putText( + image, f"{score:.2f}", (bbox[0], bbox[1] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), thickness + ) # Draw landmarks for j, point in enumerate(landmark_set):