ImagePRO-Python 0.5.1__py3-none-any.whl → 0.5.2__py3-none-any.whl

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.
Files changed (30) hide show
  1. ImagePRO/__init__.py +33 -0
  2. ImagePRO/human_analysis/__init__.py +7 -0
  3. ImagePRO/human_analysis/body_analysis/__init__.py +7 -0
  4. ImagePRO/human_analysis/body_analysis/body_pose_estimation.py +10 -5
  5. ImagePRO/human_analysis/body_analysis/hand_tracking.py +13 -7
  6. ImagePRO/human_analysis/face_analysis/__init__.py +16 -0
  7. ImagePRO/human_analysis/face_analysis/eye_status_analysis.py +7 -3
  8. ImagePRO/human_analysis/face_analysis/face_comparison.py +9 -3
  9. ImagePRO/human_analysis/face_analysis/face_detection.py +12 -7
  10. ImagePRO/human_analysis/face_analysis/face_mesh_analysis.py +8 -4
  11. ImagePRO/human_analysis/face_analysis/head_pose_estimation.py +7 -3
  12. ImagePRO/object_analysis/__init__.py +6 -0
  13. ImagePRO/object_analysis/object_detection.py +22 -20
  14. ImagePRO/pre_processing/__init__.py +22 -0
  15. ImagePRO/pre_processing/blur.py +26 -12
  16. ImagePRO/pre_processing/contrast.py +8 -2
  17. ImagePRO/pre_processing/crop.py +4 -0
  18. ImagePRO/pre_processing/dataset_generator.py +14 -6
  19. ImagePRO/pre_processing/grayscale.py +10 -9
  20. ImagePRO/pre_processing/resize.py +17 -19
  21. ImagePRO/pre_processing/rotate.py +5 -1
  22. ImagePRO/pre_processing/sharpen.py +6 -2
  23. ImagePRO/utils/__init__.py +6 -0
  24. imagepro_python-0.5.2.dist-info/METADATA +30 -0
  25. imagepro_python-0.5.2.dist-info/RECORD +29 -0
  26. imagepro_python-0.5.1.dist-info/METADATA +0 -20
  27. imagepro_python-0.5.1.dist-info/RECORD +0 -28
  28. {imagepro_python-0.5.1.dist-info → imagepro_python-0.5.2.dist-info}/WHEEL +0 -0
  29. {imagepro_python-0.5.1.dist-info → imagepro_python-0.5.2.dist-info}/licenses/LICENSE +0 -0
  30. {imagepro_python-0.5.1.dist-info → imagepro_python-0.5.2.dist-info}/top_level.txt +0 -0
ImagePRO/__init__.py CHANGED
@@ -0,0 +1,33 @@
1
+ """
2
+ ImagePRO - Professional & Modular Image Processing Library in Python
3
+
4
+ A clean, modular, and easy-to-use Python library for image processing tasks,
5
+ built with OpenCV, MediaPipe, YOLO and designed to be extensible for developers.
6
+
7
+ Whether you're working on computer vision pipelines, preprocessing images for AI models,
8
+ or simply automating batch image edits — ImagePRO gives you powerful tools with minimal effort.
9
+
10
+ Features:
11
+ - Image I/O management and batch processing
12
+ - Pre-processing: resize, crop, rotate, blur, sharpen, contrast enhancement
13
+ - Human analysis: face mesh, pose estimation, hand tracking
14
+ - Object detection with YOLO models
15
+ - Real-time processing capabilities
16
+ """
17
+
18
+ __version__ = "0.5.2"
19
+ __author__ = "Parsa Safaie"
20
+ __email__ = "parsasafaie.2568@proton.me"
21
+
22
+ # Core modules
23
+ from . import utils
24
+ from . import pre_processing
25
+ from . import human_analysis
26
+ from . import object_analysis
27
+
28
+ __all__ = [
29
+ "utils",
30
+ "pre_processing",
31
+ "human_analysis",
32
+ "object_analysis"
33
+ ]
@@ -0,0 +1,7 @@
1
+ # Human Analysis Module
2
+ # Provides face and body analysis capabilities using MediaPipe
3
+
4
+ from . import face_analysis
5
+ from . import body_analysis
6
+
7
+ __all__ = ["face_analysis", "body_analysis"]
@@ -0,0 +1,7 @@
1
+ # Body Analysis Module
2
+ # Provides body pose estimation and hand tracking capabilities
3
+
4
+ from . import body_pose_estimation
5
+ from . import hand_tracking
6
+
7
+ __all__ = ["body_pose_estimation", "hand_tracking"]
@@ -10,10 +10,15 @@ sys.path.append(str(parent_dir))
10
10
 
11
11
  from utils.io_handler import IOHandler
12
12
 
13
+ # Constants
13
14
  mp_pose = mp.solutions.pose
15
+ TOTAL_LANDMARKS = 33
16
+ DEFAULT_CONFIDENCE = 0.7
17
+ LANDMARK_RADIUS = 3
18
+ LANDMARK_COLOR = (0, 0, 255) # Red color for landmarks
14
19
 
15
20
  def detect_body_pose(
16
- model_accuracy: float = 0.7,
21
+ model_accuracy: float = DEFAULT_CONFIDENCE,
17
22
  landmarks_idx: list | None = None,
18
23
  src_image_path: str | None = None,
19
24
  src_np_image=None,
@@ -56,7 +61,7 @@ def detect_body_pose(
56
61
  np_image = IOHandler.load_image(image_path=src_image_path, np_image=src_np_image)
57
62
 
58
63
  if landmarks_idx is None:
59
- landmarks_idx = list(range(33))
64
+ landmarks_idx = list(range(TOTAL_LANDMARKS))
60
65
 
61
66
  if pose_obj is None:
62
67
  pose_obj = mp_pose.Pose(
@@ -71,7 +76,7 @@ def detect_body_pose(
71
76
  all_landmarks = []
72
77
 
73
78
  if result.pose_landmarks:
74
- if len(landmarks_idx) == 33:
79
+ if len(landmarks_idx) == TOTAL_LANDMARKS:
75
80
  mp.solutions.drawing_utils.draw_landmarks(
76
81
  annotated_image,
77
82
  result.pose_landmarks,
@@ -83,7 +88,7 @@ def detect_body_pose(
83
88
  for idx in landmarks_idx:
84
89
  lm = result.pose_landmarks.landmark[idx]
85
90
  x, y = int(w * lm.x), int(h * lm.y)
86
- cv2.circle(annotated_image, (x, y), 3, (0, 0, 255), -1)
91
+ cv2.circle(annotated_image, (x, y), LANDMARK_RADIUS, LANDMARK_COLOR, -1)
87
92
 
88
93
  for idx in landmarks_idx:
89
94
  lm = result.pose_landmarks.landmark[idx]
@@ -104,7 +109,7 @@ def detect_body_pose_live():
104
109
  raise RuntimeError("Failed to open webcam.")
105
110
 
106
111
  pose_obj = mp_pose.Pose(
107
- min_detection_confidence=0.7,
112
+ min_detection_confidence=DEFAULT_CONFIDENCE,
108
113
  static_image_mode=False
109
114
  )
110
115
 
@@ -10,12 +10,18 @@ sys.path.append(str(parent_dir))
10
10
 
11
11
  from utils.io_handler import IOHandler
12
12
 
13
+ # Constants
13
14
  mp_hands = mp.solutions.hands
15
+ DEFAULT_MAX_HANDS = 2
16
+ DEFAULT_MIN_CONFIDENCE = 0.7
17
+ TOTAL_HAND_LANDMARKS = 21
18
+ LANDMARK_RADIUS = 3
19
+ LANDMARK_COLOR = (0, 0, 255) # Red color for landmarks
14
20
 
15
21
 
16
22
  def detect_hands(
17
- max_hands: int = 2,
18
- min_confidence: float = 0.7,
23
+ max_hands: int = DEFAULT_MAX_HANDS,
24
+ min_confidence: float = DEFAULT_MIN_CONFIDENCE,
19
25
  landmarks_idx: list | None = None,
20
26
  src_image_path: str | None = None,
21
27
  src_np_image=None,
@@ -71,7 +77,7 @@ def detect_hands(
71
77
  )
72
78
 
73
79
  if landmarks_idx is None:
74
- landmarks_idx = list(range(21))
80
+ landmarks_idx = list(range(TOTAL_HAND_LANDMARKS))
75
81
 
76
82
  rgb_image = cv2.cvtColor(np_image, cv2.COLOR_BGR2RGB)
77
83
  results = hands_obj.process(rgb_image)
@@ -81,7 +87,7 @@ def detect_hands(
81
87
 
82
88
  if results.multi_hand_landmarks:
83
89
  for hand_id, hand_landmarks in enumerate(results.multi_hand_landmarks):
84
- if len(landmarks_idx) == 21:
90
+ if len(landmarks_idx) == TOTAL_HAND_LANDMARKS:
85
91
  mp.solutions.drawing_utils.draw_landmarks(
86
92
  image=annotated_image,
87
93
  landmark_list=hand_landmarks,
@@ -94,7 +100,7 @@ def detect_hands(
94
100
  for idx in landmarks_idx:
95
101
  lm = hand_landmarks.landmark[idx]
96
102
  x, y = int(w * lm.x), int(h * lm.y)
97
- cv2.circle(annotated_image, (x, y), 3, (0, 0, 255), -1)
103
+ cv2.circle(annotated_image, (x, y), LANDMARK_RADIUS, LANDMARK_COLOR, -1)
98
104
 
99
105
  for idx in landmarks_idx:
100
106
  lm = hand_landmarks.landmark[idx]
@@ -108,7 +114,7 @@ def detect_hands(
108
114
  return annotated_image, all_landmarks
109
115
 
110
116
 
111
- def detect_hands_live(max_hands: int = 2, min_confidence: float = 0.7):
117
+ def detect_hands_live(max_hands: int = DEFAULT_MAX_HANDS, min_confidence: float = DEFAULT_MIN_CONFIDENCE):
112
118
  """Real-time hand detection via webcam. Press ESC to exit."""
113
119
  if not isinstance(max_hands, int) or max_hands <= 0:
114
120
  raise ValueError("'max_hands' must be a positive integer.")
@@ -149,4 +155,4 @@ def detect_hands_live(max_hands: int = 2, min_confidence: float = 0.7):
149
155
 
150
156
 
151
157
  if __name__ == "__main__":
152
- detect_hands_live(max_hands=2)
158
+ detect_hands_live(max_hands=DEFAULT_MAX_HANDS)
@@ -0,0 +1,16 @@
1
+ # Face Analysis Module
2
+ # Provides facial landmark detection, pose estimation, and eye status analysis
3
+
4
+ from . import eye_status_analysis
5
+ from . import face_comparison
6
+ from . import face_detection
7
+ from . import face_mesh_analysis
8
+ from . import head_pose_estimation
9
+
10
+ __all__ = [
11
+ "eye_status_analysis",
12
+ "face_comparison",
13
+ "face_detection",
14
+ "face_mesh_analysis",
15
+ "head_pose_estimation"
16
+ ]
@@ -11,15 +11,19 @@ sys.path.append(str(parent_dir))
11
11
  from utils.io_handler import IOHandler
12
12
  from human_analysis.face_analysis.face_mesh_analysis import analyze_face_mesh
13
13
 
14
+ # Constants
14
15
  mp_face_mesh = mp.solutions.face_mesh
16
+ DEFAULT_MIN_CONFIDENCE = 0.7
17
+ DEFAULT_THRESHOLD = 0.2
18
+ RIGHT_EYE_INDICES = [386, 374, 263, 362] # MediaPipe 468-point model
15
19
 
16
20
 
17
21
  def analyze_eye_status(
18
- min_confidence: float = 0.7,
22
+ min_confidence: float = DEFAULT_MIN_CONFIDENCE,
19
23
  src_image_path: str | None = None,
20
24
  src_np_image=None,
21
25
  face_mesh_obj=None,
22
- threshold: float = 0.2,
26
+ threshold: float = DEFAULT_THRESHOLD,
23
27
  ) -> bool:
24
28
  """
25
29
  Analyze right-eye open/closed status via Eye Aspect Ratio (EAR).
@@ -72,7 +76,7 @@ def analyze_eye_status(
72
76
  )
73
77
 
74
78
  # Landmark indices for right eye (MediaPipe 468-point model)
75
- indices = [386, 374, 263, 362]
79
+ indices = RIGHT_EYE_INDICES
76
80
 
77
81
  _, landmarks = analyze_face_mesh(
78
82
  max_faces=1,
@@ -2,6 +2,12 @@ from insightface.app import FaceAnalysis
2
2
  import cv2
3
3
  import numpy as np
4
4
 
5
+ # Constants
6
+ DEFAULT_SIMILARITY_THRESHOLD = 0.5
7
+ DEFAULT_MODEL_NAME = "buffalo_l"
8
+ DEFAULT_PROVIDER = "CPUExecutionProvider"
9
+
10
+
5
11
  def compare_faces(src_image_path_1, src_image_path_2, app=None):
6
12
  """
7
13
  Compare two face images using FaceAnalysis embeddings.
@@ -24,8 +30,8 @@ def compare_faces(src_image_path_1, src_image_path_2, app=None):
24
30
  # Prepare FaceAnalysis model if not provided
25
31
  if app is None:
26
32
  app = FaceAnalysis(
27
- name="buffalo_l",
28
- providers=["CPUExecutionProvider"],
33
+ name=DEFAULT_MODEL_NAME,
34
+ providers=[DEFAULT_PROVIDER],
29
35
  )
30
36
  app.prepare(ctx_id=0) # Run on CPU
31
37
 
@@ -57,4 +63,4 @@ def compare_faces(src_image_path_1, src_image_path_2, app=None):
57
63
  sim = np.dot(emb1, emb2) / (np.linalg.norm(emb1) * np.linalg.norm(emb2))
58
64
 
59
65
  # Return match result based on threshold
60
- return True if sim > 0.5 else False
66
+ return True if sim > DEFAULT_SIMILARITY_THRESHOLD else False
@@ -11,10 +11,19 @@ sys.path.append(str(parent_dir))
11
11
  from utils.io_handler import IOHandler
12
12
  from human_analysis.face_analysis.face_mesh_analysis import analyze_face_mesh
13
13
 
14
+ # Constants
15
+ DEFAULT_MAX_FACES = 1
16
+ DEFAULT_MIN_CONFIDENCE = 0.7
17
+ FACE_OUTLINE_INDICES = [
18
+ 10, 338, 297, 332, 284, 251, 389, 356, 454, 323,
19
+ 361, 288, 397, 365, 379, 378, 400, 377, 152, 148,
20
+ 176, 149, 150, 136, 164, 163, 153, 157
21
+ ]
22
+
14
23
 
15
24
  def detect_faces(
16
- max_faces: int = 1,
17
- min_confidence: float = 0.7,
25
+ max_faces: int = DEFAULT_MAX_FACES,
26
+ min_confidence: float = DEFAULT_MIN_CONFIDENCE,
18
27
  src_image_path: str | None = None,
19
28
  src_np_image=None,
20
29
  output_image_path: str | None = None,
@@ -68,11 +77,7 @@ def detect_faces(
68
77
  height, width = np_image.shape[:2]
69
78
 
70
79
  # Selected face outline landmark indices (MediaPipe 468-point model)
71
- face_outline_indices = [
72
- 10, 338, 297, 332, 284, 251, 389, 356, 454, 323,
73
- 361, 288, 397, 365, 379, 378, 400, 377, 152, 148,
74
- 176, 149, 150, 136, 164, 163, 153, 157
75
- ]
80
+ face_outline_indices = FACE_OUTLINE_INDICES
76
81
 
77
82
  # --- Run face mesh analysis ----------------------------------------------
78
83
  _, raw_landmarks = analyze_face_mesh(
@@ -10,14 +10,18 @@ sys.path.append(str(parent_dir))
10
10
 
11
11
  from utils.io_handler import IOHandler
12
12
 
13
+ # Constants
13
14
  mp_face_mesh = mp.solutions.face_mesh
14
15
  mp_drawing_utils = mp.solutions.drawing_utils
15
16
  mp_drawing_styles = mp.solutions.drawing_styles
17
+ DEFAULT_MAX_FACES = 1
18
+ DEFAULT_MIN_CONFIDENCE = 0.7
19
+ TOTAL_FACE_LANDMARKS = 468
16
20
 
17
21
 
18
22
  def analyze_face_mesh(
19
- max_faces: int = 1,
20
- min_confidence: float = 0.7,
23
+ max_faces: int = DEFAULT_MAX_FACES,
24
+ min_confidence: float = DEFAULT_MIN_CONFIDENCE,
21
25
  landmarks_idx: list | None = None,
22
26
  src_image_path: str | None = None,
23
27
  src_np_image=None,
@@ -118,7 +122,7 @@ def analyze_face_mesh(
118
122
 
119
123
  for face_id, face_landmarks in enumerate(results.multi_face_landmarks):
120
124
  # Draw either the full tessellation or specific landmark dots
121
- if len(landmarks_idx) == 468:
125
+ if len(landmarks_idx) == TOTAL_FACE_LANDMARKS:
122
126
  mp_drawing_utils.draw_landmarks(
123
127
  image=annotated,
124
128
  landmark_list=face_landmarks,
@@ -152,7 +156,7 @@ def analyze_face_mesh(
152
156
  return annotated, all_landmarks
153
157
 
154
158
 
155
- def analyze_face_mesh_live(max_faces: int = 1, min_confidence: float = 0.7):
159
+ def analyze_face_mesh_live(max_faces: int = DEFAULT_MAX_FACES, min_confidence: float = DEFAULT_MIN_CONFIDENCE):
156
160
  """
157
161
  Launch webcam preview with real-time FaceMesh overlay.
158
162
 
@@ -11,12 +11,16 @@ sys.path.append(str(parent_dir))
11
11
  from utils.io_handler import IOHandler
12
12
  from human_analysis.face_analysis.face_mesh_analysis import analyze_face_mesh
13
13
 
14
+ # Constants
14
15
  mp_face_mesh = mp.solutions.face_mesh
16
+ DEFAULT_MAX_FACES = 1
17
+ DEFAULT_MIN_CONFIDENCE = 0.7
18
+ HEAD_POSE_INDICES = [1, 152, 33, 263, 168] # nose_tip, chin, left_eye, right_eye, nasion
15
19
 
16
20
 
17
21
  def estimate_head_pose(
18
- max_faces: int = 1,
19
- min_confidence: float = 0.7,
22
+ max_faces: int = DEFAULT_MAX_FACES,
23
+ min_confidence: float = DEFAULT_MIN_CONFIDENCE,
20
24
  src_image_path: str | None = None,
21
25
  src_np_image=None,
22
26
  output_csv_path: str | None = None,
@@ -64,7 +68,7 @@ def estimate_head_pose(
64
68
  np_image = IOHandler.load_image(image_path=src_image_path, np_image=src_np_image)
65
69
 
66
70
  # Important landmark indices (MediaPipe 468 model)
67
- indices = [1, 152, 33, 263, 168] # nose_tip, chin, left_eye, right_eye, nasion
71
+ indices = HEAD_POSE_INDICES
68
72
 
69
73
  _, landmarks = analyze_face_mesh(
70
74
  max_faces=max_faces,
@@ -0,0 +1,6 @@
1
+ # Object Analysis Module
2
+ # Provides object detection capabilities using YOLO models
3
+
4
+ from . import object_detection
5
+
6
+ __all__ = ["object_detection"]
@@ -8,15 +8,26 @@ sys.path.append(str(parent_dir))
8
8
 
9
9
  from utils.io_handler import IOHandler
10
10
 
11
+ # Constants
12
+ DEFAULT_ACCURACY_LEVEL = 1
13
+ DEFAULT_CONFIDENCE = 0.5
14
+ MODEL_MAPPING = {
15
+ 1: "yolo11n.pt",
16
+ 2: "yolo11s.pt",
17
+ 3: "yolo11m.pt",
18
+ 4: "yolo11l.pt",
19
+ 5: "yolo11x.pt"
20
+ }
21
+
11
22
 
12
23
  def detect_objects(
13
24
  model=None,
14
- accuracy_level=1,
15
- src_image_path=None,
25
+ accuracy_level: int = DEFAULT_ACCURACY_LEVEL,
26
+ src_image_path: str | None = None,
16
27
  src_np_image=None,
17
- output_image_path=None,
18
- output_csv_path=None,
19
- show_result=False
28
+ output_image_path: str | None = None,
29
+ output_csv_path: str | None = None,
30
+ show_result: bool = False
20
31
  ):
21
32
  """
22
33
  Run object detection on a single image using Ultralytics YOLO.
@@ -56,19 +67,10 @@ def detect_objects(
56
67
  """
57
68
  # Create a model from preset if not provided by caller
58
69
  if model is None:
59
- if accuracy_level == 1:
60
- model_name = "yolo11n.pt"
61
- elif accuracy_level == 2:
62
- model_name = "yolo11s.pt"
63
- elif accuracy_level == 3:
64
- model_name = "yolo11m.pt"
65
- elif accuracy_level == 4:
66
- model_name = "yolo11l.pt"
67
- elif accuracy_level == 5:
68
- model_name = "yolo11x.pt"
69
- else:
70
- raise ValueError('Unknown accuracy level.')
71
-
70
+ if accuracy_level not in MODEL_MAPPING:
71
+ raise ValueError(f"'accuracy_level' must be in {list(MODEL_MAPPING.keys())}, got {accuracy_level}")
72
+
73
+ model_name = MODEL_MAPPING[accuracy_level]
72
74
  model = YOLO(model=model_name)
73
75
 
74
76
  # Load image from path or ndarray using the shared IO helper
@@ -90,9 +92,9 @@ def detect_objects(
90
92
  if show_result:
91
93
  result.show()
92
94
  if output_image_path:
93
- IOHandler.save_image(np_image=result.plot(), result_path=output_image_path)
95
+ print(IOHandler.save_image(np_image=result.plot(), result_path=output_image_path))
94
96
  if output_csv_path:
95
- IOHandler.save_csv(data=lines, result_path=output_csv_path)
97
+ print(IOHandler.save_csv(data=lines, result_path=output_csv_path))
96
98
 
97
99
  # Return the plotted image and the CSV-friendly rows
98
100
  return result.plot(), lines
@@ -0,0 +1,22 @@
1
+ # Pre-processing Module
2
+ # Provides image manipulation, filtering, and enhancement capabilities
3
+
4
+ from . import blur
5
+ from . import contrast
6
+ from . import crop
7
+ from . import dataset_generator
8
+ from . import grayscale
9
+ from . import resize
10
+ from . import rotate
11
+ from . import sharpen
12
+
13
+ __all__ = [
14
+ "blur",
15
+ "contrast",
16
+ "crop",
17
+ "dataset_generator",
18
+ "grayscale",
19
+ "resize",
20
+ "rotate",
21
+ "sharpen"
22
+ ]
@@ -9,9 +9,15 @@ sys.path.append(str(parent_dir))
9
9
 
10
10
  from utils.io_handler import IOHandler
11
11
 
12
+ # Constants
13
+ DEFAULT_KERNEL_SIZE = (5, 5)
14
+ DEFAULT_FILTER_SIZE = 5
15
+ DEFAULT_SIGMA_COLOR = 75
16
+ DEFAULT_SIGMA_SPACE = 75
17
+
12
18
 
13
19
  def apply_average_blur(
14
- kernel_size: tuple[int, int] = (5, 5),
20
+ kernel_size: tuple[int, int] = DEFAULT_KERNEL_SIZE,
15
21
  src_image_path: str | None = None,
16
22
  src_np_image=None,
17
23
  output_image_path: str | None = None
@@ -55,13 +61,15 @@ def apply_average_blur(
55
61
 
56
62
  np_image = IOHandler.load_image(image_path=src_image_path, np_image=src_np_image)
57
63
  blurred = cv2.blur(np_image, kernel_size)
64
+
58
65
  if output_image_path:
59
66
  print(IOHandler.save_image(blurred, output_image_path))
67
+
60
68
  return blurred
61
69
 
62
70
 
63
71
  def apply_gaussian_blur(
64
- kernel_size: tuple[int, int] = (5, 5),
72
+ kernel_size: tuple[int, int] = DEFAULT_KERNEL_SIZE,
65
73
  src_image_path: str | None = None,
66
74
  src_np_image=None,
67
75
  output_image_path: str | None = None
@@ -98,14 +106,16 @@ def apply_gaussian_blur(
98
106
  raise ValueError("'kernel_size' must be a tuple of two odd positive integers.")
99
107
 
100
108
  np_image = IOHandler.load_image(image_path=src_image_path, np_image=src_np_image)
101
- blurred = cv2.GaussianBlur(np_image, kernel_size, sigmaX=0)
109
+ blurred = cv2.GaussianBlur(np_image, kernel_size, 0)
110
+
102
111
  if output_image_path:
103
112
  print(IOHandler.save_image(blurred, output_image_path))
113
+
104
114
  return blurred
105
115
 
106
116
 
107
117
  def apply_median_blur(
108
- filter_size: int = 5,
118
+ filter_size: int = DEFAULT_FILTER_SIZE,
109
119
  src_image_path: str | None = None,
110
120
  src_np_image=None,
111
121
  output_image_path: str | None = None
@@ -143,30 +153,32 @@ def apply_median_blur(
143
153
 
144
154
  np_image = IOHandler.load_image(image_path=src_image_path, np_image=src_np_image)
145
155
  blurred = cv2.medianBlur(np_image, filter_size)
156
+
146
157
  if output_image_path:
147
158
  print(IOHandler.save_image(blurred, output_image_path))
159
+
148
160
  return blurred
149
161
 
150
162
 
151
163
  def apply_bilateral_blur(
152
164
  filter_size: int = 9,
153
- sigma_color: float = 75,
154
- sigma_space: float = 75,
165
+ sigma_color: float = DEFAULT_SIGMA_COLOR,
166
+ sigma_space: float = DEFAULT_SIGMA_SPACE,
155
167
  src_image_path: str | None = None,
156
168
  src_np_image=None,
157
169
  output_image_path: str | None = None
158
170
  ) -> np.ndarray:
159
171
  """
160
- Apply bilateral filter to smooth while preserving edges.
172
+ Apply bilateral blur to an image.
161
173
 
162
174
  Parameters
163
175
  ----------
164
176
  filter_size : int, default=9
165
- Diameter of pixel neighborhood.
177
+ Filter size, must be a positive integer.
166
178
  sigma_color : float, default=75
167
- Color-space standard deviation.
179
+ Color sigma, higher values mean more colors will be mixed.
168
180
  sigma_space : float, default=75
169
- Coordinate-space standard deviation.
181
+ Space sigma, higher values mean farther pixels will influence each other.
170
182
  src_image_path : str | None, optional
171
183
  Path to input image.
172
184
  src_np_image : np.ndarray | None, optional
@@ -182,9 +194,9 @@ def apply_bilateral_blur(
182
194
  Raises
183
195
  ------
184
196
  ValueError
185
- If parameters are invalid.
197
+ If filter size or sigma parameters are invalid.
186
198
  """
187
- if not isinstance(filter_size, int) or filter_size < 1:
199
+ if not isinstance(filter_size, int) or filter_size <= 0:
188
200
  raise ValueError("'filter_size' must be a positive integer.")
189
201
  if not isinstance(sigma_color, (int, float)) or sigma_color <= 0:
190
202
  raise ValueError("'sigma_color' must be a positive number.")
@@ -193,6 +205,8 @@ def apply_bilateral_blur(
193
205
 
194
206
  np_image = IOHandler.load_image(image_path=src_image_path, np_image=src_np_image)
195
207
  blurred = cv2.bilateralFilter(np_image, filter_size, sigma_color, sigma_space)
208
+
196
209
  if output_image_path:
197
210
  print(IOHandler.save_image(blurred, output_image_path))
211
+
198
212
  return blurred
@@ -10,10 +10,16 @@ sys.path.append(str(parent_dir))
10
10
  from pre_processing.grayscale import convert_to_grayscale
11
11
  from utils.io_handler import IOHandler
12
12
 
13
+ # Constants
14
+ DEFAULT_CLIP_LIMIT = 2.0
15
+ DEFAULT_TILE_GRID_SIZE = (8, 8)
16
+ DEFAULT_ALPHA = 1.5
17
+ DEFAULT_BETA = 10
18
+
13
19
 
14
20
  def apply_clahe_contrast(
15
- clip_limit: float = 2.0,
16
- tile_grid_size: tuple[int, int] = (8, 8),
21
+ clip_limit: float = DEFAULT_CLIP_LIMIT,
22
+ tile_grid_size: tuple[int, int] = DEFAULT_TILE_GRID_SIZE,
17
23
  src_image_path: str | None = None,
18
24
  src_np_image=None,
19
25
  output_image_path: str | None = None
@@ -8,6 +8,10 @@ sys.path.append(str(parent_dir))
8
8
 
9
9
  from utils.io_handler import IOHandler
10
10
 
11
+ # Constants
12
+ DEFAULT_START_POINT = (0, 0)
13
+ DEFAULT_END_POINT = (100, 100)
14
+
11
15
 
12
16
  def crop_image(
13
17
  start_point: tuple[int, int],
@@ -17,20 +17,28 @@ from rotate import rotate_image_custom
17
17
  from grayscale import convert_to_grayscale
18
18
  from resize import resize_image
19
19
 
20
+ # Constants
21
+ DEFAULT_NUM_IMAGES = 200
22
+ DEFAULT_START_INDEX = 0
23
+ DEFAULT_MIN_CONFIDENCE = 0.7
24
+ DEFAULT_CAMERA_INDEX = 0
25
+ DEFAULT_DELAY = 0.1
26
+ DEFAULT_FACE_ID = "unknown"
27
+
20
28
 
21
29
  def capture_bulk_pictures(
22
30
  folder_path: str | Path,
23
- face_id: str | int,
24
- num_images: int = 200,
25
- start_index: int = 0,
26
- min_confidence: float = 0.7,
27
- camera_index: int = 0,
31
+ face_id: str | int = DEFAULT_FACE_ID,
32
+ num_images: int = DEFAULT_NUM_IMAGES,
33
+ start_index: int = DEFAULT_START_INDEX,
34
+ min_confidence: float = DEFAULT_MIN_CONFIDENCE,
35
+ camera_index: int = DEFAULT_CAMERA_INDEX,
28
36
  apply_blur: bool = False,
29
37
  apply_grayscale: bool = False,
30
38
  apply_sharpen: bool = False,
31
39
  apply_rotate: bool = False,
32
40
  apply_resize: tuple = False,
33
- delay: float = 0.1,
41
+ delay: float = DEFAULT_DELAY,
34
42
  ) -> None:
35
43
  """
36
44
  Capture frames from webcam and save cropped face images, with optional preprocessing.
@@ -1,9 +1,9 @@
1
1
  import sys
2
2
  from pathlib import Path
3
- import numpy as np
4
3
  import cv2
4
+ import numpy as np
5
5
 
6
- # Add parent directory to sys.path for importing custom modules
6
+ # Add parent directory to sys.path for custom module imports
7
7
  parent_dir = Path(__file__).resolve().parent.parent
8
8
  sys.path.append(str(parent_dir))
9
9
 
@@ -12,20 +12,20 @@ from utils.io_handler import IOHandler
12
12
 
13
13
  def convert_to_grayscale(
14
14
  src_image_path: str | None = None,
15
- src_np_image: np.ndarray | None = None,
15
+ src_np_image=None,
16
16
  output_image_path: str | None = None
17
17
  ) -> np.ndarray:
18
18
  """
19
- Convert a BGR image to single-channel grayscale.
19
+ Convert an image to grayscale.
20
20
 
21
21
  Parameters
22
22
  ----------
23
23
  src_image_path : str | None, optional
24
- Path to the input image file.
24
+ Path to input image.
25
25
  src_np_image : np.ndarray | None, optional
26
- Preloaded BGR image. Used if `src_image_path` is None.
26
+ Preloaded BGR image array.
27
27
  output_image_path : str | None, optional
28
- Path to save the grayscale image.
28
+ If provided, save the grayscale image.
29
29
 
30
30
  Returns
31
31
  -------
@@ -37,13 +37,14 @@ def convert_to_grayscale(
37
37
  TypeError
38
38
  If input types are invalid.
39
39
  FileNotFoundError
40
- If the provided `src_image_path` does not exist.
40
+ If image path does not exist.
41
41
  IOError
42
42
  If saving the image fails.
43
43
  """
44
44
  np_image = IOHandler.load_image(image_path=src_image_path, np_image=src_np_image)
45
45
  grayscale = cv2.cvtColor(np_image, cv2.COLOR_BGR2GRAY)
46
-
46
+
47
47
  if output_image_path:
48
48
  print(IOHandler.save_image(grayscale, output_image_path))
49
+
49
50
  return grayscale
@@ -1,9 +1,9 @@
1
1
  import sys
2
2
  from pathlib import Path
3
- import numpy as np
4
3
  import cv2
4
+ import numpy as np
5
5
 
6
- # Add parent directory to sys.path for importing custom modules
6
+ # Add parent directory to sys.path for custom module imports
7
7
  parent_dir = Path(__file__).resolve().parent.parent
8
8
  sys.path.append(str(parent_dir))
9
9
 
@@ -13,22 +13,22 @@ from utils.io_handler import IOHandler
13
13
  def resize_image(
14
14
  new_size: tuple[int, int],
15
15
  src_image_path: str | None = None,
16
- src_np_image: np.ndarray | None = None,
16
+ src_np_image=None,
17
17
  output_image_path: str | None = None
18
18
  ) -> np.ndarray:
19
19
  """
20
- Resize an image to the specified dimensions.
20
+ Resize an image to new dimensions.
21
21
 
22
22
  Parameters
23
23
  ----------
24
24
  new_size : tuple[int, int]
25
- (width, height) in pixels, both must be positive integers.
25
+ New image size as (width, height).
26
26
  src_image_path : str | None, optional
27
- Path to the input image. Overrides `src_np_image` if provided.
27
+ Path to input image.
28
28
  src_np_image : np.ndarray | None, optional
29
- Preloaded image array, used if `src_image_path` is None.
29
+ Preloaded BGR image array.
30
30
  output_image_path : str | None, optional
31
- Path to save the resized image.
31
+ If provided, save the resized image.
32
32
 
33
33
  Returns
34
34
  -------
@@ -37,28 +37,26 @@ def resize_image(
37
37
 
38
38
  Raises
39
39
  ------
40
- TypeError
41
- If `new_size` is not a tuple of two integers.
42
40
  ValueError
43
- If width or height are not positive integers.
41
+ If new_size is invalid.
42
+ TypeError
43
+ If input types are invalid.
44
44
  FileNotFoundError
45
- If `src_image_path` does not exist.
45
+ If image path does not exist.
46
46
  IOError
47
47
  If saving the image fails.
48
48
  """
49
49
  if (
50
50
  not isinstance(new_size, tuple)
51
51
  or len(new_size) != 2
52
- or not all(isinstance(x, int) for x in new_size)
52
+ or not all(isinstance(dim, int) and dim > 0 for dim in new_size)
53
53
  ):
54
- raise TypeError("'new_size' must be a tuple of two integers: (width, height).")
55
-
56
- if new_size[0] <= 0 or new_size[1] <= 0:
57
- raise ValueError("Both width and height must be positive integers.")
54
+ raise ValueError("'new_size' must be a tuple of two positive integers.")
58
55
 
59
56
  np_image = IOHandler.load_image(image_path=src_image_path, np_image=src_np_image)
60
- resized = cv2.resize(np_image, dsize=new_size)
61
-
57
+ resized = cv2.resize(np_image, new_size, interpolation=cv2.INTER_LINEAR)
58
+
62
59
  if output_image_path:
63
60
  print(IOHandler.save_image(resized, output_image_path))
61
+
64
62
  return resized
@@ -9,6 +9,10 @@ sys.path.append(str(parent_dir))
9
9
 
10
10
  from utils.io_handler import IOHandler
11
11
 
12
+ # Constants
13
+ DEFAULT_SCALE = 1.0
14
+ DEFAULT_ANGLE = 45.0
15
+
12
16
 
13
17
  def rotate_image_90(
14
18
  src_image_path: str | None = None,
@@ -67,7 +71,7 @@ def rotate_image_270(
67
71
 
68
72
  def rotate_image_custom(
69
73
  angle: float,
70
- scale: float = 1.0,
74
+ scale: float = DEFAULT_SCALE,
71
75
  src_image_path: str | None = None,
72
76
  src_np_image: np.ndarray | None = None,
73
77
  output_image_path: str | None = None
@@ -10,9 +10,13 @@ sys.path.append(str(parent_dir))
10
10
  from utils.io_handler import IOHandler
11
11
  from pre_processing.blur import apply_average_blur
12
12
 
13
+ # Constants
14
+ DEFAULT_LAPLACIAN_COEFFICIENT = 3.0
15
+ DEFAULT_UNSHARP_COEFFICIENT = 1.0
16
+
13
17
 
14
18
  def apply_laplacian_sharpening(
15
- coefficient: float = 3.0,
19
+ coefficient: float = DEFAULT_LAPLACIAN_COEFFICIENT,
16
20
  src_image_path: str | None = None,
17
21
  src_np_image: np.ndarray | None = None,
18
22
  output_image_path: str | None = None
@@ -52,7 +56,7 @@ def apply_laplacian_sharpening(
52
56
 
53
57
 
54
58
  def apply_unsharp_masking(
55
- coefficient: float = 1.0,
59
+ coefficient: float = DEFAULT_UNSHARP_COEFFICIENT,
56
60
  src_image_path: str | None = None,
57
61
  src_np_image: np.ndarray | None = None,
58
62
  output_image_path: str | None = None
@@ -0,0 +1,6 @@
1
+ # Utils Module
2
+ # Provides shared utilities for image I/O operations and data handling
3
+
4
+ from .io_handler import IOHandler
5
+
6
+ __all__ = ["IOHandler"]
@@ -0,0 +1,30 @@
1
+ Metadata-Version: 2.4
2
+ Name: ImagePRO-Python
3
+ Version: 0.5.2
4
+ Summary: Professional & modular image processing library with OpenCV, MediaPipe, and YOLO integration.
5
+ Author-email: Parsa Safaie <parsasafaie.2568@proton.me>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/parsasafaie/ImagePRO
8
+ Project-URL: Repository, https://github.com/parsasafaie/ImagePRO.git
9
+ Project-URL: Documentation, https://github.com/parsasafaie/ImagePRO#readme
10
+ Project-URL: Issues, https://github.com/parsasafaie/ImagePRO/issues
11
+ Keywords: opencv,mediapipe,computer-vision,face,pose,yolo,image-processing
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: License :: OSI Approved :: MIT License
18
+ Classifier: Operating System :: OS Independent
19
+ Classifier: Topic :: Scientific/Engineering :: Image Processing
20
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Requires-Python: ==3.10.*
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: numpy<3.0,>=1.24
26
+ Requires-Dist: opencv-python<5.0,>=4.8
27
+ Requires-Dist: ultralytics<9.0,>=8.2.0
28
+ Requires-Dist: mediapipe<1.0,>=0.10.0
29
+ Requires-Dist: insightface<1.0,>=0.7
30
+ Dynamic: license-file
@@ -0,0 +1,29 @@
1
+ ImagePRO/__init__.py,sha256=WLaJEr5remdE8_84-TZ7gQbdv8G2qB5iXd-fkLK3zps,998
2
+ ImagePRO/human_analysis/__init__.py,sha256=uSU0lM1p1HM6TNGv6u0nPHWy9QY505v43lqTkhClddM,190
3
+ ImagePRO/human_analysis/body_analysis/__init__.py,sha256=czQoJJIrDAWz0UUY0h0mwxymSQ6L6CaZYYHhYFHyf4U,203
4
+ ImagePRO/human_analysis/body_analysis/body_pose_estimation.py,sha256=SNuZ_fMhOhCq3PhHL4snCob0uozqkYz18tPlV2lZlJs,4307
5
+ ImagePRO/human_analysis/body_analysis/hand_tracking.py,sha256=Qym-YK4ixgILk74ikX6D5YHQdOXErLG2OsaJF_w8P_4,5524
6
+ ImagePRO/human_analysis/face_analysis/__init__.py,sha256=dKVZ6pq-0aQHL9vhMSt0BHs3WV_cTW65QPLJGnSiUgM,405
7
+ ImagePRO/human_analysis/face_analysis/eye_status_analysis.py,sha256=ZbuBj2qkyUUBcUp-RSHquNwQU7Ntm0Go4jhAd-HkPLw,5739
8
+ ImagePRO/human_analysis/face_analysis/face_comparison.py,sha256=dOi0MC6vkYMGo-44yQII9YoNEHYnSHK_j7lK6Gheu24,2180
9
+ ImagePRO/human_analysis/face_analysis/face_detection.py,sha256=cPSytFmzUv8u-tNRxqaJ696Lucz5g6pt4EFqxHKprsQ,4146
10
+ ImagePRO/human_analysis/face_analysis/face_mesh_analysis.py,sha256=zr_eBQDggsVkDWfaJdckJra24YnY3uyWviYv0MUGlKo,8533
11
+ ImagePRO/human_analysis/face_analysis/head_pose_estimation.py,sha256=nPvAH21zuLQyzvqkq7UUl3ec_bx6oR94AwE8JtgqUmo,5903
12
+ ImagePRO/object_analysis/__init__.py,sha256=pj1vjY8uVUqeVONpaCacWufUzHF7rS5-nmy_C5IfI2w,148
13
+ ImagePRO/object_analysis/object_detection.py,sha256=PiweREsa9HOzW5DTUi1sVohfErm2QYROlRmes7UUaKg,3555
14
+ ImagePRO/pre_processing/__init__.py,sha256=nXUhE8RnDyW7T93fKsSDPfqzGHIW50OvgQvznY5UH0E,417
15
+ ImagePRO/pre_processing/blur.py,sha256=MXA2m-mB36A1OtmJEunZmFu_Q-cfRhvHdZj0tA9sc9A,6208
16
+ ImagePRO/pre_processing/contrast.py,sha256=nhFUkXEOT6rXhubkWouu3yJY5ShdE4OZVWSgUqNgmvo,4480
17
+ ImagePRO/pre_processing/crop.py,sha256=0PbKhgHyxwbCiP5ODyrTRKQca2hWt1O90_up7QpqLAE,2424
18
+ ImagePRO/pre_processing/dataset_generator.py,sha256=k5MSO4WJfJe4V5crITXleZG4IXwtz1SW-iFgxAW4xDI,6308
19
+ ImagePRO/pre_processing/grayscale.py,sha256=49xi9z2Wsa6MFXZDpNymIRY9wDnkLJZs70IWQJcdK3k,1241
20
+ ImagePRO/pre_processing/resize.py,sha256=-lQINmrINSqywlsPQfDwIVyZJ4qVDT0p_6H-wl-E22w,1640
21
+ ImagePRO/pre_processing/rotate.py,sha256=6poUFHAFGxJJP4wI9V2pl6MA7cVQnJhnIxLMMrIoPVw,3608
22
+ ImagePRO/pre_processing/sharpen.py,sha256=TJLx0lMnFkJwxaz0BqSbEsKwa4EakdbBYku7yQNT22E,2841
23
+ ImagePRO/utils/__init__.py,sha256=F3UA7o2Ai3o4PedPrP9yWtPgv0gipiojHHpioRWPKyM,146
24
+ ImagePRO/utils/io_handler.py,sha256=lWc_UzoihbzZ7sObCFK7KXCOhsp00V6KUoMVpV-6tSs,6059
25
+ imagepro_python-0.5.2.dist-info/licenses/LICENSE,sha256=sehkHN7dbe5umrINZJyJjIf9VTemZSgTfJlq6iIsbJQ,1069
26
+ imagepro_python-0.5.2.dist-info/METADATA,sha256=xByO7dTlPdXAuHiNwRvPkgoLr6TNnmlkqjKEiw_Cj3E,1418
27
+ imagepro_python-0.5.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
28
+ imagepro_python-0.5.2.dist-info/top_level.txt,sha256=UOuPzsoWrVKXgUupOSI96shJ6wE8Fhz-8bm8oMlLC3s,9
29
+ imagepro_python-0.5.2.dist-info/RECORD,,
@@ -1,20 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: ImagePRO-Python
3
- Version: 0.5.1
4
- Summary: clean, modular, and easy-to-use Python library for image processing tasks.
5
- Author-email: Parsa Safaie <parsasafaie.2568@proton.me>
6
- License: MIT
7
- Keywords: opencv,mediapipe,computer-vision,face,pose
8
- Classifier: Programming Language :: Python :: 3
9
- Classifier: License :: OSI Approved :: MIT License
10
- Classifier: Operating System :: OS Independent
11
- Classifier: Topic :: Scientific/Engineering :: Image Processing
12
- Requires-Python: ==3.10.*
13
- Description-Content-Type: text/markdown
14
- License-File: LICENSE
15
- Requires-Dist: numpy<3.0,>=1.24
16
- Requires-Dist: opencv-python<5.0,>=4.8
17
- Requires-Dist: ultralytics<9.0,>=8.2.0
18
- Requires-Dist: mediapipe<1.0,>=0.10.0
19
- Requires-Dist: insightface<1.0,>=0.7
20
- Dynamic: license-file
@@ -1,28 +0,0 @@
1
- ImagePRO/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- ImagePRO/human_analysis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- ImagePRO/human_analysis/body_analysis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- ImagePRO/human_analysis/body_analysis/body_pose_estimation.py,sha256=CXyJSyafARKTguMwThqIsd4xCdwb0rOwQM0pFVQx_oA,4099
5
- ImagePRO/human_analysis/body_analysis/hand_tracking.py,sha256=wVzW0soB3V1mLxF27oG27--vdpIuG1F1aVzhTtD2MGI,5220
6
- ImagePRO/human_analysis/face_analysis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- ImagePRO/human_analysis/face_analysis/eye_status_analysis.py,sha256=yzxzcniyVrTtlU2aADOx8IC2BMUYi2i7HfssPG-LfV4,5574
8
- ImagePRO/human_analysis/face_analysis/face_comparison.py,sha256=xdfLN7tljEO9YpnXI9MpR1Jvu4DuhOFDrSG6KR6UxbY,2030
9
- ImagePRO/human_analysis/face_analysis/face_detection.py,sha256=qob4dIVGZPZRDMy7_wS3LYWpaUNe7Q-P2_9IENrbc2E,4019
10
- ImagePRO/human_analysis/face_analysis/face_mesh_analysis.py,sha256=LjplQXxPpOzK0VdD_f73Be40PvSEG-T22_DFl4TvMKc,8356
11
- ImagePRO/human_analysis/face_analysis/head_pose_estimation.py,sha256=gRYRfW-sqZG1R1qeAH4S0rVMGZWS8ABosldfMhBbklI,5767
12
- ImagePRO/object_analysis/object_detection.py,sha256=PiMwZktfZDk6XftEFBmiwDZ4M0v-dcGrgf6w-JWo8n8,3482
13
- ImagePRO/pre_processing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
- ImagePRO/pre_processing/blur.py,sha256=JqkM0cLfRrBlQEixkC-iuhu6rR62VPMA2KObzmcmt_Q,5909
15
- ImagePRO/pre_processing/contrast.py,sha256=00qp_BZ8-t1TqLE-bTWcLFS5bMCeAXTT7cNnADHUR3w,4341
16
- ImagePRO/pre_processing/crop.py,sha256=a5tF5nDOekCA-SqJqddYXzJo7PN2DZpcdIJsObpZBmA,2351
17
- ImagePRO/pre_processing/dataset_generator.py,sha256=DmcCfOPUbrkJUIltH5Zbv6C2gkAe5yT4JvihgVQg51E,6045
18
- ImagePRO/pre_processing/grayscale.py,sha256=PtdONZPmLzZpj7YpeBA9D_pYcVNTmOZPNJasDpeO9Yo,1325
19
- ImagePRO/pre_processing/resize.py,sha256=1ceEKZ7bHJK9a07QEzfEd6H3oqNT2yL5PWKI0HXmIkE,1890
20
- ImagePRO/pre_processing/rotate.py,sha256=tBNkiSZFpMPOjlQFQw9dR1y1zuT0Owqd4iBIRVEBrYs,3544
21
- ImagePRO/pre_processing/sharpen.py,sha256=CneU-avwfRsWRUU-COmAtpfWlMQgCN1WVp3hd96YJmc,2708
22
- ImagePRO/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
- ImagePRO/utils/io_handler.py,sha256=lWc_UzoihbzZ7sObCFK7KXCOhsp00V6KUoMVpV-6tSs,6059
24
- imagepro_python-0.5.1.dist-info/licenses/LICENSE,sha256=sehkHN7dbe5umrINZJyJjIf9VTemZSgTfJlq6iIsbJQ,1069
25
- imagepro_python-0.5.1.dist-info/METADATA,sha256=9f7vgjdNd-k7Qi6LMqTlWxOve-Rq7PgStxOoeaGM9V4,770
26
- imagepro_python-0.5.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
27
- imagepro_python-0.5.1.dist-info/top_level.txt,sha256=UOuPzsoWrVKXgUupOSI96shJ6wE8Fhz-8bm8oMlLC3s,9
28
- imagepro_python-0.5.1.dist-info/RECORD,,