改为按帧自适应显示 Autocal 深度色阶

从有效 UV 区域计算当前帧范围,排除无效值和区域外像素。57 项定向测试及代码、文档检查通过。
This commit is contained in:
ykcheungab
2026-10-11 18:14:54 +08:00
parent 34a1d9b1f1
commit 3304b4eda9
5 changed files with 44 additions and 11 deletions
+1 -1
View File
@@ -486,7 +486,7 @@
"arrows": "Displacement arrows", "arrows": "Displacement arrows",
"depth": "Depth", "depth": "Depth",
"depth_tip": "False colour of algorithm depth/deformation, not calibrated millimetres.", "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", "depth_missing": "No valid depth/deformation for this frame",
"flow_missing": "No valid displacement for this frame" "flow_missing": "No valid displacement for this frame"
}, },
+1 -1
View File
@@ -486,7 +486,7 @@
"arrows": "位移箭头", "arrows": "位移箭头",
"depth": "深度", "depth": "深度",
"depth_tip": "显示算法深度/形变信号的伪彩色,不表示已标定的毫米深度。", "depth_tip": "显示算法深度/形变信号的伪彩色,不表示已标定的毫米深度。",
"depth_scale": "形变伪彩色范围 0–1(算法单位);超范围颜色饱和", "depth_scale": "形变色阶自动适应本帧:{low:.4g}–{high:.4g}(算法单位,非 mm)",
"depth_missing": "本帧无有效深度/形变信号", "depth_missing": "本帧无有效深度/形变信号",
"flow_missing": "本帧无有效位移信号" "flow_missing": "本帧无有效位移信号"
}, },
@@ -111,7 +111,7 @@ finger_F001_<时间>_<标识>/
采集页持续显示 FN/FX/FY 原始信号及最近 60 秒曲线;已有标定的轴另显示 N,未标定的轴不将 raw 转称为 N。无效帧在曲线中断开;停止或超过 1 秒没有新帧时明确提示。此处没有实时 FT 参考力,人工填写的参考力仍是独立声明。 采集页持续显示 FN/FX/FY 原始信号及最近 60 秒曲线;已有标定的轴另显示 N,未标定的轴不将 raw 转称为 N。无效帧在曲线中断开;停止或超过 1 秒没有新帧时明确提示。此处没有实时 FT 参考力,人工填写的参考力仍是独立声明。
实时 UV 图有“真实背景”“位移箭头”“深度”三个独立开关;取消真实背景显示纯色画布,深度颜色可叠加在两种背景上。深度使用固定 0–1 算法单位色阶,超范围饱和,不代表毫米;缺失或过期字段不绘制,显示原因。显示切换不改变数据和录像,也不旋转 UV 坐标。 实时 UV 图有“真实背景”“位移箭头”“深度”三个独立开关;取消真实背景显示纯色画布,深度颜色可叠加在两种背景上。深度色阶按当前帧有效 UV 区域内的有限值最小/最大值自动调整,并显示范围;同一颜色在不同帧不代表相同数值,算法单位不代表毫米。缺失或过期字段不绘制,显示原因。显示切换不改变数据和录像,也不旋转 UV 坐标。
复核时选中表格中的保持段,检查下方原始样本图;起点、终点以该段保持开始为 0 秒,只能在原保持段内调整。勾选“已检查此段稳定”,点击“应用窗口并重算”,最后“另存分析结果”。至少有两个不同载荷的已确认加载/零载窗口时,显示已确认窗口拟合;不足时明确显示候选拟合。人工确认只表示看过稳定性,不证明参考力准确或物理同步。 复核时选中表格中的保持段,检查下方原始样本图;起点、终点以该段保持开始为 0 秒,只能在原保持段内调整。勾选“已检查此段稳定”,点击“应用窗口并重算”,最后“另存分析结果”。至少有两个不同载荷的已确认加载/零载窗口时,显示已确认窗口拟合;不足时明确显示候选拟合。人工确认只表示看过稳定性,不证明参考力准确或物理同步。
@@ -307,16 +307,19 @@ class FingerSourcePanel(QWidget):
fresh = (getattr(packet, "depth_valid", None) is True fresh = (getattr(packet, "depth_valid", None) is True
and getattr(packet, "depth_frame_id", None) == packet.frame_id) and getattr(packet, "depth_frame_id", None) == packet.frame_id)
if fresh and depth is not None and np.shape(depth) == frame.shape[:2]: if fresh and depth is not None and np.shape(depth) == frame.shape[:2]:
# Fixed scale in SDK divergence units, never millimetres. valid = np.isfinite(depth)
colored = depth_map_to_bgr(depth, flow_colormap("light"), if mask is not None:
value_range=(0, 1), invalid_mask=mask) valid &= np.asarray(mask, dtype=bool)
if colored is not None: if np.any(valid):
valid = np.isfinite(depth) # Adapt to this frame's valid UV region, excluding the exterior.
if mask is not None: low, high = float(np.min(depth[valid])), float(np.max(depth[valid]))
valid &= np.asarray(mask, dtype=bool) 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) blended = cv2.addWeighted(frame, .4, colored, .6, 0)
frame[valid] = blended[valid] frame[valid] = blended[valid]
notes.append(t("feedback.depth_scale")) notes.append(t("feedback.depth_scale").format(low=low, high=high))
else: else:
notes.append(t("feedback.depth_missing")) notes.append(t("feedback.depth_missing"))
else: else:
@@ -83,3 +83,33 @@ def test_display_toggles_redraw_same_frame_without_mutating_measurements(qt_app,
assert panel.display_note.text() assert panel.display_note.text()
np.testing.assert_array_equal(frames[-1], solid) np.testing.assert_array_equal(frames[-1], solid)
panel.shutdown() 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()