base.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. # Copyright 2025 Yakhyokhuja Valikhujaev
  2. # Author: Yakhyokhuja Valikhujaev
  3. # GitHub: https://github.com/yakhyo
  4. from abc import ABC, abstractmethod
  5. from typing import Any, Dict, List
  6. import numpy as np
  7. class BaseDetector(ABC):
  8. """
  9. Abstract base class for all face detectors.
  10. This class defines the interface that all face detectors must implement,
  11. ensuring consistency across different detection methods.
  12. """
  13. def __init__(self, **kwargs):
  14. """Initialize the detector with configuration parameters."""
  15. self.config = kwargs
  16. @abstractmethod
  17. def detect(self, image: np.ndarray, **kwargs) -> List[Dict[str, Any]]:
  18. """
  19. Detect faces in an image.
  20. Args:
  21. image (np.ndarray): Input image as numpy array with shape (H, W, C)
  22. **kwargs: Additional detection parameters
  23. Returns:
  24. List[Dict[str, Any]]: List of detected faces, where each dictionary contains:
  25. - 'bbox' (np.ndarray): Bounding box coordinates with shape (4,) as [x1, y1, x2, y2]
  26. - 'confidence' (float): Detection confidence score (0.0 to 1.0)
  27. - 'landmarks' (np.ndarray): Facial landmarks with shape (5, 2) for 5-point landmarks
  28. or (68, 2) for 68-point landmarks. Empty array if not supported.
  29. Example:
  30. >>> faces = detector.detect(image)
  31. >>> for face in faces:
  32. ... bbox = face['bbox'] # np.ndarray with shape (4,)
  33. ... confidence = face['confidence'] # float
  34. ... landmarks = face['landmarks'] # np.ndarray with shape (5, 2)
  35. """
  36. pass
  37. @abstractmethod
  38. def preprocess(self, image: np.ndarray) -> np.ndarray:
  39. """
  40. Preprocess input image for detection.
  41. Args:
  42. image (np.ndarray): Input image
  43. Returns:
  44. np.ndarray: Preprocessed image tensor
  45. """
  46. pass
  47. @abstractmethod
  48. def postprocess(self, outputs, **kwargs) -> Any:
  49. """
  50. Postprocess model outputs to get final detections.
  51. Args:
  52. outputs: Raw model outputs
  53. **kwargs: Additional postprocessing parameters
  54. Returns:
  55. Any: Processed outputs (implementation-specific format, typically tuple of arrays)
  56. """
  57. pass
  58. def __str__(self) -> str:
  59. """String representation of the detector."""
  60. return f'{self.__class__.__name__}({self.config})'
  61. def __repr__(self) -> str:
  62. """Detailed string representation."""
  63. return self.__str__()
  64. @property
  65. def supports_landmarks(self) -> bool:
  66. """
  67. Whether this detector supports landmark detection.
  68. Returns:
  69. bool: True if landmarks are supported, False otherwise
  70. """
  71. return hasattr(self, '_supports_landmarks') and self._supports_landmarks
  72. def get_info(self) -> Dict[str, Any]:
  73. """
  74. Get detector information and configuration.
  75. Returns:
  76. Dict[str, Any]: Detector information
  77. """
  78. return {
  79. 'name': self.__class__.__name__,
  80. 'supports_landmarks': self._supports_landmarks,
  81. 'config': self.config,
  82. }