From 3304b4eda927805d41158457ef09aaba7ee43167 Mon Sep 17 00:00:00 2001 From: ykcheungab Date: Sun, 11 Oct 2026 18:14:54 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=B9=E4=B8=BA=E6=8C=89=E5=B8=A7=E8=87=AA?= =?UTF-8?q?=E9=80=82=E5=BA=94=E6=98=BE=E7=A4=BA=20Autocal=20=E6=B7=B1?= =?UTF-8?q?=E5=BA=A6=E8=89=B2=E9=98=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 从有效 UV 区域计算当前帧范围,排除无效值和区域外像素。57 项定向测试及代码、文档检查通过。 --- apps/autocal/config/locales/en_US.json | 2 +- apps/autocal/config/locales/zh_CN.json | 2 +- .../docs/calibration-data-format.zh.md | 2 +- .../orisys_autocal/ui/finger_source_panel.py | 19 +++++++----- .../tests/test_calibration_feedback.py | 30 +++++++++++++++++++ 5 files changed, 44 insertions(+), 11 deletions(-) diff --git a/apps/autocal/config/locales/en_US.json b/apps/autocal/config/locales/en_US.json index 2c321c0..4ad8aa9 100644 --- a/apps/autocal/config/locales/en_US.json +++ b/apps/autocal/config/locales/en_US.json @@ -486,7 +486,7 @@ "arrows": "Displacement arrows", "depth": "Depth", "depth_tip": "False colour of algorithm depth/deformation, not calibrated millimetres.", - "depth_scale": "Deformation colour range 0–1 (algorithm units); values outside saturate", + "depth_scale": "Adaptive deformation range for this frame: {low:.4g}–{high:.4g} (algorithm units, not mm)", "depth_missing": "No valid depth/deformation for this frame", "flow_missing": "No valid displacement for this frame" }, diff --git a/apps/autocal/config/locales/zh_CN.json b/apps/autocal/config/locales/zh_CN.json index 4dfe567..8fb0c72 100644 --- a/apps/autocal/config/locales/zh_CN.json +++ b/apps/autocal/config/locales/zh_CN.json @@ -486,7 +486,7 @@ "arrows": "位移箭头", "depth": "深度", "depth_tip": "显示算法深度/形变信号的伪彩色,不表示已标定的毫米深度。", - "depth_scale": "形变伪彩色范围 0–1(算法单位);超范围颜色饱和", + "depth_scale": "形变色阶自动适应本帧:{low:.4g}–{high:.4g}(算法单位,非 mm)", "depth_missing": "本帧无有效深度/形变信号", "flow_missing": "本帧无有效位移信号" }, diff --git a/apps/autocal/docs/calibration-data-format.zh.md b/apps/autocal/docs/calibration-data-format.zh.md index 8221a7c..b181156 100644 --- a/apps/autocal/docs/calibration-data-format.zh.md +++ b/apps/autocal/docs/calibration-data-format.zh.md @@ -111,7 +111,7 @@ finger_F001_<时间>_<标识>/ 采集页持续显示 FN/FX/FY 原始信号及最近 60 秒曲线;已有标定的轴另显示 N,未标定的轴不将 raw 转称为 N。无效帧在曲线中断开;停止或超过 1 秒没有新帧时明确提示。此处没有实时 FT 参考力,人工填写的参考力仍是独立声明。 -实时 UV 图有“真实背景”“位移箭头”“深度”三个独立开关;取消真实背景显示纯色画布,深度颜色可叠加在两种背景上。深度使用固定 0–1 算法单位色阶,超范围饱和,不代表毫米;缺失或过期字段不绘制,显示原因。显示切换不改变数据和录像,也不旋转 UV 坐标。 +实时 UV 图有“真实背景”“位移箭头”“深度”三个独立开关;取消真实背景显示纯色画布,深度颜色可叠加在两种背景上。深度色阶按当前帧有效 UV 区域内的有限值最小/最大值自动调整,并显示范围;同一颜色在不同帧不代表相同数值,算法单位不代表毫米。缺失或过期字段不绘制,显示原因。显示切换不改变数据和录像,也不旋转 UV 坐标。 复核时选中表格中的保持段,检查下方原始样本图;起点、终点以该段保持开始为 0 秒,只能在原保持段内调整。勾选“已检查此段稳定”,点击“应用窗口并重算”,最后“另存分析结果”。至少有两个不同载荷的已确认加载/零载窗口时,显示已确认窗口拟合;不足时明确显示候选拟合。人工确认只表示看过稳定性,不证明参考力准确或物理同步。 diff --git a/apps/autocal/src/orisys_autocal/ui/finger_source_panel.py b/apps/autocal/src/orisys_autocal/ui/finger_source_panel.py index fc8d52c..84ff061 100644 --- a/apps/autocal/src/orisys_autocal/ui/finger_source_panel.py +++ b/apps/autocal/src/orisys_autocal/ui/finger_source_panel.py @@ -307,16 +307,19 @@ class FingerSourcePanel(QWidget): fresh = (getattr(packet, "depth_valid", None) is True and getattr(packet, "depth_frame_id", None) == packet.frame_id) if fresh and depth is not None and np.shape(depth) == frame.shape[:2]: - # Fixed scale in SDK divergence units, never millimetres. - colored = depth_map_to_bgr(depth, flow_colormap("light"), - value_range=(0, 1), invalid_mask=mask) - if colored is not None: - valid = np.isfinite(depth) - if mask is not None: - valid &= np.asarray(mask, dtype=bool) + valid = np.isfinite(depth) + if mask is not None: + valid &= np.asarray(mask, dtype=bool) + if np.any(valid): + # Adapt to this frame's valid UV region, excluding the exterior. + low, high = float(np.min(depth[valid])), float(np.max(depth[valid])) + colored = depth_map_to_bgr( + np.where(valid, depth, low), flow_colormap("light"), + value_range=(low, high), invalid_mask=valid, + ) blended = cv2.addWeighted(frame, .4, colored, .6, 0) frame[valid] = blended[valid] - notes.append(t("feedback.depth_scale")) + notes.append(t("feedback.depth_scale").format(low=low, high=high)) else: notes.append(t("feedback.depth_missing")) else: diff --git a/apps/autocal/tests/test_calibration_feedback.py b/apps/autocal/tests/test_calibration_feedback.py index 79d6ae6..4068e4f 100644 --- a/apps/autocal/tests/test_calibration_feedback.py +++ b/apps/autocal/tests/test_calibration_feedback.py @@ -83,3 +83,33 @@ def test_display_toggles_redraw_same_frame_without_mutating_measurements(qt_app, assert panel.display_note.text() np.testing.assert_array_equal(frames[-1], solid) panel.shutdown() + + +def test_depth_range_adapts_per_frame_and_excludes_invalid_uv_pixels(qt_app, monkeypatch): + from orisys_autocal.ui import finger_source_panel + + panel = finger_source_panel.FingerSourcePanel() + panel.background_check.setChecked(False) + panel.depth_check.setChecked(True) + mask = np.zeros((64, 80), dtype=bool) + mask[10:30, 20:40] = True + depth = np.full((64, 80), 1e6) + depth[mask] = np.linspace(2, 4, mask.sum()) + depth[10, 20] = np.nan + frames = [] + monkeypatch.setattr(panel, "_show_frame", lambda frame: frames.append(frame.copy())) + panel._last_packet = packet(depth=depth, valid_mask=mask, + depth_valid=True, depth_frame_id=1) + panel._redraw() + first = frames[-1] + assert "4" in panel.display_note.text() + panel._last_packet = replace(panel._last_packet, depth=depth * 10 + 5) + panel._redraw() + # A different numerical range spans the same colour ramp in the next frame. + np.testing.assert_array_equal(frames[-1], first) + assert "45" in panel.display_note.text() + panel._last_packet = replace(panel._last_packet, depth=np.full_like(depth, np.nan)) + panel._redraw() + assert panel.display_note.text() + assert not np.array_equal(frames[-1], first) + panel.shutdown()