@camstack/addon-pipeline 1.1.66 → 1.1.68
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.
- package/dist/audio-analyzer/index.js +1 -1
- package/dist/audio-analyzer/index.mjs +1 -1
- package/dist/detection-pipeline/index.js +52 -13
- package/dist/detection-pipeline/index.mjs +52 -13
- package/dist/{dist-D5o9fGxq.js → dist-BxxVKcnw.js} +43 -5
- package/dist/{dist-BpWot5-w.mjs → dist-DkGHtAaK.mjs} +43 -5
- package/dist/motion-wasm/index.js +1 -1
- package/dist/motion-wasm/index.mjs +1 -1
- package/dist/pipeline-runner/index.js +2 -2
- package/dist/pipeline-runner/index.mjs +2 -2
- package/dist/recorder/index.js +1 -1
- package/dist/recorder/index.mjs +1 -1
- package/dist/session-decode/decode-worker-child.js +176 -11
- package/dist/session-decode/decode-worker-child.mjs +176 -11
- package/dist/{step-definitions-81eYyJbW.js → step-definitions-CAs0RD2N.js} +1 -1
- package/dist/{step-definitions-D6R9X0V7.mjs → step-definitions-Delhq28w.mjs} +1 -1
- package/dist/stream-broker/_stub.js +1 -1
- package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-CIIIVPzB.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-BUXIIogo.mjs} +1 -1
- package/dist/stream-broker/{_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-CPbLcza9.mjs → _virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-D68Lj69v.mjs} +1 -1
- package/dist/stream-broker/{hostInit-CeBNudbY.mjs → hostInit-D7_95hNV.mjs} +1 -1
- package/dist/stream-broker/index.js +1 -1
- package/dist/stream-broker/index.mjs +1 -1
- package/dist/stream-broker/remoteEntry.js +1 -1
- package/embed-dist/assets/{MaskShapeCanvas-DI4BY7W2-CbBbcdZb.js → MaskShapeCanvas-DI4BY7W2-CRvzj7Of.js} +1 -1
- package/embed-dist/assets/{MotionZonesSettings-NcxxQN8r-aA6zvms_.js → MotionZonesSettings-NcxxQN8r-CBgvPUB-.js} +1 -1
- package/embed-dist/assets/{PrivacyMaskSettings-APgPLF7p-CcGB7iAE.js → PrivacyMaskSettings-APgPLF7p-DH07fe1k.js} +1 -1
- package/embed-dist/assets/{index-BRG_Fqb5.js → index-BkoPcGtQ.js} +13 -13
- package/embed-dist/index.html +1 -1
- package/package.json +1 -1
- package/python/inference_pool.py +362 -45
- package/python/test_inference_pool_ov_ppp.py +117 -0
- package/python/test_inference_pool_preprocess.py +93 -1
|
@@ -11,7 +11,13 @@ np = pytest.importorskip("numpy")
|
|
|
11
11
|
PIL = pytest.importorskip("PIL")
|
|
12
12
|
from PIL import Image # noqa: E402
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
import inference_pool # noqa: E402
|
|
15
|
+
from inference_pool import ( # noqa: E402
|
|
16
|
+
_preprocess,
|
|
17
|
+
_preprocess_ctc_gray,
|
|
18
|
+
_preprocess_ov_uint8,
|
|
19
|
+
_to_model_tensor,
|
|
20
|
+
)
|
|
15
21
|
|
|
16
22
|
|
|
17
23
|
def _hwc(h: int, w: int) -> "np.ndarray":
|
|
@@ -63,3 +69,89 @@ def test_ctc_gray_caps_resized_width_at_input_w() -> None:
|
|
|
63
69
|
img = Image.new("RGB", (800, 64), (50, 50, 50))
|
|
64
70
|
out = _preprocess_ctc_gray(img, 384, 64)
|
|
65
71
|
assert out.shape == (1, 1, 64, 384)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
# ---------------------------------------------------------------------------
|
|
75
|
+
# Fix 2 — OpenVINO PrePostProcessor uint8 producer (`_preprocess_ov_uint8`)
|
|
76
|
+
# ---------------------------------------------------------------------------
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def test_ov_uint8_letterbox_is_nhwc_uint8_at_model_size() -> None:
|
|
80
|
+
# A non-square frame is aspect-preserved + padded to a square uint8 canvas.
|
|
81
|
+
plan = {"inputW": 640, "inputH": 640, "size": 640, "letterbox": True, "normalization": "none"}
|
|
82
|
+
img = Image.new("RGB", (1280, 720), (10, 20, 30))
|
|
83
|
+
tensor, scale, pad = _preprocess_ov_uint8(img, plan)
|
|
84
|
+
assert tensor.shape == (1, 640, 640, 3) # NHWC — OV transposes on-device
|
|
85
|
+
assert tensor.dtype == np.uint8 # NO float/255 in Python — folded into OV
|
|
86
|
+
assert 0 < scale < 1 # 640/1280
|
|
87
|
+
assert pad[1] > 0 # letterbox pads the shorter (vertical) axis
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def test_ov_uint8_letterbox_preserves_aspect_ratio() -> None:
|
|
91
|
+
# The real content occupies scale*orig; the rest is 114 grey padding — the
|
|
92
|
+
# aspect-ratio letterbox YOLO needs, preserved even though float/layout
|
|
93
|
+
# moved into OV.
|
|
94
|
+
plan = {"inputW": 640, "inputH": 640, "size": 640, "letterbox": True, "normalization": "none"}
|
|
95
|
+
img = Image.new("RGB", (1280, 640), (200, 100, 50))
|
|
96
|
+
tensor, scale, pad = _preprocess_ov_uint8(img, plan)
|
|
97
|
+
assert scale == pytest.approx(0.5, abs=1e-6)
|
|
98
|
+
# Padded rows (top/bottom) are the 114 letterbox fill.
|
|
99
|
+
grid = tensor[0]
|
|
100
|
+
assert np.all(grid[0] == 114)
|
|
101
|
+
assert np.all(grid[-1] == 114)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def test_ov_uint8_plain_resize_matches_model_dims() -> None:
|
|
105
|
+
plan = {"inputW": 224, "inputH": 224, "size": 224, "letterbox": False, "normalization": "imagenet"}
|
|
106
|
+
img = Image.new("RGB", (500, 300), (128, 128, 128))
|
|
107
|
+
tensor, scale, pad = _preprocess_ov_uint8(img, plan)
|
|
108
|
+
assert tensor.shape == (1, 224, 224, 3)
|
|
109
|
+
assert tensor.dtype == np.uint8
|
|
110
|
+
assert (scale, pad) == (1.0, (0, 0))
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
# ---------------------------------------------------------------------------
|
|
114
|
+
# Fix 1 — bench preprocess cache is HIT on the (tagged) batch path
|
|
115
|
+
# ---------------------------------------------------------------------------
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def test_bench_tag_caches_preprocess_and_counts_hit() -> None:
|
|
119
|
+
# A tagged frame (as the MSG_INFER_BATCH path now sets via `_bench_frame_id`)
|
|
120
|
+
# is preprocessed ONCE (miss) then served from cache (hit) — the fix that
|
|
121
|
+
# turns the sustained batch benchmark into a pure-inference measurement.
|
|
122
|
+
inference_pool._runtime = "onnxruntime"
|
|
123
|
+
inference_pool._bench_preprocess_cache.clear()
|
|
124
|
+
inference_pool._bench_cache_hits = 0
|
|
125
|
+
inference_pool._bench_cache_misses = 0
|
|
126
|
+
|
|
127
|
+
cfg = {"inputSize": 640, "_input_name": "images", "preprocessMode": "letterbox"}
|
|
128
|
+
img = Image.new("RGB", (640, 640), (12, 34, 56))
|
|
129
|
+
img._bench_frame_id = 4242
|
|
130
|
+
|
|
131
|
+
first = _preprocess(img, cfg)
|
|
132
|
+
assert inference_pool._bench_cache_misses == 1
|
|
133
|
+
assert inference_pool._bench_cache_hits == 0
|
|
134
|
+
|
|
135
|
+
# Five more inferences on the SAME pinned frame → all cache hits, and the
|
|
136
|
+
# returned tuple is the SAME object (no re-preprocess).
|
|
137
|
+
for _ in range(5):
|
|
138
|
+
again = _preprocess(img, cfg)
|
|
139
|
+
assert again is first
|
|
140
|
+
assert inference_pool._bench_cache_hits == 5
|
|
141
|
+
assert inference_pool._bench_cache_misses == 1
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def test_untagged_frame_never_caches() -> None:
|
|
145
|
+
# Live camera frames carry no tag → every call re-preprocesses (correct).
|
|
146
|
+
inference_pool._runtime = "onnxruntime"
|
|
147
|
+
inference_pool._bench_preprocess_cache.clear()
|
|
148
|
+
inference_pool._bench_cache_hits = 0
|
|
149
|
+
inference_pool._bench_cache_misses = 0
|
|
150
|
+
|
|
151
|
+
cfg = {"inputSize": 640, "_input_name": "images", "preprocessMode": "letterbox"}
|
|
152
|
+
img = Image.new("RGB", (640, 640), (9, 9, 9)) # no _bench_frame_id
|
|
153
|
+
_preprocess(img, cfg)
|
|
154
|
+
_preprocess(img, cfg)
|
|
155
|
+
assert inference_pool._bench_cache_hits == 0
|
|
156
|
+
assert inference_pool._bench_cache_misses == 0
|
|
157
|
+
assert len(inference_pool._bench_preprocess_cache) == 0
|