feat: add world origin triad and explicit render-space mapping to visualization
This commit is contained in:
@@ -75,11 +75,12 @@ Use `--birdseye` for a top-down X-Z view (looking down Y axis).
|
|||||||
uv run visualize_extrinsics.py -i output/extrinsics.json --birdseye --show
|
uv run visualize_extrinsics.py -i output/extrinsics.json --birdseye --show
|
||||||
```
|
```
|
||||||
|
|
||||||
**Ground Plane Overlay:**
|
**Ground Plane & Origin Overlay:**
|
||||||
Render a semi-transparent X-Z ground plane to anchor camera poses.
|
Render a semi-transparent X-Z ground plane and/or a world origin triad.
|
||||||
- `--show-ground/--no-show-ground`: Toggle ground plane (default: show).
|
- `--show-ground/--no-show-ground`: Toggle ground plane (default: show).
|
||||||
- `--ground-y FLOAT`: Set the Y height of the plane (default: 0.0).
|
- `--ground-y FLOAT`: Set the Y height of the plane (default: 0.0).
|
||||||
- `--ground-size FLOAT`: Set the side length of the plane in meters (default: 8.0).
|
- `--ground-size FLOAT`: Set the side length of the plane in meters (default: 8.0).
|
||||||
|
- `--show-origin-axes/--no-show-origin-axes`: Toggle world origin triad (X:red, Y:green, Z:blue) (default: show).
|
||||||
|
|
||||||
*Example: Ground plane at Y=-1.5 with 10m size*
|
*Example: Ground plane at Y=-1.5 with 10m size*
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -474,6 +474,11 @@ def run_diagnostics(poses: Dict[str, np.ndarray], convention: str):
|
|||||||
default=8.0,
|
default=8.0,
|
||||||
help="Size of the ground plane (side length in meters).",
|
help="Size of the ground plane (side length in meters).",
|
||||||
)
|
)
|
||||||
|
@click.option(
|
||||||
|
"--show-origin-axes/--no-show-origin-axes",
|
||||||
|
default=True,
|
||||||
|
help="Show a world-origin axis triad (X:red, Y:green, Z:blue).",
|
||||||
|
)
|
||||||
def main(
|
def main(
|
||||||
input: str,
|
input: str,
|
||||||
output: Optional[str],
|
output: Optional[str],
|
||||||
@@ -491,6 +496,7 @@ def main(
|
|||||||
show_ground: bool,
|
show_ground: bool,
|
||||||
ground_y: float,
|
ground_y: float,
|
||||||
ground_size: float,
|
ground_size: float,
|
||||||
|
show_origin_axes: bool,
|
||||||
):
|
):
|
||||||
"""Visualize camera extrinsics from JSON using Plotly."""
|
"""Visualize camera extrinsics from JSON using Plotly."""
|
||||||
try:
|
try:
|
||||||
@@ -546,6 +552,52 @@ def main(
|
|||||||
intrinsics=cam_intrinsics,
|
intrinsics=cam_intrinsics,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if show_origin_axes:
|
||||||
|
origin = np.zeros(3)
|
||||||
|
axis_len = scale
|
||||||
|
fig.add_trace(
|
||||||
|
go.Scatter3d(
|
||||||
|
x=[origin[0], origin[0] + axis_len],
|
||||||
|
y=[origin[1], origin[1]],
|
||||||
|
z=[origin[2], origin[2]],
|
||||||
|
mode="lines",
|
||||||
|
line=dict(color="red", width=4),
|
||||||
|
name="World X",
|
||||||
|
legendgroup="Origin",
|
||||||
|
showlegend=True,
|
||||||
|
hoverinfo="text",
|
||||||
|
text="World X",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
fig.add_trace(
|
||||||
|
go.Scatter3d(
|
||||||
|
x=[origin[0], origin[0]],
|
||||||
|
y=[origin[1], origin[1] + axis_len],
|
||||||
|
z=[origin[2], origin[2]],
|
||||||
|
mode="lines",
|
||||||
|
line=dict(color="green", width=4),
|
||||||
|
name="World Y",
|
||||||
|
legendgroup="Origin",
|
||||||
|
showlegend=True,
|
||||||
|
hoverinfo="text",
|
||||||
|
text="World Y",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
fig.add_trace(
|
||||||
|
go.Scatter3d(
|
||||||
|
x=[origin[0], origin[0]],
|
||||||
|
y=[origin[1], origin[1]],
|
||||||
|
z=[origin[2], origin[2] + axis_len],
|
||||||
|
mode="lines",
|
||||||
|
line=dict(color="blue", width=4),
|
||||||
|
name="World Z",
|
||||||
|
legendgroup="Origin",
|
||||||
|
showlegend=True,
|
||||||
|
hoverinfo="text",
|
||||||
|
text="World Z",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
if show_ground:
|
if show_ground:
|
||||||
half_size = ground_size / 2.0
|
half_size = ground_size / 2.0
|
||||||
x_grid = np.linspace(-half_size, half_size, 2)
|
x_grid = np.linspace(-half_size, half_size, 2)
|
||||||
@@ -583,10 +635,16 @@ def main(
|
|||||||
eye=dict(x=0, y=2.5, z=0),
|
eye=dict(x=0, y=2.5, z=0),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
render_desc = (
|
||||||
|
"OpenCV: local +X,+Y,+Z (Y-down)"
|
||||||
|
if render_space == "opencv"
|
||||||
|
else "OpenGL: local +X,-Y,-Z (Y-up, Z-back) rel. to OpenCV"
|
||||||
|
)
|
||||||
|
|
||||||
fig.update_layout(
|
fig.update_layout(
|
||||||
title=f"Camera Extrinsics ({pose_convention}, {render_space})",
|
title=f"Camera Extrinsics ({pose_convention})<br><sup>{render_desc}</sup>",
|
||||||
scene=scene_dict,
|
scene=scene_dict,
|
||||||
margin=dict(l=0, r=0, b=0, t=40),
|
margin=dict(l=0, r=0, b=0, t=60),
|
||||||
legend=dict(x=0, y=1),
|
legend=dict(x=0, y=1),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user