viso-sdk-python 1.1.18__tar.gz → 1.1.19__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.
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/CHANGELOG.md +5 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/PKG-INFO +1 -1
- viso_sdk_python-1.1.19/tests/unit/test_object.py +189 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/tests/unit/test_viso_data.py +23 -4
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/_version.c +7 -7
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/_version.py +1 -1
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/redis/viso_data.c +72 -46
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/redis/viso_data.py +1 -1
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk_python.egg-info/PKG-INFO +1 -1
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk_python.egg-info/SOURCES.txt +1 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/AUTHORS +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/COPYING +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/MANIFEST.in +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/README.md +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/docs/Makefile +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/docs/__init__.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/docs/conf.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/docs/ext/__init__.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/docs/ext/docstrings.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/docs/ext/manager_tmpl.j2 +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/docs/index.rst +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/docs/make.bat +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/docs/source/modules.rst +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/docs/source/viso_sdk._version.rst +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/docs/source/viso_sdk.constants.constants.rst +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/docs/source/viso_sdk.constants.modules.rst +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/docs/source/viso_sdk.constants.rst +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/docs/source/viso_sdk.constants.variables.rst +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/docs/source/viso_sdk.edge.common.rst +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/docs/source/viso_sdk.edge.rst +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/docs/source/viso_sdk.logging.logger.rst +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/docs/source/viso_sdk.logging.rst +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/docs/source/viso_sdk.model.download.rst +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/docs/source/viso_sdk.model.rst +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/docs/source/viso_sdk.mqtt.mqtt_wrapper.rst +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/docs/source/viso_sdk.mqtt.rst +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/docs/source/viso_sdk.mqtt.utils.rst +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/docs/source/viso_sdk.nodered.flow.rst +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/docs/source/viso_sdk.nodered.rst +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/docs/source/viso_sdk.redis.redis_wrapper.rst +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/docs/source/viso_sdk.redis.rst +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/docs/source/viso_sdk.rst +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/docs/source/viso_sdk.status.rst +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/docs/source/viso_sdk.status.status_logger.rst +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/pyproject.toml +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/requirements-dev.txt +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/requirements-docker.txt +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/requirements-docs.txt +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/requirements-lint.txt +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/requirements-test.txt +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/requirements.txt +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/setup.cfg +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/setup.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/tests/__init__.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/tests/conftest.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/tests/fixtures/flow.json +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/tests/integration/__init__.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/tests/integration/test_status.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/tests/meta/__init__.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/tests/meta/test_ensure_type_hints.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/tests/smoke/__init__.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/tests/smoke/test_dists.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/tests/unit/__init__.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/tests/unit/test_flow.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/tests/unit/test_logger.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/tests/unit/test_model_fetch.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/tests/unit/test_nms.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/tests/unit/test_redis_utils.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/tests/unit/test_redis_wrapper.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/tests/unit/test_stream_cleanup.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/tests/unit/test_trace_malloc.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/tox.ini +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/__init__.c +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/__init__.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/constants/__init__.c +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/constants/__init__.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/constants/constants.c +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/constants/constants.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/constants/modules.c +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/constants/modules.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/constants/variables.c +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/constants/variables.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/debug/__init__.c +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/debug/__init__.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/debug/trace_malloc.c +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/debug/trace_malloc.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/detection/__init__.c +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/detection/__init__.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/detection/model_utils.c +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/detection/model_utils.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/detection/nms.c +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/detection/nms.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/detection/object.c +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/detection/object.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/edge/__init__.c +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/edge/__init__.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/edge/common.c +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/edge/common.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/logging/__init__.c +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/logging/__init__.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/logging/log_id.c +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/logging/log_id.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/logging/logger.c +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/logging/logger.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/model/__init__.c +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/model/__init__.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/model/fetch.c +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/model/fetch.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/mqtt/__init__.c +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/mqtt/__init__.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/mqtt/mqtt_wrapper.c +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/mqtt/mqtt_wrapper.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/mqtt/utils.c +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/mqtt/utils.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/nodered/__init__.c +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/nodered/__init__.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/nodered/flow.c +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/nodered/flow.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/py.typed +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/redis/__init__.c +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/redis/__init__.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/redis/redis_wrapper.c +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/redis/redis_wrapper.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/redis/stream_cleanup.c +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/redis/stream_cleanup.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/redis/utils.c +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/redis/utils.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/roi/__init__.c +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/roi/__init__.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/roi/polygon_roi_manager.c +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/roi/polygon_roi_manager.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/status/__init__.c +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/status/__init__.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/status/status_logger.c +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/status/status_logger.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/structures/__init__.c +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/structures/__init__.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/structures/rollingq.c +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk/structures/rollingq.py +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk_python.egg-info/dependency_links.txt +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk_python.egg-info/requires.txt +0 -0
- {viso_sdk_python-1.1.18 → viso_sdk_python-1.1.19}/viso_sdk_python.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
"""Unit tests for Detection class and object detection utilities."""
|
|
2
|
+
import numpy as np
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from viso_sdk.detection.object import Detection, filter_iou_threshold, filter_labels
|
|
6
|
+
from viso_sdk.constants import KEY
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class TestDetectionInit:
|
|
10
|
+
def test_init_with_direct_params(self):
|
|
11
|
+
det = Detection(class_id=1, label="car", score=0.95, tlwh=[0.1, 0.2, 0.3, 0.4])
|
|
12
|
+
assert det.class_id == 1
|
|
13
|
+
assert det.label == "car"
|
|
14
|
+
assert det.score == 0.95
|
|
15
|
+
assert np.allclose(det.tlwh, [0.1, 0.2, 0.3, 0.4])
|
|
16
|
+
|
|
17
|
+
def test_init_with_dict(self):
|
|
18
|
+
det_dict = {
|
|
19
|
+
KEY.CLASS_ID: 2,
|
|
20
|
+
KEY.LABEL: "person",
|
|
21
|
+
KEY.SCORE: 0.88,
|
|
22
|
+
KEY.TLWH: [0.2, 0.3, 0.4, 0.5],
|
|
23
|
+
}
|
|
24
|
+
det = Detection(det=det_dict)
|
|
25
|
+
assert det.class_id == 2
|
|
26
|
+
assert det.label == "person"
|
|
27
|
+
assert det.score == 0.88
|
|
28
|
+
assert np.allclose(det.tlwh, [0.2, 0.3, 0.4, 0.5])
|
|
29
|
+
|
|
30
|
+
def test_init_with_roi_id_and_name(self):
|
|
31
|
+
det = Detection(class_id=1, label="car", score=0.9, tlwh=[0.1, 0.2, 0.3, 0.4],
|
|
32
|
+
roi_id=[1, 2], roi_name=["zone_a", "zone_b"])
|
|
33
|
+
assert det.roi_id == [1, 2]
|
|
34
|
+
assert det.roi_name == ["zone_a", "zone_b"]
|
|
35
|
+
|
|
36
|
+
def test_init_converts_single_roi_to_list(self):
|
|
37
|
+
det = Detection(class_id=1, label="car", score=0.9, tlwh=[0.1, 0.2, 0.3, 0.4],
|
|
38
|
+
roi_id=5, roi_name="parking")
|
|
39
|
+
assert det.roi_id == [5]
|
|
40
|
+
assert det.roi_name == ["parking"]
|
|
41
|
+
|
|
42
|
+
def test_init_defaults_none_roi_to_empty_list(self):
|
|
43
|
+
det = Detection(class_id=1, label="car", score=0.9, tlwh=[0.1, 0.2, 0.3, 0.4])
|
|
44
|
+
assert det.roi_id == []
|
|
45
|
+
assert det.roi_name == []
|
|
46
|
+
|
|
47
|
+
def test_init_with_default_values(self):
|
|
48
|
+
det = Detection(tlwh=[0.1, 0.2, 0.3, 0.4])
|
|
49
|
+
assert det.class_id == -1
|
|
50
|
+
assert det.label == ""
|
|
51
|
+
assert det.score == 0.0
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class TestDetectionCoordinateConversion:
|
|
55
|
+
def test_normalized_coordinates_stay_normalized(self):
|
|
56
|
+
# When tlwh has values < 1.0, treat as normalized
|
|
57
|
+
det = Detection(class_id=1, label="car", score=0.9, tlwh=[0.1, 0.2, 0.3, 0.4])
|
|
58
|
+
assert np.allclose(det.tlwh, [0.1, 0.2, 0.3, 0.4])
|
|
59
|
+
|
|
60
|
+
def test_pixel_coordinates_converted_to_normalized(self):
|
|
61
|
+
# When tlwh has values >= 1.0, treat as pixels and normalize
|
|
62
|
+
det = Detection(class_id=1, label="car", score=0.9,
|
|
63
|
+
tlwh=[100, 200, 300, 400], frame_sz=(1000, 1000))
|
|
64
|
+
expected = [0.1, 0.2, 0.3, 0.4]
|
|
65
|
+
assert np.allclose(det.tlwh, expected)
|
|
66
|
+
|
|
67
|
+
def test_pixel_coords_clamped_to_frame_bounds(self):
|
|
68
|
+
# Coordinates exceeding frame bounds should be clamped
|
|
69
|
+
det = Detection(class_id=1, label="car", score=0.9,
|
|
70
|
+
tlwh=[900, 900, 200, 200], frame_sz=(1000, 1000))
|
|
71
|
+
# x + w = 1100 > 1000, so xmax should be clamped to 1.0
|
|
72
|
+
# Final normalized: x=0.9, y=0.9, w=0.1, h=0.1
|
|
73
|
+
assert det.tlwh[0] == 0.9
|
|
74
|
+
assert det.tlwh[1] == 0.9
|
|
75
|
+
assert det.tlwh[2] <= 0.1
|
|
76
|
+
assert det.tlwh[3] <= 0.1
|
|
77
|
+
|
|
78
|
+
def test_negative_coordinates_clamped_to_zero(self):
|
|
79
|
+
det = Detection(class_id=1, label="car", score=0.9,
|
|
80
|
+
tlwh=[-10, -20, 100, 100], frame_sz=(1000, 1000))
|
|
81
|
+
# Negative coords should be clamped to 0
|
|
82
|
+
assert det.tlwh[0] >= 0.0
|
|
83
|
+
assert det.tlwh[1] >= 0.0
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class TestDetectionConversionMethods:
|
|
87
|
+
def test_to_tlbr(self):
|
|
88
|
+
det = Detection(class_id=1, label="car", score=0.9, tlwh=[0.1, 0.2, 0.3, 0.4])
|
|
89
|
+
tlbr = det.to_tlbr()
|
|
90
|
+
# tlbr = [xmin, ymin, xmax, ymax] = [0.1, 0.2, 0.4, 0.6]
|
|
91
|
+
assert np.allclose(tlbr, [0.1, 0.2, 0.4, 0.6])
|
|
92
|
+
|
|
93
|
+
def test_to_xyah(self):
|
|
94
|
+
det = Detection(class_id=1, label="car", score=0.9, tlwh=[0.1, 0.2, 0.4, 0.2])
|
|
95
|
+
xyah = det.to_xyah()
|
|
96
|
+
# center_x = 0.1 + 0.4/2 = 0.3
|
|
97
|
+
# center_y = 0.2 + 0.2/2 = 0.3
|
|
98
|
+
# aspect = 0.4 / 0.2 = 2.0
|
|
99
|
+
# height = 0.2
|
|
100
|
+
assert np.allclose(xyah, [0.3, 0.3, 2.0, 0.2])
|
|
101
|
+
|
|
102
|
+
def test_to_dict(self):
|
|
103
|
+
det = Detection(class_id=3, label="truck", score=0.876,
|
|
104
|
+
tlwh=[0.123, 0.456, 0.789, 0.234],
|
|
105
|
+
roi_id=[1], roi_name=["zone1"])
|
|
106
|
+
d = det.to_dict()
|
|
107
|
+
assert d[KEY.CLASS_ID] == 3
|
|
108
|
+
assert d[KEY.LABEL] == "truck"
|
|
109
|
+
assert d[KEY.SCORE] == 0.88 # Rounded to 2 decimals
|
|
110
|
+
assert d[KEY.ROI_ID] == [1]
|
|
111
|
+
assert d[KEY.ROI_NAME] == ["zone1"]
|
|
112
|
+
# TLWH rounded to 3 decimals
|
|
113
|
+
assert len(d[KEY.TLWH]) == 4
|
|
114
|
+
assert isinstance(d[KEY.TLWH], list)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
class TestFilterIouThreshold:
|
|
118
|
+
def test_filters_overlapping_detections(self):
|
|
119
|
+
# Create overlapping detections with different scores
|
|
120
|
+
det1 = Detection(class_id=1, label="car", score=0.9, tlwh=[0.1, 0.1, 0.3, 0.3])
|
|
121
|
+
det2 = Detection(class_id=1, label="car", score=0.7, tlwh=[0.15, 0.15, 0.3, 0.3]) # Overlaps with det1
|
|
122
|
+
det3 = Detection(class_id=1, label="car", score=0.95, tlwh=[0.6, 0.6, 0.2, 0.2]) # Separate
|
|
123
|
+
|
|
124
|
+
detections = [det1, det2, det3]
|
|
125
|
+
filtered = filter_iou_threshold(detections, score_threshold=0.5, iou_threshold=0.3, img_sz=(1000, 1000))
|
|
126
|
+
|
|
127
|
+
# Should keep det1 (higher score than det2) and det3 (non-overlapping)
|
|
128
|
+
assert len(filtered) >= 1
|
|
129
|
+
assert det3 in filtered # Non-overlapping detection should remain
|
|
130
|
+
|
|
131
|
+
def test_filters_by_score_threshold(self):
|
|
132
|
+
det1 = Detection(class_id=1, label="car", score=0.9, tlwh=[0.1, 0.1, 0.3, 0.3])
|
|
133
|
+
det2 = Detection(class_id=1, label="car", score=0.4, tlwh=[0.6, 0.6, 0.2, 0.2]) # Below threshold
|
|
134
|
+
|
|
135
|
+
detections = [det1, det2]
|
|
136
|
+
filtered = filter_iou_threshold(detections, score_threshold=0.5, iou_threshold=0.5, img_sz=(1000, 1000))
|
|
137
|
+
|
|
138
|
+
# Only det1 should pass score threshold
|
|
139
|
+
assert len(filtered) == 1
|
|
140
|
+
assert filtered[0].score == 0.9
|
|
141
|
+
|
|
142
|
+
def test_empty_detections_returns_empty(self):
|
|
143
|
+
filtered = filter_iou_threshold([], score_threshold=0.5, iou_threshold=0.5, img_sz=(1000, 1000))
|
|
144
|
+
assert filtered == []
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
class TestFilterLabels:
|
|
148
|
+
def test_filters_by_label_list(self):
|
|
149
|
+
det1 = Detection(class_id=1, label="car", score=0.9, tlwh=[0.1, 0.1, 0.3, 0.3])
|
|
150
|
+
det2 = Detection(class_id=2, label="person", score=0.8, tlwh=[0.5, 0.5, 0.2, 0.2])
|
|
151
|
+
det3 = Detection(class_id=3, label="truck", score=0.85, tlwh=[0.7, 0.7, 0.2, 0.2])
|
|
152
|
+
|
|
153
|
+
detections = [det1, det2, det3]
|
|
154
|
+
filtered = filter_labels(detections, labels_to_detect=["car", "truck"])
|
|
155
|
+
|
|
156
|
+
assert len(filtered) == 2
|
|
157
|
+
labels = [d.label for d in filtered]
|
|
158
|
+
assert "car" in labels
|
|
159
|
+
assert "truck" in labels
|
|
160
|
+
assert "person" not in labels
|
|
161
|
+
|
|
162
|
+
def test_none_labels_returns_all(self):
|
|
163
|
+
det1 = Detection(class_id=1, label="car", score=0.9, tlwh=[0.1, 0.1, 0.3, 0.3])
|
|
164
|
+
det2 = Detection(class_id=2, label="person", score=0.8, tlwh=[0.5, 0.5, 0.2, 0.2])
|
|
165
|
+
|
|
166
|
+
detections = [det1, det2]
|
|
167
|
+
filtered = filter_labels(detections, labels_to_detect=None)
|
|
168
|
+
|
|
169
|
+
assert len(filtered) == 2
|
|
170
|
+
assert filtered == detections
|
|
171
|
+
|
|
172
|
+
def test_empty_labels_returns_all(self):
|
|
173
|
+
det1 = Detection(class_id=1, label="car", score=0.9, tlwh=[0.1, 0.1, 0.3, 0.3])
|
|
174
|
+
det2 = Detection(class_id=2, label="person", score=0.8, tlwh=[0.5, 0.5, 0.2, 0.2])
|
|
175
|
+
|
|
176
|
+
detections = [det1, det2]
|
|
177
|
+
filtered = filter_labels(detections, labels_to_detect=[])
|
|
178
|
+
|
|
179
|
+
assert len(filtered) == 2
|
|
180
|
+
assert filtered == detections
|
|
181
|
+
|
|
182
|
+
def test_no_matching_labels_returns_empty(self):
|
|
183
|
+
det1 = Detection(class_id=1, label="car", score=0.9, tlwh=[0.1, 0.1, 0.3, 0.3])
|
|
184
|
+
det2 = Detection(class_id=2, label="person", score=0.8, tlwh=[0.5, 0.5, 0.2, 0.2])
|
|
185
|
+
|
|
186
|
+
detections = [det1, det2]
|
|
187
|
+
filtered = filter_labels(detections, labels_to_detect=["truck", "bike"])
|
|
188
|
+
|
|
189
|
+
assert len(filtered) == 0
|
|
@@ -58,12 +58,15 @@ class TestMetaModule:
|
|
|
58
58
|
|
|
59
59
|
|
|
60
60
|
class TestMeta:
|
|
61
|
-
def
|
|
62
|
-
#
|
|
61
|
+
def test_to_dict_uses_current_time(self):
|
|
62
|
+
# to_dict() should use time.time() to get fresh timestamp
|
|
63
63
|
meta = Meta(cur_node=NODE, feed_idx=0, src_node=NODE, src_port=0, src_name=None)
|
|
64
|
-
|
|
64
|
+
time.sleep(0.01) # Small delay to ensure timestamps differ
|
|
65
|
+
t_before = time.time()
|
|
65
66
|
d = meta.to_dict()
|
|
66
|
-
|
|
67
|
+
t_after = time.time()
|
|
68
|
+
assert t_before <= d["ts"] <= t_after
|
|
69
|
+
assert d["ts"] != meta.ts # Should be different from stored ts
|
|
67
70
|
|
|
68
71
|
def test_to_dict_has_required_keys(self):
|
|
69
72
|
meta = Meta(cur_node=NODE, feed_idx=0, src_node=NODE, src_port=0, src_name=None)
|
|
@@ -77,6 +80,22 @@ class TestMeta:
|
|
|
77
80
|
t_after = time.time()
|
|
78
81
|
assert t_before <= meta.ts <= t_after
|
|
79
82
|
|
|
83
|
+
def test_update_source(self):
|
|
84
|
+
meta = Meta(cur_node=NODE, feed_idx=0, src_node=NODE, src_port=0, src_name=None)
|
|
85
|
+
meta.update_source({"frame_id": 100})
|
|
86
|
+
assert meta.source.frame_id == 100
|
|
87
|
+
|
|
88
|
+
def test_update_module(self):
|
|
89
|
+
meta = Meta(cur_node=NODE, feed_idx=0, src_node=NODE, src_port=0, src_name=None)
|
|
90
|
+
meta.update_module({"custom_field": "test"})
|
|
91
|
+
assert meta.module.custom_field == "test"
|
|
92
|
+
|
|
93
|
+
def test_update_frame_format(self):
|
|
94
|
+
meta = Meta(cur_node=NODE, feed_idx=0, src_node=NODE, src_port=0, src_name=None)
|
|
95
|
+
meta.update_frame_format({"encoder": ".jpg", "with_base64": True})
|
|
96
|
+
assert meta.frame_format.encoder == ".jpg"
|
|
97
|
+
assert meta.frame_format.with_base64 is True
|
|
98
|
+
|
|
80
99
|
|
|
81
100
|
class TestVisoData:
|
|
82
101
|
def test_create_without_frame_returns_none_frame(self):
|
|
@@ -1994,7 +1994,7 @@ static __pyx_mstatetype * const __pyx_mstate_global = &__pyx_mstate_global_stati
|
|
|
1994
1994
|
#endif
|
|
1995
1995
|
/* #### Code section: constant_name_defines ### */
|
|
1996
1996
|
#define __pyx_kp_u_ __pyx_string_tab[0]
|
|
1997
|
-
#define
|
|
1997
|
+
#define __pyx_kp_u_1_1_19 __pyx_string_tab[1]
|
|
1998
1998
|
#define __pyx_kp_u_Copyright_2020 __pyx_string_tab[2]
|
|
1999
1999
|
#define __pyx_kp_u_Viso_ai_team __pyx_string_tab[3]
|
|
2000
2000
|
#define __pyx_kp_u__2 __pyx_string_tab[4]
|
|
@@ -2605,16 +2605,16 @@ __Pyx_RefNannySetupContext("PyInit__version", 0);
|
|
|
2605
2605
|
* __license__ = "LGPL3"
|
|
2606
2606
|
* __title__ = "viso-sdk-python" # <<<<<<<<<<<<<<
|
|
2607
2607
|
*
|
|
2608
|
-
* __version__ = "1.1.
|
|
2608
|
+
* __version__ = "1.1.19"
|
|
2609
2609
|
*/
|
|
2610
2610
|
if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_title, __pyx_mstate_global->__pyx_kp_u_viso_sdk_python) < (0)) __PYX_ERR(0, 15, __pyx_L1_error)
|
|
2611
2611
|
|
|
2612
2612
|
/* "viso_sdk/_version.py":17
|
|
2613
2613
|
* __title__ = "viso-sdk-python"
|
|
2614
2614
|
*
|
|
2615
|
-
* __version__ = "1.1.
|
|
2615
|
+
* __version__ = "1.1.19" # <<<<<<<<<<<<<<
|
|
2616
2616
|
*/
|
|
2617
|
-
if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_version, __pyx_mstate_global->
|
|
2617
|
+
if (PyDict_SetItem(__pyx_mstate_global->__pyx_d, __pyx_mstate_global->__pyx_n_u_version, __pyx_mstate_global->__pyx_kp_u_1_1_19) < (0)) __PYX_ERR(0, 17, __pyx_L1_error)
|
|
2618
2618
|
|
|
2619
2619
|
/* "viso_sdk/_version.py":1
|
|
2620
2620
|
* """ # <<<<<<<<<<<<<<
|
|
@@ -2689,7 +2689,7 @@ static int __Pyx_InitConstants(__pyx_mstatetype *__pyx_mstate) {
|
|
|
2689
2689
|
{
|
|
2690
2690
|
const struct { const unsigned int length: 5; } index[] = {{1},{6},{15},{12},{1},{18},{26},{15},{5},{7},{10},{18},{13},{8},{8},{7},{9},{8},{11},{8},{10},{8},{3},{2},{4},{12},{10},{8},{9},{11},{4}};
|
|
2691
2691
|
#if (CYTHON_COMPRESS_STRINGS) == 2 /* compression: bz2 (242 bytes) */
|
|
2692
|
-
const char* const cstring = "BZh91AY&
|
|
2692
|
+
const char* const cstring = "BZh91AY&SYo\247\030\321\000\000\007\337\200@\000@\003x%\350\204A\000\277\357\377\2400\000\315[\014\246\251\261\032\217\005<\240\r\007\244\323@DM6\223LM2\000\000\001\240\324\3656\251\246\241\232\020\304\310\3204\321\241B}\317\023\177kg\260 \035\340 Z\376\rG[']N7\363d\253B\010\313\310Z\267(\347m\323\314\021\232\010\010\024@c\311w\270\016\003\344b\354\037\236\203J\027\241\211a\270\276(\315:U\024$b\337\332]'j\372\314\025\256\316\316e`Tm\0023)E\244\027\351\362\025\rH\213YH\275X\250Gz{\240\367\332\304\326\244\302\251\344\341_\034a\254\230\376\276!0f\271\314\347\255\367\004GrU*\004\201\212\020\326\026\203r\226\221\215=K\030Y%%\037\225\001,<\037\342\356H\247\n\022\r\364\343\032 ";
|
|
2693
2693
|
PyObject *data = __Pyx_DecompressString(cstring, 242, 2);
|
|
2694
2694
|
if (unlikely(!data)) __PYX_ERR(0, 1, __pyx_L1_error)
|
|
2695
2695
|
const char* const bytes = __Pyx_PyBytes_AsString(data);
|
|
@@ -2697,7 +2697,7 @@ const char* const cstring = "BZh91AY&SY_\303Rz\000\000\007\337\200@\000@\003xE\3
|
|
|
2697
2697
|
if (likely(bytes)); else { Py_DECREF(data); __PYX_ERR(0, 1, __pyx_L1_error) }
|
|
2698
2698
|
#endif
|
|
2699
2699
|
#elif (CYTHON_COMPRESS_STRINGS) != 0 /* compression: zlib (196 bytes) */
|
|
2700
|
-
const char* const cstring = "x\3325\216\275n\3030\014\204_\305/`#M\
|
|
2700
|
+
const char* const cstring = "x\3325\216\275n\3030\014\204_\305/`#M\247\002A\177\320!K\206N]\tF\242c\"2\351JT\002\277}\3518\006\207;\334\007\362\330\275t>o\337:\315\231/\2035\373\335~\327\376r\321\016\2711\302\361\343\322\005\315\016Q>o\317|\323\257cs`\351u\003\357\213\266%^\333i\266A\345t\3749\275\342\271Lh\003\000V\3172@H,\004,`\031\003\2351\\=\333\036\000\3675C\344\034\321\310x$\267\202#\001\320\210\234\234C\317\211\026M\034H\312\303:\222\207j\254+\\wD\357\372\254\377\253\230\326\260\220E\352\261&o3*K'\030\333\272w\243\\X\375\330L\230\377\001;rm\357";
|
|
2701
2701
|
PyObject *data = __Pyx_DecompressString(cstring, 196, 1);
|
|
2702
2702
|
if (unlikely(!data)) __PYX_ERR(0, 1, __pyx_L1_error)
|
|
2703
2703
|
const char* const bytes = __Pyx_PyBytes_AsString(data);
|
|
@@ -2705,7 +2705,7 @@ const char* const cstring = "x\3325\216\275n\3030\014\204_\305/`#M\227\016A\177\
|
|
|
2705
2705
|
if (likely(bytes)); else { Py_DECREF(data); __PYX_ERR(0, 1, __pyx_L1_error) }
|
|
2706
2706
|
#endif
|
|
2707
2707
|
#else /* compression: none (287 bytes) */
|
|
2708
|
-
const char* const bytes = ".1.1.
|
|
2708
|
+
const char* const bytes = ".1.1.19Copyright 2020-Viso.ai team?g.corrigan@viso.ai viso.ai AG <info@viso.ai>viso-sdk-pythonLGPL3abspath__author__cline_in_traceback__copyright___cur_dirdatetimedirname__email____file____license____main____module____name__nowospath__qualname__setdefault__test____title____version__year";
|
|
2709
2709
|
PyObject *data = NULL;
|
|
2710
2710
|
CYTHON_UNUSED_VAR(__Pyx_DecompressString);
|
|
2711
2711
|
#endif
|