uniface 0.1.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
uniface-0.1.4/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Yakhyokhuja Valikhujaev
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
uniface-0.1.4/PKG-INFO ADDED
@@ -0,0 +1,281 @@
1
+ Metadata-Version: 2.1
2
+ Name: uniface
3
+ Version: 0.1.4
4
+ Summary: UniFace: A Comprehensive Library for Face Detection, Recognition, Landmark Analysis, Age, and Gender Detection
5
+ Home-page: https://github.com/yakhyo/uniface
6
+ Author: Yakhyokhuja Valikhujaev
7
+ Author-email: yakhyo9696@gmail.com
8
+ License: MIT
9
+ Keywords: face detection,face recognition,facial landmark,facial attribute,onnx,opencv,retinaface
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.8
12
+ Classifier: Programming Language :: Python :: 3.9
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
17
+ Requires-Python: >=3.8
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Requires-Dist: numpy
21
+ Requires-Dist: opencv-python
22
+ Requires-Dist: onnx
23
+ Requires-Dist: onnxruntime
24
+ Requires-Dist: requests
25
+ Requires-Dist: torch
26
+ Requires-Dist: scikit-image
27
+ Provides-Extra: dev
28
+ Requires-Dist: pytest; extra == "dev"
29
+
30
+ # UniFace: All-in-One Face Analysis Library
31
+
32
+
33
+ [![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
34
+ ![Python](https://img.shields.io/badge/Python-3.8%2B-blue)
35
+ [![PyPI Version](https://img.shields.io/pypi/v/uniface.svg)](https://pypi.org/project/uniface/)
36
+ [![Build Status](https://github.com/yakhyo/uniface/actions/workflows/build.yml/badge.svg)](https://github.com/yakhyo/uniface/actions)
37
+ [![Downloads](https://pepy.tech/badge/uniface)](https://pepy.tech/project/uniface)
38
+ [![Code Style: PEP8](https://img.shields.io/badge/code%20style-PEP8-green.svg)](https://www.python.org/dev/peps/pep-0008/)
39
+ [![GitHub Release Downloads](https://img.shields.io/github/downloads/yakhyo/uniface/total.svg?label=Model%20Downloads)](https://github.com/yakhyo/uniface/releases)
40
+
41
+
42
+ **uniface** is a lightweight face detection library designed for high-performance face localization, landmark detection and face alignment. The library supports ONNX models and provides utilities for bounding box visualization and landmark plotting. To train RetinaFace model, see https://github.com/yakhyo/retinaface-pytorch.
43
+
44
+ ---
45
+
46
+ ## Features
47
+
48
+ - [ ] Age and gender detection (Planned).
49
+ - [ ] Face recognition (Planned).
50
+ - [x] Face Alignment (Added: 2024-11-21).
51
+ - [x] High-speed face detection using ONNX models (Added: 2024-11-20).
52
+ - [x] Accurate facial landmark localization (e.g., eyes, nose, and mouth) (Added: 2024-11-20).
53
+ - [x] Easy-to-use API for inference and visualization (Added: 2024-11-20).
54
+
55
+ ---
56
+
57
+ ## Installation
58
+
59
+ The easiest way to install **UniFace** is via [PyPI](https://pypi.org/project/uniface/). This will automatically install the library along with its prerequisites.
60
+
61
+ ```bash
62
+ pip install uniface
63
+ ```
64
+
65
+ To work with the latest version of **UniFace**, which may not yet be released on PyPI, you can install it directly from the repository:
66
+
67
+ ```bash
68
+ git clone https://github.com/yakhyo/uniface.git
69
+ cd uniface
70
+ pip install .
71
+ ```
72
+
73
+ ---
74
+
75
+ ## Quick Start
76
+
77
+ To get started with face detection using **UniFace**, check out the [example notebook](examples/face_detection.ipynb).
78
+ It demonstrates how to initialize the model, run inference, and visualize the results.
79
+
80
+ ---
81
+
82
+ ## Examples
83
+
84
+ Explore the following example notebooks to learn how to use **UniFace** effectively:
85
+
86
+ - [Face Detection](examples/face_detection.ipynb): Demonstrates how to perform face detection, draw bounding boxes, and landmarks on an image.
87
+ - [Face Alignment](examples/face_alignment.ipynb): Shows how to align faces using detected landmarks.
88
+ - [Age and Gender Detection](examples/age_gender.ipynb): Example for detecting age and gender from faces. (underdevelopment)
89
+
90
+ ### Initialize the Model
91
+
92
+ ```python
93
+ from uniface import RetinaFace
94
+
95
+ # Initialize the RetinaFace model
96
+ uniface_inference = RetinaFace(
97
+ model="retinaface_mnet_v2", # Model name
98
+ conf_thresh=0.5, # Confidence threshold
99
+ pre_nms_topk=5000, # Pre-NMS Top-K detections
100
+ nms_thresh=0.4, # NMS IoU threshold
101
+ post_nms_topk=750 # Post-NMS Top-K detections
102
+ )
103
+ ```
104
+
105
+ ### Run Inference
106
+
107
+ Inference on image:
108
+
109
+ ```python
110
+ import cv2
111
+ from uniface.visualization import draw_detections
112
+
113
+ # Load an image
114
+ image_path = "assets/test.jpg"
115
+ original_image = cv2.imread(image_path)
116
+
117
+ # Perform inference
118
+ boxes, landmarks = uniface_inference.detect(original_image)
119
+
120
+ # Visualize results
121
+ draw_detections(original_image, (boxes, landmarks), vis_threshold=0.6)
122
+
123
+ # Save the output image
124
+ output_path = "output.jpg"
125
+ cv2.imwrite(output_path, original_image)
126
+ print(f"Saved output image to {output_path}")
127
+ ```
128
+
129
+ Inference on video:
130
+
131
+ ```python
132
+ import cv2
133
+ from uniface.visualization import draw_detections
134
+
135
+ # Initialize the webcam
136
+ cap = cv2.VideoCapture(0)
137
+
138
+ if not cap.isOpened():
139
+ print("Error: Unable to access the webcam.")
140
+ exit()
141
+
142
+ while True:
143
+ # Capture a frame from the webcam
144
+ ret, frame = cap.read()
145
+ if not ret:
146
+ print("Error: Failed to read frame.")
147
+ break
148
+
149
+ # Perform inference
150
+ boxes, landmarks = uniface_inference.detect(frame)
151
+
152
+ # Draw detections on the frame
153
+ draw_detections(frame, (boxes, landmarks), vis_threshold=0.6)
154
+
155
+ # Display the output
156
+ cv2.imshow("Webcam Inference", frame)
157
+
158
+ # Exit if 'q' is pressed
159
+ if cv2.waitKey(1) & 0xFF == ord('q'):
160
+ break
161
+
162
+ # Release the webcam and close all OpenCV windows
163
+ cap.release()
164
+ cv2.destroyAllWindows()
165
+ ```
166
+
167
+ ---
168
+
169
+ ### Evaluation results of available models on WiderFace
170
+
171
+ | RetinaFace Models | Easy | Medium | Hard |
172
+ | ------------------ | ---------- | ---------- | ---------- |
173
+ | retinaface_mnet025 | 88.48% | 87.02% | 80.61% |
174
+ | retinaface_mnet050 | 89.42% | 87.97% | 82.40% |
175
+ | retinaface_mnet_v1 | 90.59% | 89.14% | 84.13% |
176
+ | retinaface_mnet_v2 | 91.70% | 91.03% | 86.60% |
177
+ | retinaface_r18 | 92.50% | 91.02% | 86.63% |
178
+ | retinaface_r34 | **94.16%** | **93.12%** | **88.90%** |
179
+
180
+ ## API Reference
181
+
182
+ ### `RetinaFace` Class
183
+
184
+ #### Initialization
185
+
186
+ ```python
187
+ RetinaFace(
188
+ model: str,
189
+ conf_thresh: float = 0.5,
190
+ pre_nms_topk: int = 5000,
191
+ nms_thresh: float = 0.4,
192
+ post_nms_topk: int = 750
193
+ )
194
+ ```
195
+
196
+ **Parameters**:
197
+
198
+ - `model` _(str)_: Name of the model to use. Supported models:
199
+ - `retinaface_mnet025`, `retinaface_mnet050`, `retinaface_mnet_v1`, `retinaface_mnet_v2`
200
+ - `retinaface_r18`, `retinaface_r34`
201
+ - `conf_thresh` _(float, default=0.5)_: Minimum confidence score for detections.
202
+ - `pre_nms_topk` _(int, default=5000)_: Max detections to keep before NMS.
203
+ - `nms_thresh` _(float, default=0.4)_: IoU threshold for Non-Maximum Suppression.
204
+ - `post_nms_topk` _(int, default=750)_: Max detections to keep after NMS.
205
+
206
+ ---
207
+
208
+ ### `detect` Method
209
+
210
+ ```python
211
+ detect(
212
+ image: np.ndarray,
213
+ max_num: int = 0,
214
+ metric: str = "default",
215
+ center_weight: float = 2.0
216
+ ) -> Tuple[np.ndarray, np.ndarray]
217
+ ```
218
+
219
+ **Description**:
220
+ Detects faces in the given image and returns bounding boxes and landmarks.
221
+
222
+ **Parameters**:
223
+
224
+ - `image` _(np.ndarray)_: Input image in BGR format.
225
+ - `max_num` _(int, default=0)_: Maximum number of faces to return. `0` means return all.
226
+ - `metric` _(str, default="default")_: Metric for prioritizing detections:
227
+ - `"default"`: Prioritize detections closer to the image center.
228
+ - `"max"`: Prioritize larger bounding box areas.
229
+ - `center_weight` _(float, default=2.0)_: Weight for prioritizing center-aligned faces.
230
+
231
+ **Returns**:
232
+
233
+ - `bounding_boxes` _(np.ndarray)_: Array of detections as `[x_min, y_min, x_max, y_max, confidence]`.
234
+ - `landmarks` _(np.ndarray)_: Array of landmarks as `[(x1, y1), ..., (x5, y5)]`.
235
+
236
+ ---
237
+
238
+ ### Visualization Utilities
239
+
240
+ #### `draw_detections`
241
+
242
+ ```python
243
+ draw_detections(
244
+ image: np.ndarray,
245
+ detections: Tuple[np.ndarray, np.ndarray],
246
+ vis_threshold: float
247
+ ) -> None
248
+ ```
249
+
250
+ **Description**:
251
+ Draws bounding boxes and landmarks on the given image.
252
+
253
+ **Parameters**:
254
+
255
+ - `image` _(np.ndarray)_: The input image in BGR format.
256
+ - `detections` _(Tuple[np.ndarray, np.ndarray])_: A tuple of bounding boxes and landmarks.
257
+ - `vis_threshold` _(float)_: Minimum confidence score for visualization.
258
+
259
+ ---
260
+
261
+ ## Contributing
262
+
263
+ We welcome contributions to enhance the library! Feel free to:
264
+
265
+ - Submit bug reports or feature requests.
266
+ - Fork the repository and create a pull request.
267
+
268
+ ---
269
+
270
+ ## License
271
+
272
+ This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
273
+
274
+ ---
275
+
276
+ ## Acknowledgments
277
+
278
+ - Based on the RetinaFace model for face detection ([https://github.com/yakhyo/retinaface-pytorch](https://github.com/yakhyo/retinaface-pytorch)).
279
+ - Inspired by InsightFace and other face detection projects.
280
+
281
+ ---
@@ -0,0 +1,252 @@
1
+ # UniFace: All-in-One Face Analysis Library
2
+
3
+
4
+ [![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
5
+ ![Python](https://img.shields.io/badge/Python-3.8%2B-blue)
6
+ [![PyPI Version](https://img.shields.io/pypi/v/uniface.svg)](https://pypi.org/project/uniface/)
7
+ [![Build Status](https://github.com/yakhyo/uniface/actions/workflows/build.yml/badge.svg)](https://github.com/yakhyo/uniface/actions)
8
+ [![Downloads](https://pepy.tech/badge/uniface)](https://pepy.tech/project/uniface)
9
+ [![Code Style: PEP8](https://img.shields.io/badge/code%20style-PEP8-green.svg)](https://www.python.org/dev/peps/pep-0008/)
10
+ [![GitHub Release Downloads](https://img.shields.io/github/downloads/yakhyo/uniface/total.svg?label=Model%20Downloads)](https://github.com/yakhyo/uniface/releases)
11
+
12
+
13
+ **uniface** is a lightweight face detection library designed for high-performance face localization, landmark detection and face alignment. The library supports ONNX models and provides utilities for bounding box visualization and landmark plotting. To train RetinaFace model, see https://github.com/yakhyo/retinaface-pytorch.
14
+
15
+ ---
16
+
17
+ ## Features
18
+
19
+ - [ ] Age and gender detection (Planned).
20
+ - [ ] Face recognition (Planned).
21
+ - [x] Face Alignment (Added: 2024-11-21).
22
+ - [x] High-speed face detection using ONNX models (Added: 2024-11-20).
23
+ - [x] Accurate facial landmark localization (e.g., eyes, nose, and mouth) (Added: 2024-11-20).
24
+ - [x] Easy-to-use API for inference and visualization (Added: 2024-11-20).
25
+
26
+ ---
27
+
28
+ ## Installation
29
+
30
+ The easiest way to install **UniFace** is via [PyPI](https://pypi.org/project/uniface/). This will automatically install the library along with its prerequisites.
31
+
32
+ ```bash
33
+ pip install uniface
34
+ ```
35
+
36
+ To work with the latest version of **UniFace**, which may not yet be released on PyPI, you can install it directly from the repository:
37
+
38
+ ```bash
39
+ git clone https://github.com/yakhyo/uniface.git
40
+ cd uniface
41
+ pip install .
42
+ ```
43
+
44
+ ---
45
+
46
+ ## Quick Start
47
+
48
+ To get started with face detection using **UniFace**, check out the [example notebook](examples/face_detection.ipynb).
49
+ It demonstrates how to initialize the model, run inference, and visualize the results.
50
+
51
+ ---
52
+
53
+ ## Examples
54
+
55
+ Explore the following example notebooks to learn how to use **UniFace** effectively:
56
+
57
+ - [Face Detection](examples/face_detection.ipynb): Demonstrates how to perform face detection, draw bounding boxes, and landmarks on an image.
58
+ - [Face Alignment](examples/face_alignment.ipynb): Shows how to align faces using detected landmarks.
59
+ - [Age and Gender Detection](examples/age_gender.ipynb): Example for detecting age and gender from faces. (underdevelopment)
60
+
61
+ ### Initialize the Model
62
+
63
+ ```python
64
+ from uniface import RetinaFace
65
+
66
+ # Initialize the RetinaFace model
67
+ uniface_inference = RetinaFace(
68
+ model="retinaface_mnet_v2", # Model name
69
+ conf_thresh=0.5, # Confidence threshold
70
+ pre_nms_topk=5000, # Pre-NMS Top-K detections
71
+ nms_thresh=0.4, # NMS IoU threshold
72
+ post_nms_topk=750 # Post-NMS Top-K detections
73
+ )
74
+ ```
75
+
76
+ ### Run Inference
77
+
78
+ Inference on image:
79
+
80
+ ```python
81
+ import cv2
82
+ from uniface.visualization import draw_detections
83
+
84
+ # Load an image
85
+ image_path = "assets/test.jpg"
86
+ original_image = cv2.imread(image_path)
87
+
88
+ # Perform inference
89
+ boxes, landmarks = uniface_inference.detect(original_image)
90
+
91
+ # Visualize results
92
+ draw_detections(original_image, (boxes, landmarks), vis_threshold=0.6)
93
+
94
+ # Save the output image
95
+ output_path = "output.jpg"
96
+ cv2.imwrite(output_path, original_image)
97
+ print(f"Saved output image to {output_path}")
98
+ ```
99
+
100
+ Inference on video:
101
+
102
+ ```python
103
+ import cv2
104
+ from uniface.visualization import draw_detections
105
+
106
+ # Initialize the webcam
107
+ cap = cv2.VideoCapture(0)
108
+
109
+ if not cap.isOpened():
110
+ print("Error: Unable to access the webcam.")
111
+ exit()
112
+
113
+ while True:
114
+ # Capture a frame from the webcam
115
+ ret, frame = cap.read()
116
+ if not ret:
117
+ print("Error: Failed to read frame.")
118
+ break
119
+
120
+ # Perform inference
121
+ boxes, landmarks = uniface_inference.detect(frame)
122
+
123
+ # Draw detections on the frame
124
+ draw_detections(frame, (boxes, landmarks), vis_threshold=0.6)
125
+
126
+ # Display the output
127
+ cv2.imshow("Webcam Inference", frame)
128
+
129
+ # Exit if 'q' is pressed
130
+ if cv2.waitKey(1) & 0xFF == ord('q'):
131
+ break
132
+
133
+ # Release the webcam and close all OpenCV windows
134
+ cap.release()
135
+ cv2.destroyAllWindows()
136
+ ```
137
+
138
+ ---
139
+
140
+ ### Evaluation results of available models on WiderFace
141
+
142
+ | RetinaFace Models | Easy | Medium | Hard |
143
+ | ------------------ | ---------- | ---------- | ---------- |
144
+ | retinaface_mnet025 | 88.48% | 87.02% | 80.61% |
145
+ | retinaface_mnet050 | 89.42% | 87.97% | 82.40% |
146
+ | retinaface_mnet_v1 | 90.59% | 89.14% | 84.13% |
147
+ | retinaface_mnet_v2 | 91.70% | 91.03% | 86.60% |
148
+ | retinaface_r18 | 92.50% | 91.02% | 86.63% |
149
+ | retinaface_r34 | **94.16%** | **93.12%** | **88.90%** |
150
+
151
+ ## API Reference
152
+
153
+ ### `RetinaFace` Class
154
+
155
+ #### Initialization
156
+
157
+ ```python
158
+ RetinaFace(
159
+ model: str,
160
+ conf_thresh: float = 0.5,
161
+ pre_nms_topk: int = 5000,
162
+ nms_thresh: float = 0.4,
163
+ post_nms_topk: int = 750
164
+ )
165
+ ```
166
+
167
+ **Parameters**:
168
+
169
+ - `model` _(str)_: Name of the model to use. Supported models:
170
+ - `retinaface_mnet025`, `retinaface_mnet050`, `retinaface_mnet_v1`, `retinaface_mnet_v2`
171
+ - `retinaface_r18`, `retinaface_r34`
172
+ - `conf_thresh` _(float, default=0.5)_: Minimum confidence score for detections.
173
+ - `pre_nms_topk` _(int, default=5000)_: Max detections to keep before NMS.
174
+ - `nms_thresh` _(float, default=0.4)_: IoU threshold for Non-Maximum Suppression.
175
+ - `post_nms_topk` _(int, default=750)_: Max detections to keep after NMS.
176
+
177
+ ---
178
+
179
+ ### `detect` Method
180
+
181
+ ```python
182
+ detect(
183
+ image: np.ndarray,
184
+ max_num: int = 0,
185
+ metric: str = "default",
186
+ center_weight: float = 2.0
187
+ ) -> Tuple[np.ndarray, np.ndarray]
188
+ ```
189
+
190
+ **Description**:
191
+ Detects faces in the given image and returns bounding boxes and landmarks.
192
+
193
+ **Parameters**:
194
+
195
+ - `image` _(np.ndarray)_: Input image in BGR format.
196
+ - `max_num` _(int, default=0)_: Maximum number of faces to return. `0` means return all.
197
+ - `metric` _(str, default="default")_: Metric for prioritizing detections:
198
+ - `"default"`: Prioritize detections closer to the image center.
199
+ - `"max"`: Prioritize larger bounding box areas.
200
+ - `center_weight` _(float, default=2.0)_: Weight for prioritizing center-aligned faces.
201
+
202
+ **Returns**:
203
+
204
+ - `bounding_boxes` _(np.ndarray)_: Array of detections as `[x_min, y_min, x_max, y_max, confidence]`.
205
+ - `landmarks` _(np.ndarray)_: Array of landmarks as `[(x1, y1), ..., (x5, y5)]`.
206
+
207
+ ---
208
+
209
+ ### Visualization Utilities
210
+
211
+ #### `draw_detections`
212
+
213
+ ```python
214
+ draw_detections(
215
+ image: np.ndarray,
216
+ detections: Tuple[np.ndarray, np.ndarray],
217
+ vis_threshold: float
218
+ ) -> None
219
+ ```
220
+
221
+ **Description**:
222
+ Draws bounding boxes and landmarks on the given image.
223
+
224
+ **Parameters**:
225
+
226
+ - `image` _(np.ndarray)_: The input image in BGR format.
227
+ - `detections` _(Tuple[np.ndarray, np.ndarray])_: A tuple of bounding boxes and landmarks.
228
+ - `vis_threshold` _(float)_: Minimum confidence score for visualization.
229
+
230
+ ---
231
+
232
+ ## Contributing
233
+
234
+ We welcome contributions to enhance the library! Feel free to:
235
+
236
+ - Submit bug reports or feature requests.
237
+ - Fork the repository and create a pull request.
238
+
239
+ ---
240
+
241
+ ## License
242
+
243
+ This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
244
+
245
+ ---
246
+
247
+ ## Acknowledgments
248
+
249
+ - Based on the RetinaFace model for face detection ([https://github.com/yakhyo/retinaface-pytorch](https://github.com/yakhyo/retinaface-pytorch)).
250
+ - Inspired by InsightFace and other face detection projects.
251
+
252
+ ---
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
uniface-0.1.4/setup.py ADDED
@@ -0,0 +1,44 @@
1
+ import os
2
+ from setuptools import setup, find_packages
3
+
4
+ # Read the README file for the long description
5
+ long_description = ""
6
+ if os.path.exists("README.md"):
7
+ with open("README.md", "r", encoding="utf-8") as f:
8
+ long_description = f.read()
9
+
10
+ setup(
11
+ name="uniface",
12
+ version="0.1.4",
13
+ packages=find_packages(),
14
+ install_requires=[
15
+ "numpy",
16
+ "opencv-python",
17
+ "onnx",
18
+ "onnxruntime",
19
+ "requests",
20
+ "torch",
21
+ "scikit-image"
22
+ ],
23
+ extras_require={
24
+ "dev": ["pytest"],
25
+ },
26
+ description="UniFace: A Comprehensive Library for Face Detection, Recognition, Landmark Analysis, Age, and Gender Detection",
27
+ long_description=long_description,
28
+ long_description_content_type="text/markdown",
29
+ author="Yakhyokhuja Valikhujaev",
30
+ author_email="yakhyo9696@gmail.com",
31
+ url="https://github.com/yakhyo/uniface",
32
+ license="MIT",
33
+ classifiers=[
34
+ "Programming Language :: Python :: 3",
35
+ "Programming Language :: Python :: 3.8",
36
+ "Programming Language :: Python :: 3.9",
37
+ "Programming Language :: Python :: 3.10",
38
+ "License :: OSI Approved :: MIT License",
39
+ "Operating System :: OS Independent",
40
+ "Topic :: Software Development :: Libraries :: Python Modules",
41
+ ],
42
+ keywords="face detection, face recognition, facial landmark, facial attribute, onnx, opencv, retinaface",
43
+ python_requires=">=3.8",
44
+ )
@@ -0,0 +1,78 @@
1
+ import pytest
2
+ import numpy as np
3
+ from uniface import RetinaFace
4
+
5
+
6
+ @pytest.fixture
7
+ def retinaface_model():
8
+ """
9
+ Fixture to initialize the RetinaFace model for testing.
10
+ """
11
+ return RetinaFace(
12
+ model="retinaface_mnet_v2",
13
+ conf_thresh=0.5,
14
+ pre_nms_topk=5000,
15
+ nms_thresh=0.4,
16
+ post_nms_topk=750,
17
+ )
18
+
19
+
20
+ def test_model_initialization(retinaface_model):
21
+ """
22
+ Test that the RetinaFace model initializes correctly.
23
+ """
24
+ assert retinaface_model is not None, "Model initialization failed."
25
+
26
+
27
+ def test_inference_on_640x640_image(retinaface_model):
28
+ """
29
+ Test inference on a 640x640 BGR image.
30
+ """
31
+ # Generate a mock 640x640 BGR image
32
+ mock_image = np.random.randint(0, 255, (640, 640, 3), dtype=np.uint8)
33
+
34
+ # Run inference
35
+ detections, landmarks = retinaface_model.detect(mock_image)
36
+
37
+ # Check output types
38
+ assert isinstance(detections, np.ndarray), "Detections should be a numpy array."
39
+ assert isinstance(landmarks, np.ndarray), "Landmarks should be a numpy array."
40
+
41
+ # Check that detections have the expected shape
42
+ if detections.size > 0: # If faces are detected
43
+ assert detections.shape[1] == 5, "Each detection should have 5 values (x1, y1, x2, y2, score)."
44
+
45
+ # Check landmarks shape
46
+ if landmarks.size > 0:
47
+ assert landmarks.shape[1:] == (5, 2), "Landmarks should have shape (N, 5, 2)."
48
+
49
+
50
+ def test_confidence_threshold(retinaface_model):
51
+ """
52
+ Test that detections respect the confidence threshold.
53
+ """
54
+ # Generate a mock 640x640 BGR image
55
+ mock_image = np.random.randint(0, 255, (640, 640, 3), dtype=np.uint8)
56
+
57
+ # Run inference
58
+ detections, _ = retinaface_model.detect(mock_image)
59
+
60
+ # Ensure all detections have confidence scores above the threshold
61
+ if detections.size > 0: # If faces are detected
62
+ confidence_scores = detections[:, 4]
63
+ assert (confidence_scores >= 0.5).all(), "Some detections have confidence below the threshold."
64
+
65
+
66
+ def test_no_faces_detected(retinaface_model):
67
+ """
68
+ Test inference on an image without detectable faces.
69
+ """
70
+ # Generate an empty (black) 640x640 image
71
+ empty_image = np.zeros((640, 640, 3), dtype=np.uint8)
72
+
73
+ # Run inference
74
+ detections, landmarks = retinaface_model.detect(empty_image)
75
+
76
+ # Ensure no detections or landmarks are found
77
+ assert detections.size == 0, "Detections should be empty for a blank image."
78
+ assert landmarks.size == 0, "Landmarks should be empty for a blank image."