Spaces:
Running on Zero
Running on Zero
| # SPDX-License-Identifier: Apache-2.0 | |
| # Copyright (c) 2026 World Labs. | |
| """Point-cloud post-processing utilities.""" | |
| from __future__ import annotations | |
| import numpy as np | |
| def statistical_outlier_mask(points: np.ndarray, *, num_neighbors: int = 5, | |
| std_ratio: float = 1.0) -> np.ndarray: | |
| """Boolean inlier mask via statistical outlier rejection. | |
| For each point, the mean distance to its ``num_neighbors`` nearest | |
| neighbours is computed; a point is an outlier when that mean exceeds | |
| ``global_mean + std_ratio * global_std``. This removes the flying-pixel | |
| floaters that back-projected depth produces at depth discontinuities. | |
| Mirrors Open3D's ``remove_statistical_outlier``. | |
| Args: | |
| points: ``(N, 3)`` float array. | |
| num_neighbors: neighbours used to estimate each point's local spacing. | |
| std_ratio: smaller is more aggressive (keeps fewer points). | |
| Returns: | |
| ``(N,)`` boolean mask, ``True`` for inliers. | |
| """ | |
| n = len(points) | |
| if n <= num_neighbors: | |
| return np.ones(n, dtype=bool) | |
| # Lazy import: only point-cloud export needs scipy. | |
| from scipy.spatial import cKDTree | |
| tree = cKDTree(points) | |
| # k + 1: the nearest neighbour is the point itself (distance 0); drop it. | |
| dists, _ = tree.query(points, k=num_neighbors + 1, workers=-1) | |
| mean_dist = dists[:, 1:].mean(axis=1) | |
| threshold = mean_dist.mean() + std_ratio * float(mean_dist.std()) | |
| return mean_dist <= threshold | |
| def depth_edge_mask(depth: np.ndarray, *, rtol: float = 0.04, | |
| kernel_size: int = 3) -> np.ndarray: | |
| """Boolean mask, ``True`` on depth-discontinuity pixels. | |
| A pixel is an edge when the local depth range (max − min over a | |
| ``kernel_size`` window) exceeds ``rtol`` of its depth. Removing these | |
| pixels *before* back-projection deletes the occlusion-boundary "veils" | |
| that bridge foreground→background — the connected floaters that | |
| statistical outlier rejection cannot catch (they have close neighbours). | |
| Mirrors MoGe / utils3d ``depth_edge`` (``rtol`` path). | |
| """ | |
| from scipy.ndimage import maximum_filter, minimum_filter | |
| local_range = (maximum_filter(depth, size=kernel_size) | |
| - minimum_filter(depth, size=kernel_size)) | |
| return local_range > rtol * np.maximum(depth, 1e-6) | |