回放叠加改用展开底图,并统一 2D/3D 投递。

箭头/采集图像与 live 的 processed_frame 对齐;deliver_measurement 先画 2D 再提交同一包给 3D。已用 overlay、scene3d 与 replay 相关测试验证。
This commit is contained in:
ykcheungab
2026-10-06 21:21:37 +08:00
parent 321e52f47a
commit 829d2c1b53
10 changed files with 519 additions and 125 deletions
+26
View File
@@ -465,6 +465,32 @@ class _Host:
self.frames.append(frame)
def show_analysis_packet(self, packet) -> None:
self.deliver_measurement(packet, advance="flush", paint_2d=False)
def deliver_measurement(
self,
packet,
*,
advance: str = "tick",
arrow_policy=None,
image_source: str | None = None,
paint_2d: bool = True,
) -> None:
if paint_2d:
from orisys_app_shared.acquisition.image_backend import ImageFrame
self.frames.append(
ImageFrame(
getattr(packet, "processed_frame", None),
flow=getattr(packet, "flow", None),
depth=getattr(packet, "depth", None),
valid_mask=getattr(packet, "valid_mask", None),
source=image_source or "replay",
frame_id=int(getattr(packet, "frame_id", 0) or 0),
arrow_policy=arrow_policy,
result_available=True,
)
)
self.analysis_packets.append(packet)
def drop_render_marker(self) -> None:
@@ -262,6 +262,32 @@ class _Host:
self.frames.append(frame)
def show_analysis_packet(self, packet) -> None:
self.deliver_measurement(packet, advance="flush", paint_2d=False)
def deliver_measurement(
self,
packet,
*,
advance: str = "tick",
arrow_policy=None,
image_source: str | None = None,
paint_2d: bool = True,
) -> None:
if paint_2d:
from orisys_app_shared.acquisition.image_backend import ImageFrame
self.frames.append(
ImageFrame(
getattr(packet, "processed_frame", None),
flow=getattr(packet, "flow", None),
depth=getattr(packet, "depth", None),
valid_mask=getattr(packet, "valid_mask", None),
source=image_source or "replay",
frame_id=int(getattr(packet, "frame_id", 0) or 0),
arrow_policy=arrow_policy,
result_available=True,
)
)
self.analysis_packets.append(packet)
def drop_render_marker(self) -> None:
+7 -7
View File
@@ -388,8 +388,8 @@ def _run_session(make_window, record_root, *, with_3d: bool):
if with_3d:
view = _RecordingView()
window.mesh3d_panel.attach_view(view)
# With no pane the sink still runs (it is registered on the worker) and does
# nothing, which is the case the comparison below is about.
# 3D is submitted on the GUI deliver path (same tick as 2D), not as an
# acquisition-thread sink — with or without a pane attached.
window.toolbar.btn_record.setChecked(True)
for index in range(96):
stuck.emit(ui_check._fake_packet(index, mono_t=index / 30.0))
@@ -427,20 +427,20 @@ def test_the_3d_consumer_cannot_change_the_record(make_window, next_record_root)
assert "t_rel_s" in header and len(with_3d_csv.splitlines()) > 10
def test_the_3d_sink_is_registered_and_inert_when_the_pane_is_off(make_window, next_record_root):
"""A sink that has to be added and removed around a toggle is a state machine."""
def test_live_3d_is_not_an_acquisition_thread_sink(make_window, next_record_root):
"""3D shares the GUI deliver path with 2D; only the record channel is a sink."""
import orisys_studio.app_window as app_module
window, stuck = _running_window(make_window)
app_module.recordings_dir = lambda: next_record_root()
try:
assert window._on_packet_recorded in stuck.sinks()
assert window._on_packet_for_3d in stuck.sinks(), (
"the 3D sink must be registered with the worker, not attached per toggle"
assert stuck.sinks() == (window._on_packet_recorded,), (
"live 3D must not register a second acquisition-thread sink"
)
assert window.mesh3d_panel.view is None, "a box sensor must not build a view"
for index in range(10):
stuck.emit(ui_check._fake_packet(index))
window._on_run_tick()
assert window.session_store.count == 10
assert window.mesh3d_panel.view is None
finally: