refactor(sam21_bridge): extract segment_with_sam21 (no plane filter)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Adriano Dal PastroandClaude Opus 4.7 committed 2026-05-13 10:06:41 +02:00
1 parent 684bd2de5e
commit 87abe26476
2 files changed
+121 -12

No files matched your search

+28 -12
View File
@@ -7,6 +7,7 @@ clients built per-request via api/_deps.py.
from __future__ import annotations
import logging
from dataclasses import dataclass
import cv2
import httpx
@@ -31,18 +32,20 @@ SAM21_BUG_CODES = frozenset({"SHAPE_MISMATCH", "BBOX_OUT_OF_BOUNDS",
"IMAGE_DECODE_ERROR", "INVALID_INPUT"})
def points_via_sam21(nuwa, sam21, bbox: tuple[int, int, int, int],
sw: Stopwatch) -> tuple[np.ndarray, dict]:
"""SAM21 path: bbox → segmented point cloud in RGB-camera/OpenCV frame.
@dataclass
class Sam21Segmentation:
"""Output di segment_with_sam21 — SAM21 puro senza plane filter."""
points_cv_m: np.ndarray # (N,3) OpenCV camera frame, metri
rgb_jpeg: bytes # snapshot Nuwa usato per la segmentazione
intrinsics_rgb: dict # con width/height iniettati dal decoded RGB
Returns points in **meters**. Raises Sam21Fallback on failures that
should trigger the bbox path. Re-raises HTTPException(502) for Nuwa
failures (the bbox path would fail too — better to fail fast). All
SAM21-specific logging happens here; callers do not log on fallback.
After the SAM21 segmentation the work-plane filter is applied (no-op if no
plane is calibrated). Returns (points, plane_info) where plane_info has
`plane_applied` and `n_points_before_plane`.
def segment_with_sam21(nuwa, sam21, bbox: tuple[int, int, int, int],
sw: Stopwatch) -> Sam21Segmentation:
"""SAM21 puro: nuwa_grab + depth_align + segment, SENZA plane filter.
Raises Sam21Fallback per failure semantiche (mask vuota, no depth, SAM21
unreachable, decode fail). Re-raises HTTPException(502) per failure Nuwa.
"""
try:
with sw.step("nuwa_grab"):
@@ -105,7 +108,7 @@ def points_via_sam21(nuwa, sam21, bbox: tuple[int, int, int, int],
with sw.step("sam21"):
try:
pts_cv = sam21.segment_pointcloud(
pts_cv_m = sam21.segment_pointcloud(
rgb_png=rgb_png,
depth_png=depth_png_out,
intrinsics=intr_full["rgb"],
@@ -125,7 +128,20 @@ def points_via_sam21(nuwa, sam21, bbox: tuple[int, int, int, int],
log.error("Unexpected SAM21 error: %r", e)
raise Sam21Fallback(f"unexpected: {e!r}") from e
pts_cv, plane_info = apply_below_plane_filter(pts_cv, get_work_plane())
return Sam21Segmentation(
points_cv_m=pts_cv_m,
rgb_jpeg=rgb_jpeg,
intrinsics_rgb=intr_full["rgb"],
)
def points_via_sam21(nuwa, sam21, bbox: tuple[int, int, int, int],
sw: Stopwatch) -> tuple[np.ndarray, dict]:
"""Legacy wrapper: segment_with_sam21 + apply_below_plane_filter.
Returns (points_cv_m, plane_info). Raises Sam21Fallback if <10 points
after plane filter (unchanged semantics)."""
seg = segment_with_sam21(nuwa, sam21, bbox, sw)
pts_cv, plane_info = apply_below_plane_filter(seg.points_cv_m, get_work_plane())
if pts_cv.shape[0] < 10:
log.warning("SAM21 cloud has %d points after plane filter (<10), falling back to bbox",
pts_cv.shape[0])