openvisionkit 0.4.0__tar.gz → 0.5.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.
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/.gitignore +3 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/.pre-commit-config.yaml +1 -1
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/PKG-INFO +1 -1
- openvisionkit-0.5.1/openvisionkit/__init__.py +1 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/openvisionkit/lib/classifier.py +2 -1
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/openvisionkit/lib/face_mesh_detector.py +0 -2
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/openvisionkit/lib/hand_detector.py +2 -1
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/openvisionkit/lib/image_detector.py +1 -39
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/openvisionkit/lib/selfie_segmentation.py +0 -2
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/openvisionkit/lib/text_detector.py +6 -14
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/openvisionkit/utility/vision_utilis.py +1 -1
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/pyproject.toml +5 -2
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/uv.lock +1 -1
- openvisionkit-0.4.0/docs/superpowers/plans/2026-06-09-visionkit-utility-methods.md +0 -2633
- openvisionkit-0.4.0/docs/superpowers/specs/2026-06-09-visionkit-utility-methods-design.md +0 -229
- openvisionkit-0.4.0/openvisionkit/__init__.py +0 -1
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/.flake8 +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/.gitattributes +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/.github/workflows/ci-integration.yml +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/.github/workflows/ci-security.yml +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/.github/workflows/ci-unit.yml +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/.github/workflows/publish.yml +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/.github/workflows/renovate.yml +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/.github/workflows/reusable-github-release.yml +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/.github/workflows/semantic-versioning.yml +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/.python-version +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/CLAUDE.md +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/Makefile +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/README.md +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/main.py +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/openvisionkit/_version.py +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/openvisionkit/capture/draw_object.py +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/openvisionkit/capture/image_template.py +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/openvisionkit/capture/screen_capture.py +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/openvisionkit/capture/video_recorder.py +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/openvisionkit/capture/video_template.py +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/openvisionkit/lib/face_detector.py +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/openvisionkit/lib/form_detector.py +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/openvisionkit/lib/form_roi_annotator.py +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/openvisionkit/lib/form_roi_detector.py +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/openvisionkit/lib/fps_counter.py +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/openvisionkit/lib/hair_segmentation.py +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/openvisionkit/lib/object_detector.py +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/openvisionkit/lib/pose_detector.py +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/openvisionkit/utility/live_plot.py +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/renovate.json +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/tests/__init__.py +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/tests/capture/__init__.py +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/tests/capture/test_video_capture_template.py +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/tests/conftest.py +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/tests/lib/__init__.py +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/tests/lib/test_face_detector.py +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/tests/lib/test_face_mesh_detector.py +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/tests/lib/test_form_roi_annotator.py +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/tests/lib/test_form_roi_detector.py +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/tests/lib/test_hair_segmentation.py +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/tests/lib/test_hand_detector.py +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/tests/lib/test_image_detector.py +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/tests/lib/test_object_detector.py +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/tests/lib/test_pose_detector.py +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/tests/lib/test_selfie_segmentation.py +0 -0
- {openvisionkit-0.4.0 → openvisionkit-0.5.1}/tests/lib/test_text_detector.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.5.1"
|
|
@@ -4,6 +4,7 @@ Works well with TensorFlow 2.15 / 2.16 on Apple Silicon
|
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
6
|
import os
|
|
7
|
+
import sys
|
|
7
8
|
|
|
8
9
|
import cv2
|
|
9
10
|
import numpy as np
|
|
@@ -163,7 +164,7 @@ if __name__ == "__main__":
|
|
|
163
164
|
cap = cv2.VideoCapture(0)
|
|
164
165
|
if not cap.isOpened():
|
|
165
166
|
print("Camera not opened. Try changing to cv2.VideoCapture(1)")
|
|
166
|
-
exit()
|
|
167
|
+
sys.exit(1)
|
|
167
168
|
|
|
168
169
|
print("Press 'q' to quit")
|
|
169
170
|
|
|
@@ -363,7 +363,7 @@ class HandDetector:
|
|
|
363
363
|
p1 = (lm1.x, lm1.y)
|
|
364
364
|
p2 = (lm2.x, lm2.y)
|
|
365
365
|
|
|
366
|
-
distance = math.
|
|
366
|
+
distance = math.hypot(p1[0] - p2[0], p1[1] - p2[1])
|
|
367
367
|
|
|
368
368
|
if return_points:
|
|
369
369
|
return distance, p1, p2
|
|
@@ -461,6 +461,7 @@ class HandDetector:
|
|
|
461
461
|
# return ((p1[0] - p2[0])**2 + (p1[1] - p2[1])**2) ** 0.5
|
|
462
462
|
return float(np.linalg.norm(np.array(p1) - np.array(p2)))
|
|
463
463
|
|
|
464
|
+
@staticmethod
|
|
464
465
|
def compute_real_palm_width(pixel_width, distance_cm, focal_length_px):
|
|
465
466
|
"""
|
|
466
467
|
Compute the real palm width in centimeters based on the detected palm width in pixels, the known distance from the camera to the hand, and the focal length of the camera in pixels.
|
|
@@ -90,10 +90,6 @@ class ImageDetector:
|
|
|
90
90
|
print("Feature detection failed → using SSIM fallback")
|
|
91
91
|
return self.fallback_ssim(self.image, image2, form_name)
|
|
92
92
|
|
|
93
|
-
# Safety check
|
|
94
|
-
if descriptors1 is None or descriptors2 is None:
|
|
95
|
-
raise ValueError("Descriptors could not be computed")
|
|
96
|
-
|
|
97
93
|
# Use KNN matcher instead of crossCheck
|
|
98
94
|
bf = cv2.BFMatcher(cv2.NORM_HAMMING)
|
|
99
95
|
|
|
@@ -189,10 +185,6 @@ class ImageDetector:
|
|
|
189
185
|
print("Feature detection failed → using SSIM fallback")
|
|
190
186
|
return self.fallback_ssim(self.image, image2, form_name)
|
|
191
187
|
|
|
192
|
-
# Safety check
|
|
193
|
-
if descriptors1 is None or descriptors2 is None:
|
|
194
|
-
raise ValueError("Descriptors could not be computed")
|
|
195
|
-
|
|
196
188
|
# Use KNN matcher instead of crossCheck
|
|
197
189
|
bf = cv2.BFMatcher(cv2.NORM_HAMMING)
|
|
198
190
|
|
|
@@ -426,37 +418,6 @@ class ImageDetector:
|
|
|
426
418
|
]
|
|
427
419
|
return filtered + predefined
|
|
428
420
|
|
|
429
|
-
# def get_dominant_hsv_colors(self, k=4):
|
|
430
|
-
# """
|
|
431
|
-
# auto-detect highlight colors in the image by clustering pixel colors in HSV space using K-means.
|
|
432
|
-
# Get dominant HSV colors from the image using K-means clustering.
|
|
433
|
-
|
|
434
|
-
# Args:
|
|
435
|
-
# k: Number of dominant colors to detect (default is 4)
|
|
436
|
-
|
|
437
|
-
# Returns:
|
|
438
|
-
# List of dominant HSV color tuples (h, s, v) detected in the image.
|
|
439
|
-
# Usage:
|
|
440
|
-
|
|
441
|
-
# """
|
|
442
|
-
# mg_blur = cv2.GaussianBlur(self.image, (5,5), 0)
|
|
443
|
-
# hsv = cv2.cvtColor(mg_blur, cv2.COLOR_BGR2HSV)
|
|
444
|
-
# pixels = hsv.reshape(-1, 3).astype(np.float32)
|
|
445
|
-
|
|
446
|
-
# _, labels, centers = cv2.kmeans(
|
|
447
|
-
# pixels, k, None,
|
|
448
|
-
# (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 0.2),
|
|
449
|
-
# 10,
|
|
450
|
-
# cv2.KMEANS_RANDOM_CENTERS
|
|
451
|
-
# )
|
|
452
|
-
# # Filter likely highlight colors
|
|
453
|
-
# highlight_colors = []
|
|
454
|
-
# for (h, s, v) in centers:
|
|
455
|
-
# if s > 80 and v > 150: # high saturation + brightness
|
|
456
|
-
# highlight_colors.append((int(h), int(s), int(v)))
|
|
457
|
-
|
|
458
|
-
# return highlight_colors
|
|
459
|
-
|
|
460
421
|
def detect_single_highlighted_text(self, image, hsv_colors=None):
|
|
461
422
|
"""Detect highlighted text based on a single HSV color.
|
|
462
423
|
Args:
|
|
@@ -747,6 +708,7 @@ class ImageDetector:
|
|
|
747
708
|
contours = sorted(contours, key=cv2.contourArea, reverse=True)
|
|
748
709
|
return contours
|
|
749
710
|
|
|
711
|
+
@staticmethod
|
|
750
712
|
def export_measurements(data, path="measurements.json"):
|
|
751
713
|
with open(path, "w") as f:
|
|
752
714
|
json.dump(data, f, indent=2)
|
|
@@ -69,7 +69,6 @@ class SelfieSegmentation:
|
|
|
69
69
|
# Blur background
|
|
70
70
|
def blur_background(self, image: np.ndarray, blur_strength=(55, 55)) -> np.ndarray:
|
|
71
71
|
result = self.process(image)
|
|
72
|
-
category_mask = result.category_mask.numpy_view()
|
|
73
72
|
blurred = cv2.GaussianBlur(image, blur_strength, 0)
|
|
74
73
|
category_mask = np.squeeze(result.category_mask.numpy_view())
|
|
75
74
|
condition = (category_mask > 0.5)[..., None]
|
|
@@ -79,7 +78,6 @@ class SelfieSegmentation:
|
|
|
79
78
|
# Replace background
|
|
80
79
|
def replace_background(self, image: np.ndarray, background_path: str) -> np.ndarray:
|
|
81
80
|
result = self.process(image)
|
|
82
|
-
category_mask = result.category_mask.numpy_view()
|
|
83
81
|
bg = cv2.imread(background_path)
|
|
84
82
|
bg = cv2.resize(bg, (image.shape[1], image.shape[0]))
|
|
85
83
|
category_mask = np.squeeze(result.category_mask.numpy_view())
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import warnings
|
|
1
2
|
from typing import Any
|
|
2
3
|
|
|
3
4
|
import cv2
|
|
@@ -69,8 +70,9 @@ try:
|
|
|
69
70
|
|
|
70
71
|
NLP = spacy.load("en_core_web_sm")
|
|
71
72
|
except Exception as e:
|
|
72
|
-
|
|
73
|
-
f"
|
|
73
|
+
warnings.warn(
|
|
74
|
+
f"spaCy not found or failed to load. Entity extraction will be unavailable. Error: {e}",
|
|
75
|
+
stacklevel=1,
|
|
74
76
|
)
|
|
75
77
|
NLP = None
|
|
76
78
|
|
|
@@ -195,7 +197,7 @@ class TextDetector:
|
|
|
195
197
|
|
|
196
198
|
bounding_boxes = pytesseract.image_to_boxes(self.image, config=self.config)
|
|
197
199
|
|
|
198
|
-
|
|
200
|
+
_ = self.original_image.shape[:2]
|
|
199
201
|
|
|
200
202
|
# 3. DRAWING
|
|
201
203
|
for line in bounding_boxes.splitlines():
|
|
@@ -580,6 +582,7 @@ class TextDetector:
|
|
|
580
582
|
|
|
581
583
|
return None
|
|
582
584
|
|
|
585
|
+
@staticmethod
|
|
583
586
|
def fallback_ssim(image1, image2, form_name, draw_frame=False):
|
|
584
587
|
image2_resized = cv2.resize(image2, (image1.shape[1], image1.shape[0]))
|
|
585
588
|
|
|
@@ -626,10 +629,6 @@ class TextDetector:
|
|
|
626
629
|
print("Feature detection failed → using SSIM fallback")
|
|
627
630
|
return self.fallback_ssim(self.image, image2, form_name)
|
|
628
631
|
|
|
629
|
-
# Safety check
|
|
630
|
-
if descriptors1 is None or descriptors2 is None:
|
|
631
|
-
raise ValueError("Descriptors could not be computed")
|
|
632
|
-
|
|
633
632
|
# Use KNN matcher instead of crossCheck
|
|
634
633
|
bf = cv2.BFMatcher(cv2.NORM_HAMMING)
|
|
635
634
|
|
|
@@ -725,10 +724,6 @@ class TextDetector:
|
|
|
725
724
|
print("Feature detection failed → using SSIM fallback")
|
|
726
725
|
return self.fallback_ssim(self.image, image2, form_name)
|
|
727
726
|
|
|
728
|
-
# Safety check
|
|
729
|
-
if descriptors1 is None or descriptors2 is None:
|
|
730
|
-
raise ValueError("Descriptors could not be computed")
|
|
731
|
-
|
|
732
727
|
# Use KNN matcher instead of crossCheck
|
|
733
728
|
bf = cv2.BFMatcher(cv2.NORM_HAMMING)
|
|
734
729
|
|
|
@@ -1221,9 +1216,6 @@ class TextDetector:
|
|
|
1221
1216
|
return "unknown"
|
|
1222
1217
|
return detect(text)
|
|
1223
1218
|
except ImportError:
|
|
1224
|
-
import warnings
|
|
1225
|
-
|
|
1226
|
-
warnings.warn("langdetect not installed; returning 'unknown'", stacklevel=2)
|
|
1227
1219
|
return "unknown"
|
|
1228
1220
|
except Exception:
|
|
1229
1221
|
return "unknown"
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "openvisionkit"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.5.1"
|
|
8
8
|
description = "MediaPipe Tasks API wrapper for Python computer vision"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "MIT" }
|
|
@@ -61,7 +61,7 @@ packages = ["openvisionkit"]
|
|
|
61
61
|
# ── Commitizen ─────────────────────────────────────────────────────────────────
|
|
62
62
|
[tool.commitizen]
|
|
63
63
|
name = "cz_conventional_commits"
|
|
64
|
-
version = "0.
|
|
64
|
+
version = "0.5.1"
|
|
65
65
|
version_scheme = "semver"
|
|
66
66
|
version_provider = "commitizen"
|
|
67
67
|
tag_format = "v$version"
|
|
@@ -85,6 +85,9 @@ markers = [
|
|
|
85
85
|
"slow: tests that take > 5 s",
|
|
86
86
|
]
|
|
87
87
|
addopts = "-ra -q"
|
|
88
|
+
filterwarnings = [
|
|
89
|
+
"ignore:spaCy not found or failed to load:UserWarning",
|
|
90
|
+
]
|
|
88
91
|
|
|
89
92
|
[tool.ruff]
|
|
90
93
|
line-length = 88
|