Seam Blending#

ERP panoramas wrap horizontally, so the left and right image boundaries are adjacent in 3D. Standard CNN padding can cause a visible seam in predicted depth at that wrap boundary.

panodac includes a Poisson-based seam correction that operates in the gradient domain and solves a narrow band around the seam.

Usage#

Use the built-in panorama seam correction (default)#

import panodac

# Enabled by default for panoramas
depth = panodac.predict("panorama.jpg")

# Disable if you want raw output
depth_raw = panodac.predict("panorama.jpg", fix_panorama_seam=False)

Apply seam correction as a post-process#

from panodac.seam_blending import fix_panorama_seam

depth_fixed = fix_panorama_seam(depth_raw, blend_width=32)

Tuning: prevent DC/mean drift with anchoring#

Poisson blending can drift in absolute scale (DC offset). The seam solver uses a screened Poisson anchoring term controlled by anchor_strength:

  • Higher anchor_strength → less drift / less change to the original depth in the seam band
  • Lower anchor_strength → more freedom to match gradients (can improve seam smoothness)
from panodac.seam_blending import fix_panorama_seam

depth_fixed = fix_panorama_seam(
    depth_raw,
    blend_width=32,
    anchor_strength=1e-3,  # default
)

API#

fix_panorama_seam #

fix_panorama_seam(depth: ndarray, blend_width: int | None = None, *, anchor_strength: float = 0.001) -> np.ndarray

Convenience wrapper to fix ERP panorama depth seam artifacts.

Parameters:

Name Type Description Default
depth ndarray

(H, W) depth map.

required
blend_width int | None

Half-width of the solve band. If None, auto-pick from width.

None
Source code in src/panodac/seam_blending.py
def fix_panorama_seam(
    depth: np.ndarray,
    blend_width: int | None = None,
    *,
    anchor_strength: float = 1e-3,
) -> np.ndarray:
    """
    Convenience wrapper to fix ERP panorama depth seam artifacts.

    Args:
        depth: (H, W) depth map.
        blend_width: Half-width of the solve band. If None, auto-pick from width.
    """
    depth_f = _as_float32_depth(depth)
    H, W = depth_f.shape
    bw = _recommended_blend_width(W) if blend_width is None else int(blend_width)
    blender = PoissonSeamBlender(blend_width=bw, anchor_strength=float(anchor_strength))
    return blender.blend(depth_f)

PoissonSeamBlender dataclass #

PoissonSeamBlender(blend_width: int = 32, anchor_strength: float = 0.001, _cached_shape: tuple[int, int] | None = None, _cached_A: csr_matrix | None = None)

Poisson blending seam fixer for ERP panoramic depth maps.

Parameters:

Name Type Description Default
blend_width int

Half-width (in pixels) of the solve band around the seam after rolling. Total solved band width = 2 * blend_width.

32