feat(work_plane gui): show fit inliers as blue scatter in 3D, drop wrong plane mesh
The 0.4x0.4 PlaneGeometry square was a fixed-size proxy that did not reflect the actual ROI extent — visually misleading. Replace it with an explicit blue point cloud of the inliers fed to fit_plane_svd, so the user can see *exactly* which depth pixels the plane was fit on. - Backend: fit response now returns fit_points_camera (CV frame) instead of the (parallax-shifted) RGB pixel projection. - Frontend: drop the purple plane mesh; new three.setFitInliers paints the inliers in blue. The RGB overlay no longer carries blue dots. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
4a83305b5e
commit
767d91acdc
3 files changed
+44
-53
No files matched your search
@@ -11,7 +11,6 @@ from fastapi import APIRouter, HTTPException
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from ..perception import filter_outliers, nuwa_to_cv_frame
|
||||
from ..perception.projection import K_from_intrinsics, project_camera_to_pixels
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
from ..perception.work_plane import (
|
||||
@@ -113,32 +112,13 @@ def fit(req: FitReq) -> dict[str, Any]:
|
||||
idx = np.random.choice(len(scene_cv), req.max_preview_points, replace=False)
|
||||
scene_cv = scene_cv[idx]
|
||||
|
||||
# Project the inliers used for the fit back to RGB pixels so the GUI can
|
||||
# overlay them on the live image (verify visually which depth pixels were
|
||||
# actually fed to fit_plane_svd). NOTE: pointcloud_roi's docstring claims
|
||||
# CV frame, but in practice the raw `pc` arrives in Nuwa native frame
|
||||
# (Z<0 forward). After nuwa_to_cv_frame + outlier mask, `pts_cv` is the
|
||||
# canonical CV-frame inlier set, so use it.
|
||||
fit_points_px: list[list[int]] = []
|
||||
try:
|
||||
intr_full = nuwa.intrinsics()
|
||||
rgb_intr = intr_full.get("rgb")
|
||||
if rgb_intr and rgb_intr.get("fx") and rgb_intr.get("cx"):
|
||||
# Inject width/height so K_from_intrinsics has all required keys.
|
||||
W = int(rgb_intr.get("width", 640))
|
||||
H = int(rgb_intr.get("height", 480))
|
||||
rgb_intr = {**rgb_intr, "width": W, "height": H}
|
||||
K = K_from_intrinsics(rgb_intr)
|
||||
with sw.step("project_inliers"):
|
||||
fit_points_px = project_camera_to_pixels(pts_cv, K, (W, H)).tolist()
|
||||
except Exception as e:
|
||||
log.warning("could not project fit inliers to RGB pixels: %s", e)
|
||||
|
||||
return {
|
||||
"plane": asdict(wp),
|
||||
"preview": True,
|
||||
"points_camera": scene_cv.tolist(),
|
||||
"fit_points_px": fit_points_px,
|
||||
# 3D inliers actually used for fit_plane_svd, in CV camera frame.
|
||||
# The GUI scatters these in blue inside the 3D viewer.
|
||||
"fit_points_camera": pts_cv.tolist(),
|
||||
"timings_ms": sw.as_dict(),
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user