@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.
Files changed (32) hide show
  1. package/dist/audio-analyzer/index.js +1 -1
  2. package/dist/audio-analyzer/index.mjs +1 -1
  3. package/dist/detection-pipeline/index.js +52 -13
  4. package/dist/detection-pipeline/index.mjs +52 -13
  5. package/dist/{dist-D5o9fGxq.js → dist-BxxVKcnw.js} +43 -5
  6. package/dist/{dist-BpWot5-w.mjs → dist-DkGHtAaK.mjs} +43 -5
  7. package/dist/motion-wasm/index.js +1 -1
  8. package/dist/motion-wasm/index.mjs +1 -1
  9. package/dist/pipeline-runner/index.js +2 -2
  10. package/dist/pipeline-runner/index.mjs +2 -2
  11. package/dist/recorder/index.js +1 -1
  12. package/dist/recorder/index.mjs +1 -1
  13. package/dist/session-decode/decode-worker-child.js +176 -11
  14. package/dist/session-decode/decode-worker-child.mjs +176 -11
  15. package/dist/{step-definitions-81eYyJbW.js → step-definitions-CAs0RD2N.js} +1 -1
  16. package/dist/{step-definitions-D6R9X0V7.mjs → step-definitions-Delhq28w.mjs} +1 -1
  17. package/dist/stream-broker/_stub.js +1 -1
  18. 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
  19. 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
  20. package/dist/stream-broker/{hostInit-CeBNudbY.mjs → hostInit-D7_95hNV.mjs} +1 -1
  21. package/dist/stream-broker/index.js +1 -1
  22. package/dist/stream-broker/index.mjs +1 -1
  23. package/dist/stream-broker/remoteEntry.js +1 -1
  24. package/embed-dist/assets/{MaskShapeCanvas-DI4BY7W2-CbBbcdZb.js → MaskShapeCanvas-DI4BY7W2-CRvzj7Of.js} +1 -1
  25. package/embed-dist/assets/{MotionZonesSettings-NcxxQN8r-aA6zvms_.js → MotionZonesSettings-NcxxQN8r-CBgvPUB-.js} +1 -1
  26. package/embed-dist/assets/{PrivacyMaskSettings-APgPLF7p-CcGB7iAE.js → PrivacyMaskSettings-APgPLF7p-DH07fe1k.js} +1 -1
  27. package/embed-dist/assets/{index-BRG_Fqb5.js → index-BkoPcGtQ.js} +13 -13
  28. package/embed-dist/index.html +1 -1
  29. package/package.json +1 -1
  30. package/python/inference_pool.py +362 -45
  31. package/python/test_inference_pool_ov_ppp.py +117 -0
  32. 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
- from inference_pool import _to_model_tensor, _preprocess_ctc_gray # noqa: E402
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