ImagePRO-Python 1.3.0__tar.gz → 1.3.1__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.
- {imagepro_python-1.3.0/src/ImagePRO_Python.egg-info → imagepro_python-1.3.1}/PKG-INFO +4 -1
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/pyproject.toml +1 -1
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/readme.md +3 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/src/ImagePRO/__init__.py +1 -1
- imagepro_python-1.3.1/src/ImagePRO/human_analysis/body_analysis/__init__.py +11 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/src/ImagePRO/human_analysis/body_analysis/body_pose_estimation.py +23 -3
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/src/ImagePRO/human_analysis/body_analysis/hand_tracking.py +23 -3
- imagepro_python-1.3.1/src/ImagePRO/human_analysis/face_analysis/__init__.py +20 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/src/ImagePRO/human_analysis/face_analysis/eye_status_analysis.py +22 -4
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/src/ImagePRO/human_analysis/face_analysis/face_comparison.py +13 -1
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/src/ImagePRO/human_analysis/face_analysis/face_detection.py +4 -1
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/src/ImagePRO/human_analysis/face_analysis/face_mesh_analysis.py +25 -6
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/src/ImagePRO/human_analysis/face_analysis/head_pose_estimation.py +13 -3
- imagepro_python-1.3.1/src/ImagePRO/object_analysis/__init__.py +9 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/src/ImagePRO/object_analysis/object_detection.py +19 -8
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/src/ImagePRO/pre_processing/__init__.py +4 -5
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/src/ImagePRO/pre_processing/dataset_generator.py +8 -1
- {imagepro_python-1.3.0 → imagepro_python-1.3.1/src/ImagePRO_Python.egg-info}/PKG-INFO +4 -1
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/tests/test_face_mesh_analysis.py +5 -4
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/tests/test_object_detection.py +1 -3
- imagepro_python-1.3.0/src/ImagePRO/human_analysis/body_analysis/__init__.py +0 -17
- imagepro_python-1.3.0/src/ImagePRO/human_analysis/face_analysis/__init__.py +0 -39
- imagepro_python-1.3.0/src/ImagePRO/object_analysis/__init__.py +0 -9
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/LICENSE +0 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/setup.cfg +0 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/src/ImagePRO/human_analysis/__init__.py +0 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/src/ImagePRO/pre_processing/blur.py +0 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/src/ImagePRO/pre_processing/contrast.py +0 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/src/ImagePRO/pre_processing/crop.py +0 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/src/ImagePRO/pre_processing/grayscale.py +0 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/src/ImagePRO/pre_processing/histogram.py +0 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/src/ImagePRO/pre_processing/resize.py +0 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/src/ImagePRO/pre_processing/rotate.py +0 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/src/ImagePRO/pre_processing/sharpen.py +0 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/src/ImagePRO/utils/__init__.py +0 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/src/ImagePRO/utils/image.py +0 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/src/ImagePRO/utils/result.py +0 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/src/ImagePRO_Python.egg-info/SOURCES.txt +0 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/src/ImagePRO_Python.egg-info/dependency_links.txt +0 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/src/ImagePRO_Python.egg-info/requires.txt +0 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/src/ImagePRO_Python.egg-info/top_level.txt +0 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/tests/test_blur.py +0 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/tests/test_body_pose_estimation.py +0 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/tests/test_contrast.py +0 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/tests/test_crop.py +0 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/tests/test_dataset_generator.py +0 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/tests/test_eye_status_analysis.py +0 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/tests/test_face_comparison.py +0 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/tests/test_face_detection.py +0 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/tests/test_grayscale.py +0 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/tests/test_hand_tracking.py +0 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/tests/test_head_pose_estimation.py +0 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/tests/test_histogram.py +0 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/tests/test_image.py +0 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/tests/test_integration.py +0 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/tests/test_resize.py +0 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/tests/test_result.py +0 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/tests/test_rotate.py +0 -0
- {imagepro_python-1.3.0 → imagepro_python-1.3.1}/tests/test_sharpen.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ImagePRO-Python
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.1
|
|
4
4
|
Summary: Professional & modular image processing library with OpenCV, MediaPipe, and YOLO integration.
|
|
5
5
|
Author-email: Parsa Safaie <parsasafaie.2568@proton.me>
|
|
6
6
|
License: MIT
|
|
@@ -90,6 +90,8 @@ pip install "ImagePRO-Python[full]" # Everything
|
|
|
90
90
|
pip install "ImagePRO-Python[dev]" # Test tooling (pytest)
|
|
91
91
|
```
|
|
92
92
|
|
|
93
|
+
> **Note**: The base install is lightweight — AI backends (MediaPipe, Ultralytics, InsightFace) are optional and imported lazily, only when you call a function that actually needs them. `import ImagePRO` never loads these dependencies. If a backend is missing, the function you call raises an `ImportError` telling you exactly which extra to install.
|
|
94
|
+
|
|
93
95
|
### From Source
|
|
94
96
|
```bash
|
|
95
97
|
git clone https://github.com/parsasafaie/ImagePRO.git
|
|
@@ -176,6 +178,7 @@ ImagePRO is built with a modular architecture designed for extensibility and mai
|
|
|
176
178
|
- **Clean Separation of Concerns**: Each module handles a specific domain
|
|
177
179
|
- **Consistent API Patterns**: All functions follow the same input/output conventions
|
|
178
180
|
- **Shared Utilities**: Common `Image` and `Result` classes for unified I/O
|
|
181
|
+
- **Lazy Optional Imports**: Heavy AI dependencies (MediaPipe, Ultralytics, InsightFace) are only imported inside the functions that use them, keeping `import ImagePRO` fast and independent of installed extras
|
|
179
182
|
- **Professional Error Handling**: Comprehensive validation with clear error messages
|
|
180
183
|
- **Type Safety**: Full type hints throughout the codebase
|
|
181
184
|
- **Documentation**: Google-style docstrings for all functions
|
|
@@ -7,7 +7,7 @@ where = ["src"]
|
|
|
7
7
|
|
|
8
8
|
[project]
|
|
9
9
|
name = "ImagePRO-Python"
|
|
10
|
-
version = "1.3.
|
|
10
|
+
version = "1.3.1"
|
|
11
11
|
description = "Professional & modular image processing library with OpenCV, MediaPipe, and YOLO integration."
|
|
12
12
|
readme = "readme.md"
|
|
13
13
|
requires-python = ">=3.9,<3.13"
|
|
@@ -41,6 +41,8 @@ pip install "ImagePRO-Python[full]" # Everything
|
|
|
41
41
|
pip install "ImagePRO-Python[dev]" # Test tooling (pytest)
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
+
> **Note**: The base install is lightweight — AI backends (MediaPipe, Ultralytics, InsightFace) are optional and imported lazily, only when you call a function that actually needs them. `import ImagePRO` never loads these dependencies. If a backend is missing, the function you call raises an `ImportError` telling you exactly which extra to install.
|
|
45
|
+
|
|
44
46
|
### From Source
|
|
45
47
|
```bash
|
|
46
48
|
git clone https://github.com/parsasafaie/ImagePRO.git
|
|
@@ -127,6 +129,7 @@ ImagePRO is built with a modular architecture designed for extensibility and mai
|
|
|
127
129
|
- **Clean Separation of Concerns**: Each module handles a specific domain
|
|
128
130
|
- **Consistent API Patterns**: All functions follow the same input/output conventions
|
|
129
131
|
- **Shared Utilities**: Common `Image` and `Result` classes for unified I/O
|
|
132
|
+
- **Lazy Optional Imports**: Heavy AI dependencies (MediaPipe, Ultralytics, InsightFace) are only imported inside the functions that use them, keeping `import ImagePRO` fast and independent of installed extras
|
|
130
133
|
- **Professional Error Handling**: Comprehensive validation with clear error messages
|
|
131
134
|
- **Type Safety**: Full type hints throughout the codebase
|
|
132
135
|
- **Documentation**: Google-style docstrings for all functions
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Body Analysis Module
|
|
2
|
+
# Provides body pose estimation and hand tracking capabilities
|
|
3
|
+
#
|
|
4
|
+
# The mediapipe dependency is optional and imported lazily inside the
|
|
5
|
+
# functions that need it, so both submodules are safe to import without
|
|
6
|
+
# any AI extras installed.
|
|
7
|
+
|
|
8
|
+
from . import body_pose_estimation
|
|
9
|
+
from . import hand_tracking
|
|
10
|
+
|
|
11
|
+
__all__ = ["body_pose_estimation", "hand_tracking"]
|
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import sys
|
|
4
4
|
from pathlib import Path
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
5
6
|
|
|
6
7
|
# Add src directory to path for absolute imports
|
|
7
8
|
_file_path = Path(__file__).resolve()
|
|
@@ -13,10 +14,11 @@ from ImagePRO.utils.image import Image
|
|
|
13
14
|
from ImagePRO.utils.result import Result
|
|
14
15
|
|
|
15
16
|
import cv2
|
|
16
|
-
|
|
17
|
+
|
|
18
|
+
if TYPE_CHECKING: # mediapipe is imported lazily inside the functions
|
|
19
|
+
import mediapipe as mp
|
|
17
20
|
|
|
18
21
|
# Constants
|
|
19
|
-
mp_pose = mp.solutions.pose
|
|
20
22
|
TOTAL_LANDMARKS = 33
|
|
21
23
|
DEFAULT_CONFIDENCE = 0.7
|
|
22
24
|
LANDMARK_RADIUS = 3
|
|
@@ -69,6 +71,16 @@ def detect_body_pose(
|
|
|
69
71
|
):
|
|
70
72
|
raise TypeError("'landmarks_idx' must be a list of integers")
|
|
71
73
|
|
|
74
|
+
try:
|
|
75
|
+
import mediapipe as mp
|
|
76
|
+
except ImportError as err:
|
|
77
|
+
raise ImportError(
|
|
78
|
+
"The optional 'mediapipe' dependency is required for body pose "
|
|
79
|
+
'detection. Install it with: pip install "ImagePRO-Python[mediapipe]"'
|
|
80
|
+
) from err
|
|
81
|
+
|
|
82
|
+
mp_pose = mp.solutions.pose
|
|
83
|
+
|
|
72
84
|
# Initialize detector if needed
|
|
73
85
|
if pose_obj is None:
|
|
74
86
|
pose_obj = mp_pose.Pose(
|
|
@@ -133,13 +145,21 @@ def detect_body_pose_live() -> None:
|
|
|
133
145
|
Raises:
|
|
134
146
|
RuntimeError: If camera cannot be accessed
|
|
135
147
|
"""
|
|
148
|
+
try:
|
|
149
|
+
import mediapipe as mp
|
|
150
|
+
except ImportError as err:
|
|
151
|
+
raise ImportError(
|
|
152
|
+
"The optional 'mediapipe' dependency is required for body pose "
|
|
153
|
+
'detection. Install it with: pip install "ImagePRO-Python[mediapipe]"'
|
|
154
|
+
) from err
|
|
155
|
+
|
|
136
156
|
# Initialize camera
|
|
137
157
|
cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)
|
|
138
158
|
if not cap.isOpened():
|
|
139
159
|
raise RuntimeError("Cannot access webcam")
|
|
140
160
|
|
|
141
161
|
# Initialize pose detector in tracking mode
|
|
142
|
-
pose_obj =
|
|
162
|
+
pose_obj = mp.solutions.pose.Pose(
|
|
143
163
|
min_detection_confidence=DEFAULT_CONFIDENCE,
|
|
144
164
|
static_image_mode=False
|
|
145
165
|
)
|
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import sys
|
|
4
4
|
from pathlib import Path
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
5
6
|
|
|
6
7
|
# Add src directory to path for absolute imports
|
|
7
8
|
_file_path = Path(__file__).resolve()
|
|
@@ -13,10 +14,11 @@ from ImagePRO.utils.image import Image
|
|
|
13
14
|
from ImagePRO.utils.result import Result
|
|
14
15
|
|
|
15
16
|
import cv2
|
|
16
|
-
|
|
17
|
+
|
|
18
|
+
if TYPE_CHECKING: # mediapipe is imported lazily inside the functions
|
|
19
|
+
import mediapipe as mp
|
|
17
20
|
|
|
18
21
|
# Constants
|
|
19
|
-
mp_hands = mp.solutions.hands
|
|
20
22
|
DEFAULT_MAX_HANDS = 2
|
|
21
23
|
DEFAULT_MIN_CONFIDENCE = 0.7
|
|
22
24
|
TOTAL_HAND_LANDMARKS = 21
|
|
@@ -79,6 +81,16 @@ def detect_hands(
|
|
|
79
81
|
):
|
|
80
82
|
raise TypeError("'landmarks_idx' must be a list of integers")
|
|
81
83
|
|
|
84
|
+
try:
|
|
85
|
+
import mediapipe as mp
|
|
86
|
+
except ImportError as err:
|
|
87
|
+
raise ImportError(
|
|
88
|
+
"The optional 'mediapipe' dependency is required for hand "
|
|
89
|
+
'tracking. Install it with: pip install "ImagePRO-Python[mediapipe]"'
|
|
90
|
+
) from err
|
|
91
|
+
|
|
92
|
+
mp_hands = mp.solutions.hands
|
|
93
|
+
|
|
82
94
|
# Initialize detector if needed
|
|
83
95
|
if hands_obj is None:
|
|
84
96
|
hands_obj = mp_hands.Hands(
|
|
@@ -168,13 +180,21 @@ def detect_hands_live(
|
|
|
168
180
|
if not isinstance(min_confidence, (int, float)) or not (0.0 <= min_confidence <= 1.0):
|
|
169
181
|
raise ValueError("'min_confidence' must be between 0.0 and 1.0")
|
|
170
182
|
|
|
183
|
+
try:
|
|
184
|
+
import mediapipe as mp
|
|
185
|
+
except ImportError as err:
|
|
186
|
+
raise ImportError(
|
|
187
|
+
"The optional 'mediapipe' dependency is required for hand "
|
|
188
|
+
'tracking. Install it with: pip install "ImagePRO-Python[mediapipe]"'
|
|
189
|
+
) from err
|
|
190
|
+
|
|
171
191
|
# Initialize camera
|
|
172
192
|
cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)
|
|
173
193
|
if not cap.isOpened():
|
|
174
194
|
raise RuntimeError("Cannot access webcam")
|
|
175
195
|
|
|
176
196
|
# Initialize hand detector in tracking mode
|
|
177
|
-
hands_obj =
|
|
197
|
+
hands_obj = mp.solutions.hands.Hands(
|
|
178
198
|
min_detection_confidence=min_confidence,
|
|
179
199
|
max_num_hands=max_hands,
|
|
180
200
|
static_image_mode=False
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Face Analysis Module
|
|
2
|
+
# Provides facial landmark detection, pose estimation, and eye status analysis
|
|
3
|
+
#
|
|
4
|
+
# The mediapipe and insightface dependencies are optional and imported
|
|
5
|
+
# lazily inside the functions that need them, so every submodule is safe
|
|
6
|
+
# to import regardless of which extras are installed.
|
|
7
|
+
|
|
8
|
+
from . import eye_status_analysis
|
|
9
|
+
from . import face_comparison
|
|
10
|
+
from . import face_detection
|
|
11
|
+
from . import face_mesh_analysis
|
|
12
|
+
from . import head_pose_estimation
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
"eye_status_analysis",
|
|
16
|
+
"face_comparison",
|
|
17
|
+
"face_detection",
|
|
18
|
+
"face_mesh_analysis",
|
|
19
|
+
"head_pose_estimation"
|
|
20
|
+
]
|
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import sys
|
|
4
4
|
from pathlib import Path
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
5
6
|
|
|
6
7
|
# Add src directory to path for absolute imports
|
|
7
8
|
_file_path = Path(__file__).resolve()
|
|
@@ -14,10 +15,11 @@ from ImagePRO.utils.image import Image
|
|
|
14
15
|
from ImagePRO.utils.result import Result
|
|
15
16
|
|
|
16
17
|
import cv2
|
|
17
|
-
|
|
18
|
+
|
|
19
|
+
if TYPE_CHECKING: # mediapipe is imported lazily inside the functions
|
|
20
|
+
import mediapipe as mp
|
|
18
21
|
|
|
19
22
|
# Constants
|
|
20
|
-
mp_face_mesh = mp.solutions.face_mesh
|
|
21
23
|
DEFAULT_MIN_CONFIDENCE = 0.7
|
|
22
24
|
DEFAULT_THRESHOLD = 0.2
|
|
23
25
|
RIGHT_EYE_INDICES = [386, 374, 263, 362] # MediaPipe right eye landmarks
|
|
@@ -65,12 +67,20 @@ def analyze_eye_status(
|
|
|
65
67
|
if not 0 <= min_confidence <= 1:
|
|
66
68
|
raise ValueError("'min_confidence' must be between 0 and 1")
|
|
67
69
|
|
|
70
|
+
try:
|
|
71
|
+
import mediapipe as mp
|
|
72
|
+
except ImportError as err:
|
|
73
|
+
raise ImportError(
|
|
74
|
+
"The optional 'mediapipe' dependency is required for eye status "
|
|
75
|
+
'analysis. Install it with: pip install "ImagePRO-Python[mediapipe]"'
|
|
76
|
+
) from err
|
|
77
|
+
|
|
68
78
|
# Get image dimensions
|
|
69
79
|
h, w = image.shape[:2]
|
|
70
80
|
|
|
71
81
|
# Initialize detector if needed
|
|
72
82
|
if face_mesh_obj is None:
|
|
73
|
-
face_mesh_obj =
|
|
83
|
+
face_mesh_obj = mp.solutions.face_mesh.FaceMesh(
|
|
74
84
|
min_detection_confidence=min_confidence,
|
|
75
85
|
refine_landmarks=True,
|
|
76
86
|
static_image_mode=True
|
|
@@ -173,13 +183,21 @@ def analyze_eye_status_live(
|
|
|
173
183
|
if not 0 <= min_confidence <= 1:
|
|
174
184
|
raise ValueError("'min_confidence' must be between 0 and 1")
|
|
175
185
|
|
|
186
|
+
try:
|
|
187
|
+
import mediapipe as mp
|
|
188
|
+
except ImportError as err:
|
|
189
|
+
raise ImportError(
|
|
190
|
+
"The optional 'mediapipe' dependency is required for eye status "
|
|
191
|
+
'analysis. Install it with: pip install "ImagePRO-Python[mediapipe]"'
|
|
192
|
+
) from err
|
|
193
|
+
|
|
176
194
|
# Initialize webcam
|
|
177
195
|
cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)
|
|
178
196
|
if not cap.isOpened():
|
|
179
197
|
raise RuntimeError("Failed to access webcam")
|
|
180
198
|
|
|
181
199
|
# Initialize face mesh detector for video
|
|
182
|
-
face_mesh =
|
|
200
|
+
face_mesh = mp.solutions.face_mesh.FaceMesh(
|
|
183
201
|
max_num_faces=1,
|
|
184
202
|
min_detection_confidence=min_confidence,
|
|
185
203
|
refine_landmarks=True,
|
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import sys
|
|
4
4
|
from pathlib import Path
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
5
6
|
|
|
6
7
|
# Add src directory to path for absolute imports
|
|
7
8
|
_file_path = Path(__file__).resolve()
|
|
@@ -13,11 +14,13 @@ import os
|
|
|
13
14
|
|
|
14
15
|
import cv2
|
|
15
16
|
import numpy as np
|
|
16
|
-
from insightface.app import FaceAnalysis
|
|
17
17
|
|
|
18
18
|
from ImagePRO.utils.image import Image
|
|
19
19
|
from ImagePRO.utils.result import Result
|
|
20
20
|
|
|
21
|
+
if TYPE_CHECKING: # insightface is imported lazily inside the function
|
|
22
|
+
from insightface.app import FaceAnalysis
|
|
23
|
+
|
|
21
24
|
# Constants
|
|
22
25
|
DEFAULT_SIMILARITY_THRESHOLD = 0.5
|
|
23
26
|
DEFAULT_MODEL_NAME = "buffalo_l"
|
|
@@ -62,6 +65,15 @@ def compare_faces(
|
|
|
62
65
|
if not isinstance(image_2, Image):
|
|
63
66
|
raise TypeError("'image_2' must be an Image instance")
|
|
64
67
|
|
|
68
|
+
try:
|
|
69
|
+
from insightface.app import FaceAnalysis
|
|
70
|
+
except ImportError as err:
|
|
71
|
+
raise ImportError(
|
|
72
|
+
"The optional 'insightface' dependency is required for face "
|
|
73
|
+
'comparison. Install it with: pip install '
|
|
74
|
+
'"ImagePRO-Python[insightface]"'
|
|
75
|
+
) from err
|
|
76
|
+
|
|
65
77
|
# Initialize model if needed
|
|
66
78
|
if app is None:
|
|
67
79
|
app = FaceAnalysis(
|
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import sys
|
|
4
4
|
from pathlib import Path
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
5
6
|
|
|
6
7
|
# Add src directory to path for absolute imports
|
|
7
8
|
_file_path = Path(__file__).resolve()
|
|
@@ -10,13 +11,15 @@ if str(_src_path) not in sys.path:
|
|
|
10
11
|
sys.path.insert(0, str(_src_path))
|
|
11
12
|
|
|
12
13
|
import cv2
|
|
13
|
-
import mediapipe as mp
|
|
14
14
|
import numpy as np
|
|
15
15
|
|
|
16
16
|
from ImagePRO.human_analysis.face_analysis.face_mesh_analysis import analyze_face_mesh
|
|
17
17
|
from ImagePRO.utils.image import Image
|
|
18
18
|
from ImagePRO.utils.result import Result
|
|
19
19
|
|
|
20
|
+
if TYPE_CHECKING: # mediapipe is imported lazily inside analyze_face_mesh
|
|
21
|
+
import mediapipe as mp
|
|
22
|
+
|
|
20
23
|
|
|
21
24
|
# Constants
|
|
22
25
|
DEFAULT_MAX_FACES = 1
|
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import sys
|
|
4
4
|
from pathlib import Path
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
5
6
|
|
|
6
7
|
# Add src directory to path for absolute imports
|
|
7
8
|
_file_path = Path(__file__).resolve()
|
|
@@ -13,12 +14,11 @@ from ImagePRO.utils.image import Image
|
|
|
13
14
|
from ImagePRO.utils.result import Result
|
|
14
15
|
|
|
15
16
|
import cv2
|
|
16
|
-
|
|
17
|
+
|
|
18
|
+
if TYPE_CHECKING: # mediapipe is imported lazily inside the functions
|
|
19
|
+
import mediapipe as mp
|
|
17
20
|
|
|
18
21
|
# Constants
|
|
19
|
-
mp_face_mesh = mp.solutions.face_mesh
|
|
20
|
-
mp_drawing_utils = mp.solutions.drawing_utils
|
|
21
|
-
mp_drawing_styles = mp.solutions.drawing_styles
|
|
22
22
|
DEFAULT_MAX_FACES = 1
|
|
23
23
|
DEFAULT_MIN_CONFIDENCE = 0.7
|
|
24
24
|
TOTAL_FACE_LANDMARKS = 468
|
|
@@ -71,7 +71,6 @@ def analyze_face_mesh(
|
|
|
71
71
|
- Coordinates are normalized [0,1]. Multiply by width/height for pixels
|
|
72
72
|
- Full mesh (468 points) shows tessellation, specific points show dots
|
|
73
73
|
"""
|
|
74
|
-
|
|
75
74
|
# Validate inputs
|
|
76
75
|
if not isinstance(image, Image):
|
|
77
76
|
raise TypeError("'image' must be an Image instance")
|
|
@@ -88,6 +87,18 @@ def analyze_face_mesh(
|
|
|
88
87
|
):
|
|
89
88
|
raise TypeError("'landmarks_idx' must be a list of integers")
|
|
90
89
|
|
|
90
|
+
try:
|
|
91
|
+
import mediapipe as mp
|
|
92
|
+
except ImportError as err:
|
|
93
|
+
raise ImportError(
|
|
94
|
+
"The optional 'mediapipe' dependency is required for face mesh "
|
|
95
|
+
'analysis. Install it with: pip install "ImagePRO-Python[mediapipe]"'
|
|
96
|
+
) from err
|
|
97
|
+
|
|
98
|
+
mp_face_mesh = mp.solutions.face_mesh
|
|
99
|
+
mp_drawing_utils = mp.solutions.drawing_utils
|
|
100
|
+
mp_drawing_styles = mp.solutions.drawing_styles
|
|
101
|
+
|
|
91
102
|
# Initialize detector if needed
|
|
92
103
|
if face_mesh_obj is None:
|
|
93
104
|
face_mesh = mp_face_mesh.FaceMesh(
|
|
@@ -195,13 +206,21 @@ def analyze_face_mesh_live(
|
|
|
195
206
|
if not isinstance(min_confidence, (int, float)) or not (0 <= min_confidence <= 1):
|
|
196
207
|
raise ValueError("'min_confidence' must be between 0 and 1")
|
|
197
208
|
|
|
209
|
+
try:
|
|
210
|
+
import mediapipe as mp
|
|
211
|
+
except ImportError as err:
|
|
212
|
+
raise ImportError(
|
|
213
|
+
"The optional 'mediapipe' dependency is required for face mesh "
|
|
214
|
+
'analysis. Install it with: pip install "ImagePRO-Python[mediapipe]"'
|
|
215
|
+
) from err
|
|
216
|
+
|
|
198
217
|
# Initialize camera
|
|
199
218
|
cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)
|
|
200
219
|
if not cap.isOpened():
|
|
201
220
|
raise RuntimeError("Cannot access webcam")
|
|
202
221
|
|
|
203
222
|
# Initialize detector in tracking mode for better performance
|
|
204
|
-
face_mesh =
|
|
223
|
+
face_mesh = mp.solutions.face_mesh.FaceMesh(
|
|
205
224
|
max_num_faces=max_faces,
|
|
206
225
|
min_detection_confidence=min_confidence,
|
|
207
226
|
refine_landmarks=True,
|
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import sys
|
|
4
4
|
from pathlib import Path
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
5
6
|
|
|
6
7
|
# Add src directory to path for absolute imports
|
|
7
8
|
_file_path = Path(__file__).resolve()
|
|
@@ -14,10 +15,11 @@ from ImagePRO.utils.image import Image
|
|
|
14
15
|
from ImagePRO.utils.result import Result
|
|
15
16
|
|
|
16
17
|
import cv2
|
|
17
|
-
|
|
18
|
+
|
|
19
|
+
if TYPE_CHECKING: # mediapipe is imported lazily inside the functions
|
|
20
|
+
import mediapipe as mp
|
|
18
21
|
|
|
19
22
|
# Constants
|
|
20
|
-
mp_face_mesh = mp.solutions.face_mesh
|
|
21
23
|
DEFAULT_MAX_FACES = 1
|
|
22
24
|
DEFAULT_MIN_CONFIDENCE = 0.7
|
|
23
25
|
HEAD_POSE_INDICES = [1, 152, 33, 263, 168] # nose_tip, chin, left_eye, right_eye, nasion
|
|
@@ -169,13 +171,21 @@ def estimate_head_pose_live(
|
|
|
169
171
|
if not 0 <= min_confidence <= 1:
|
|
170
172
|
raise ValueError("'min_confidence' must be between 0 and 1")
|
|
171
173
|
|
|
174
|
+
try:
|
|
175
|
+
import mediapipe as mp
|
|
176
|
+
except ImportError as err:
|
|
177
|
+
raise ImportError(
|
|
178
|
+
"The optional 'mediapipe' dependency is required for head pose "
|
|
179
|
+
'estimation. Install it with: pip install "ImagePRO-Python[mediapipe]"'
|
|
180
|
+
) from err
|
|
181
|
+
|
|
172
182
|
# Initialize webcam
|
|
173
183
|
cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)
|
|
174
184
|
if not cap.isOpened():
|
|
175
185
|
raise RuntimeError("Failed to access webcam")
|
|
176
186
|
|
|
177
187
|
# Initialize face mesh detector for video
|
|
178
|
-
face_mesh =
|
|
188
|
+
face_mesh = mp.solutions.face_mesh.FaceMesh(
|
|
179
189
|
max_num_faces=max_faces,
|
|
180
190
|
min_detection_confidence=min_confidence,
|
|
181
191
|
refine_landmarks=True,
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Object Analysis Module
|
|
2
|
+
# Provides object detection capabilities using YOLO models
|
|
3
|
+
#
|
|
4
|
+
# The ultralytics dependency is optional and imported lazily inside the
|
|
5
|
+
# functions that need it, so this package imports cleanly without it.
|
|
6
|
+
|
|
7
|
+
from . import object_detection
|
|
8
|
+
|
|
9
|
+
__all__ = ["object_detection"]
|
{imagepro_python-1.3.0 → imagepro_python-1.3.1}/src/ImagePRO/object_analysis/object_detection.py
RENAMED
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import sys
|
|
4
4
|
from pathlib import Path
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
5
6
|
|
|
6
7
|
# Add src directory to path for absolute imports
|
|
7
8
|
_file_path = Path(__file__).resolve()
|
|
@@ -9,11 +10,12 @@ _src_path = _file_path.parents[2] # Go up to src directory
|
|
|
9
10
|
if str(_src_path) not in sys.path:
|
|
10
11
|
sys.path.insert(0, str(_src_path))
|
|
11
12
|
|
|
12
|
-
from ultralytics import YOLO
|
|
13
|
-
|
|
14
13
|
from ImagePRO.utils.image import Image
|
|
15
14
|
from ImagePRO.utils.result import Result
|
|
16
15
|
|
|
16
|
+
if TYPE_CHECKING: # ultralytics is imported lazily inside the function
|
|
17
|
+
from ultralytics import YOLO
|
|
18
|
+
|
|
17
19
|
# Constants
|
|
18
20
|
DEFAULT_ACCURACY_LEVEL = 1
|
|
19
21
|
MODEL_MAPPING = {
|
|
@@ -65,15 +67,24 @@ def detect_objects(
|
|
|
65
67
|
if not isinstance(image, Image):
|
|
66
68
|
raise TypeError("'image' must be an Image instance")
|
|
67
69
|
|
|
70
|
+
# accuracy_level only applies when no model is given
|
|
71
|
+
if model is None and accuracy_level not in MODEL_MAPPING:
|
|
72
|
+
raise ValueError(
|
|
73
|
+
f"'accuracy_level' must be in {list(MODEL_MAPPING.keys())}, "
|
|
74
|
+
f"got {accuracy_level}"
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
try:
|
|
78
|
+
from ultralytics import YOLO
|
|
79
|
+
except ImportError as err:
|
|
80
|
+
raise ImportError(
|
|
81
|
+
"The optional 'ultralytics' dependency is required for object "
|
|
82
|
+
'detection. Install it with: pip install "ImagePRO-Python[yolo]"'
|
|
83
|
+
) from err
|
|
84
|
+
|
|
68
85
|
# Initialize model
|
|
69
86
|
model_name = None
|
|
70
87
|
if model is None:
|
|
71
|
-
if accuracy_level not in MODEL_MAPPING:
|
|
72
|
-
raise ValueError(
|
|
73
|
-
f"'accuracy_level' must be in {list(MODEL_MAPPING.keys())}, "
|
|
74
|
-
f"got {accuracy_level}"
|
|
75
|
-
)
|
|
76
|
-
|
|
77
88
|
model_name = MODEL_MAPPING[accuracy_level]
|
|
78
89
|
model = YOLO(model=model_name)
|
|
79
90
|
|
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
# Pre-processing Module
|
|
2
2
|
# Provides image manipulation, filtering, and enhancement capabilities
|
|
3
|
+
#
|
|
4
|
+
# dataset_generator uses the optional mediapipe dependency, imported
|
|
5
|
+
# lazily inside its functions, so it is safe to import here regardless.
|
|
3
6
|
|
|
4
7
|
from . import blur
|
|
5
8
|
from . import contrast
|
|
6
9
|
from . import crop
|
|
10
|
+
from . import dataset_generator
|
|
7
11
|
from . import grayscale
|
|
8
12
|
from . import resize
|
|
9
13
|
from . import rotate
|
|
10
14
|
from . import sharpen
|
|
11
15
|
|
|
12
|
-
try: # dataset_generator needs the optional mediapipe dependency
|
|
13
|
-
from . import dataset_generator
|
|
14
|
-
except ImportError:
|
|
15
|
-
dataset_generator = None
|
|
16
|
-
|
|
17
16
|
__all__ = [
|
|
18
17
|
"blur",
|
|
19
18
|
"contrast",
|
{imagepro_python-1.3.0 → imagepro_python-1.3.1}/src/ImagePRO/pre_processing/dataset_generator.py
RENAMED
|
@@ -12,7 +12,6 @@ if str(_src_path) not in sys.path:
|
|
|
12
12
|
sys.path.insert(0, str(_src_path))
|
|
13
13
|
|
|
14
14
|
import cv2
|
|
15
|
-
import mediapipe as mp
|
|
16
15
|
|
|
17
16
|
from ImagePRO.human_analysis.face_analysis.face_detection import detect_faces
|
|
18
17
|
from ImagePRO.pre_processing import blur, grayscale, resize, rotate, sharpen
|
|
@@ -95,6 +94,14 @@ def capture_bulk_pictures(
|
|
|
95
94
|
if not isinstance(delay, (int, float)) or delay < 0:
|
|
96
95
|
raise ValueError("'delay' must be a non-negative number")
|
|
97
96
|
|
|
97
|
+
try:
|
|
98
|
+
import mediapipe as mp
|
|
99
|
+
except ImportError as err:
|
|
100
|
+
raise ImportError(
|
|
101
|
+
"The optional 'mediapipe' dependency is required for dataset "
|
|
102
|
+
'generation. Install it with: pip install "ImagePRO-Python[mediapipe]"'
|
|
103
|
+
) from err
|
|
104
|
+
|
|
98
105
|
# Setup output directory structure
|
|
99
106
|
base_dir = Path(folder_path)
|
|
100
107
|
face_folder = base_dir / str(face_id)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ImagePRO-Python
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.1
|
|
4
4
|
Summary: Professional & modular image processing library with OpenCV, MediaPipe, and YOLO integration.
|
|
5
5
|
Author-email: Parsa Safaie <parsasafaie.2568@proton.me>
|
|
6
6
|
License: MIT
|
|
@@ -90,6 +90,8 @@ pip install "ImagePRO-Python[full]" # Everything
|
|
|
90
90
|
pip install "ImagePRO-Python[dev]" # Test tooling (pytest)
|
|
91
91
|
```
|
|
92
92
|
|
|
93
|
+
> **Note**: The base install is lightweight — AI backends (MediaPipe, Ultralytics, InsightFace) are optional and imported lazily, only when you call a function that actually needs them. `import ImagePRO` never loads these dependencies. If a backend is missing, the function you call raises an `ImportError` telling you exactly which extra to install.
|
|
94
|
+
|
|
93
95
|
### From Source
|
|
94
96
|
```bash
|
|
95
97
|
git clone https://github.com/parsasafaie/ImagePRO.git
|
|
@@ -176,6 +178,7 @@ ImagePRO is built with a modular architecture designed for extensibility and mai
|
|
|
176
178
|
- **Clean Separation of Concerns**: Each module handles a specific domain
|
|
177
179
|
- **Consistent API Patterns**: All functions follow the same input/output conventions
|
|
178
180
|
- **Shared Utilities**: Common `Image` and `Result` classes for unified I/O
|
|
181
|
+
- **Lazy Optional Imports**: Heavy AI dependencies (MediaPipe, Ultralytics, InsightFace) are only imported inside the functions that use them, keeping `import ImagePRO` fast and independent of installed extras
|
|
179
182
|
- **Professional Error Handling**: Comprehensive validation with clear error messages
|
|
180
183
|
- **Type Safety**: Full type hints throughout the codebase
|
|
181
184
|
- **Documentation**: Google-style docstrings for all functions
|
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import mediapipe as mp # real package or the conftest stub
|
|
6
|
+
|
|
5
7
|
import numpy as np
|
|
6
8
|
import pytest
|
|
7
9
|
|
|
8
|
-
from ImagePRO.human_analysis.face_analysis import face_mesh_analysis
|
|
9
10
|
from ImagePRO.human_analysis.face_analysis.face_mesh_analysis import analyze_face_mesh
|
|
10
11
|
|
|
11
12
|
from fakes import FakeFaceMesh, make_landmarks
|
|
@@ -23,7 +24,7 @@ def patch_facemesh(monkeypatch):
|
|
|
23
24
|
instance_holder["instance"] = mesh
|
|
24
25
|
return mesh
|
|
25
26
|
|
|
26
|
-
monkeypatch.setattr(
|
|
27
|
+
monkeypatch.setattr(mp.solutions.face_mesh, "FaceMesh", factory)
|
|
27
28
|
return instance_holder
|
|
28
29
|
|
|
29
30
|
return _patch
|
|
@@ -120,7 +121,7 @@ class TestAnalyzeFaceMeshWithDetection:
|
|
|
120
121
|
patch_facemesh(result=SimpleNamespace(multi_face_landmarks=faces))
|
|
121
122
|
calls = []
|
|
122
123
|
monkeypatch.setattr(
|
|
123
|
-
|
|
124
|
+
mp.solutions.drawing_utils,
|
|
124
125
|
"draw_landmarks",
|
|
125
126
|
lambda *args, **kwargs: calls.append(args),
|
|
126
127
|
)
|
|
@@ -156,7 +157,7 @@ class TestAnalyzeFaceMeshConfiguration:
|
|
|
156
157
|
)
|
|
157
158
|
created = []
|
|
158
159
|
monkeypatch.setattr(
|
|
159
|
-
|
|
160
|
+
mp.solutions.face_mesh,
|
|
160
161
|
"FaceMesh",
|
|
161
162
|
lambda **kwargs: created.append(kwargs),
|
|
162
163
|
)
|
|
@@ -84,9 +84,7 @@ class TestDetectObjectsModelSelection:
|
|
|
84
84
|
def __call__(self, image):
|
|
85
85
|
return [self._result]
|
|
86
86
|
|
|
87
|
-
monkeypatch.setattr(
|
|
88
|
-
"ImagePRO.object_analysis.object_detection.YOLO", RecordingYOLO
|
|
89
|
-
)
|
|
87
|
+
monkeypatch.setattr("ultralytics.YOLO", RecordingYOLO)
|
|
90
88
|
result = detect_objects(image=sample_bgr_image, accuracy_level=level)
|
|
91
89
|
assert created["model"] == expected_model
|
|
92
90
|
assert result.meta["model"] == expected_model
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
# Body Analysis Module
|
|
2
|
-
# Provides body pose estimation and hand tracking capabilities
|
|
3
|
-
#
|
|
4
|
-
# Both modules need the optional mediapipe dependency; they are imported
|
|
5
|
-
# guardedly so the package stays importable without it.
|
|
6
|
-
|
|
7
|
-
try: # requires mediapipe
|
|
8
|
-
from . import body_pose_estimation
|
|
9
|
-
except ImportError:
|
|
10
|
-
body_pose_estimation = None
|
|
11
|
-
|
|
12
|
-
try: # requires mediapipe
|
|
13
|
-
from . import hand_tracking
|
|
14
|
-
except ImportError:
|
|
15
|
-
hand_tracking = None
|
|
16
|
-
|
|
17
|
-
__all__ = ["body_pose_estimation", "hand_tracking"]
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
# Face Analysis Module
|
|
2
|
-
# Provides facial landmark detection, pose estimation, and eye status analysis
|
|
3
|
-
#
|
|
4
|
-
# The mediapipe-based modules and the insightface-based module are imported
|
|
5
|
-
# guardedly so that importing the package works with only the dependencies
|
|
6
|
-
# a caller actually needs; unavailable modules are set to None.
|
|
7
|
-
|
|
8
|
-
try: # requires mediapipe
|
|
9
|
-
from . import eye_status_analysis
|
|
10
|
-
except ImportError:
|
|
11
|
-
eye_status_analysis = None
|
|
12
|
-
|
|
13
|
-
try: # requires insightface
|
|
14
|
-
from . import face_comparison
|
|
15
|
-
except ImportError:
|
|
16
|
-
face_comparison = None
|
|
17
|
-
|
|
18
|
-
try: # requires mediapipe
|
|
19
|
-
from . import face_detection
|
|
20
|
-
except ImportError:
|
|
21
|
-
face_detection = None
|
|
22
|
-
|
|
23
|
-
try: # requires mediapipe
|
|
24
|
-
from . import face_mesh_analysis
|
|
25
|
-
except ImportError:
|
|
26
|
-
face_mesh_analysis = None
|
|
27
|
-
|
|
28
|
-
try: # requires mediapipe
|
|
29
|
-
from . import head_pose_estimation
|
|
30
|
-
except ImportError:
|
|
31
|
-
head_pose_estimation = None
|
|
32
|
-
|
|
33
|
-
__all__ = [
|
|
34
|
-
"eye_status_analysis",
|
|
35
|
-
"face_comparison",
|
|
36
|
-
"face_detection",
|
|
37
|
-
"face_mesh_analysis",
|
|
38
|
-
"head_pose_estimation"
|
|
39
|
-
]
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
# Object Analysis Module
|
|
2
|
-
# Provides object detection capabilities using YOLO models
|
|
3
|
-
|
|
4
|
-
try: # object_detection needs the optional ultralytics dependency
|
|
5
|
-
from . import object_detection
|
|
6
|
-
except ImportError:
|
|
7
|
-
object_detection = None
|
|
8
|
-
|
|
9
|
-
__all__ = ["object_detection"]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{imagepro_python-1.3.0 → imagepro_python-1.3.1}/src/ImagePRO_Python.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|