fix: reduce alarm snapshot label obstruction
This commit is contained in:
@@ -62,6 +62,8 @@ ZONE_OVERLAY_PALETTE: tuple[tuple[int, int, int], ...] = (
|
|||||||
TRASH_OVERLAY_RGB = (255, 64, 64)
|
TRASH_OVERLAY_RGB = (255, 64, 64)
|
||||||
LABEL_TEXT_RGB = (255, 255, 255)
|
LABEL_TEXT_RGB = (255, 255, 255)
|
||||||
LABEL_SHADOW_RGB = (0, 0, 0)
|
LABEL_SHADOW_RGB = (0, 0, 0)
|
||||||
|
LABEL_BOX_ALPHA = 0.34
|
||||||
|
LABEL_OUTLINE_ALPHA = 0.64
|
||||||
CJK_FONT_CANDIDATES = (
|
CJK_FONT_CANDIDATES = (
|
||||||
Path("/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc"),
|
Path("/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc"),
|
||||||
Path("/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.otf"),
|
Path("/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.otf"),
|
||||||
@@ -350,13 +352,13 @@ def render_region_labels_with_ffmpeg(
|
|||||||
|
|
||||||
|
|
||||||
def build_drawtext_filter(labels: list[OverlayLabel], font_file: Path, height: int) -> str:
|
def build_drawtext_filter(labels: list[OverlayLabel], font_file: Path, height: int) -> str:
|
||||||
font_size = max(14, min(30, round(height * 0.052)))
|
font_size = max(10, min(22, round(height * 0.036)))
|
||||||
filters: list[str] = []
|
filters: list[str] = []
|
||||||
for label in labels:
|
for label in labels:
|
||||||
text = escape_drawtext_value(label.text)
|
text = escape_drawtext_value(label.text)
|
||||||
font = escape_drawtext_value(str(font_file))
|
font = escape_drawtext_value(str(font_file))
|
||||||
color = rgb_to_hex(LABEL_TEXT_RGB)
|
color = rgb_to_hex(LABEL_TEXT_RGB)
|
||||||
box_color = "black@0.62"
|
box_color = f"black@{LABEL_BOX_ALPHA:.2f}"
|
||||||
filters.append(
|
filters.append(
|
||||||
"drawtext="
|
"drawtext="
|
||||||
f"fontfile='{font}':"
|
f"fontfile='{font}':"
|
||||||
@@ -367,7 +369,7 @@ def build_drawtext_filter(labels: list[OverlayLabel], font_file: Path, height: i
|
|||||||
f"fontcolor={color}:"
|
f"fontcolor={color}:"
|
||||||
"box=1:"
|
"box=1:"
|
||||||
f"boxcolor={box_color}:"
|
f"boxcolor={box_color}:"
|
||||||
"boxborderw=4"
|
"boxborderw=2"
|
||||||
)
|
)
|
||||||
return ",".join(filters)
|
return ",".join(filters)
|
||||||
|
|
||||||
@@ -442,8 +444,8 @@ def draw_region_label(
|
|||||||
box_height = min(box_height, height - y)
|
box_height = min(box_height, height - y)
|
||||||
if box_width < 6 or box_height < 6:
|
if box_width < 6 or box_height < 6:
|
||||||
return
|
return
|
||||||
fill_rect(rgb, width, height, x, y, box_width, box_height, LABEL_SHADOW_RGB, alpha=0.62)
|
fill_rect(rgb, width, height, x, y, box_width, box_height, LABEL_SHADOW_RGB, alpha=LABEL_BOX_ALPHA)
|
||||||
draw_rect_outline(rgb, width, height, x, y, box_width, box_height, accent_rgb, alpha=0.9)
|
draw_rect_outline(rgb, width, height, x, y, box_width, box_height, accent_rgb, alpha=LABEL_OUTLINE_ALPHA)
|
||||||
draw_text(rgb, width, height, x + 2, y + 2, glyphs, LABEL_TEXT_RGB, LABEL_SHADOW_RGB)
|
draw_text(rgb, width, height, x + 2, y + 2, glyphs, LABEL_TEXT_RGB, LABEL_SHADOW_RGB)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -315,4 +315,27 @@
|
|||||||
- Remote health returned `status=ok` and `runtime_status=running`.
|
- Remote health returned `status=ok` and `runtime_status=running`.
|
||||||
- Remote container config shows the new thresholds.
|
- Remote container config shows the new thresholds.
|
||||||
- After deployment, latest diagnostics stabilized at `zone_counts = {"1": 1, "2": 1, "6": 1}`.
|
- After deployment, latest diagnostics stabilized at `zone_counts = {"1": 1, "2": 1, "6": 1}`.
|
||||||
- During a two-minute observation window after `13:25`, no new `batch_consumed` events were emitted; only expected pre-warning/alarm lifecycle events appeared for the occupied zones.
|
- During a two-minute observation window after `13:25`, no new `batch_consumed` events were emitted; only expected pre-warning/alarm lifecycle events appeared for the occupied zones.
|
||||||
|
|
||||||
|
## Current Task: Reduce Alarm Snapshot Label Visual Obstruction
|
||||||
|
|
||||||
|
**Goal:** Region labels on uploaded alarm screenshots should be smaller and more transparent so operators can inspect the food/display image underneath.
|
||||||
|
|
||||||
|
**Design:** Keep the existing label content, placement, CJK font rendering, and per-zone colors. Only reduce the visual weight of the label layer by lowering font size, black label-box opacity, border width, and fallback label-box opacity.
|
||||||
|
|
||||||
|
- [x] Inspect current alarm snapshot label rendering style.
|
||||||
|
- [x] Add a regression test for smaller ffmpeg drawtext label style.
|
||||||
|
- [x] Reduce drawtext font size and label-box opacity.
|
||||||
|
- [x] Keep fallback label renderer visually consistent with the ffmpeg path.
|
||||||
|
- [x] Run full local verification.
|
||||||
|
- [x] Deploy the updated snapshot overlay style to `xiaozheng@10.8.0.23`.
|
||||||
|
- [x] Verify remote runtime health and deployed label style.
|
||||||
|
|
||||||
|
### Notes
|
||||||
|
|
||||||
|
- Targeted snapshot test passed: `PYTHONPATH=src python3 -m unittest tests/test_alarm_snapshots.py -v`.
|
||||||
|
- Full local verification passed: `PYTHONPATH=src python3 -m unittest discover -s tests -v` (`103` tests).
|
||||||
|
- Remote verification passed:
|
||||||
|
- `GET /api/manage/health` returned `status=ok` and `runtime_status=running`.
|
||||||
|
- Running container uses `fontsize=13`, `boxcolor=black@0.34`, and `boxborderw=2` for region labels.
|
||||||
|
- `cold-display-guard-runtime` logs show normal startup after restart.
|
||||||
|
|||||||
@@ -189,6 +189,25 @@ class AlarmSnapshotTests(unittest.TestCase):
|
|||||||
dockerfile = (Path(__file__).resolve().parents[1] / "Dockerfile").read_text(encoding="utf-8")
|
dockerfile = (Path(__file__).resolve().parents[1] / "Dockerfile").read_text(encoding="utf-8")
|
||||||
self.assertIn("fonts-noto-cjk", dockerfile)
|
self.assertIn("fonts-noto-cjk", dockerfile)
|
||||||
|
|
||||||
|
def test_drawtext_label_style_stays_small_and_translucent(self) -> None:
|
||||||
|
filter_text = alarm_snapshots.build_drawtext_filter(
|
||||||
|
[
|
||||||
|
alarm_snapshots.OverlayLabel(
|
||||||
|
text="区域 1",
|
||||||
|
fallback_text="R1",
|
||||||
|
x=10,
|
||||||
|
y=20,
|
||||||
|
accent_rgb=(255, 196, 0),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
Path("/tmp/NotoSansCJK-Regular.ttc"),
|
||||||
|
height=360,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertIn("fontsize=13", filter_text)
|
||||||
|
self.assertIn("boxcolor=black@0.34", filter_text)
|
||||||
|
self.assertIn("boxborderw=2", filter_text)
|
||||||
|
|
||||||
def test_capture_alert_snapshot_encodes_frame_with_configured_calibration_overlay(self) -> None:
|
def test_capture_alert_snapshot_encodes_frame_with_configured_calibration_overlay(self) -> None:
|
||||||
encoded_frames: list[Frame] = []
|
encoded_frames: list[Frame] = []
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user