Skip to content

Filter Point Cloud Using Oriented Bounding Box

SUMMARY

Filter Point Cloud Using Oriented Bounding Box keeps only the points that fall inside a rotated (oriented) 3D box.

Like filter_point_cloud_using_bounding_box, but the box can be rotated to any orientation instead of staying aligned with the world's X/Y/Z axes — use this when the region of interest is a box-shaped object that isn't axis-aligned, such as the result of calculate_oriented_bounding_box, or a box built manually from a known center, size, and rotation.

Use this Skill when you want to crop a point cloud to a box-shaped region that is rotated relative to the world axes.

The Skill

python
from telekinesis import vitreous, datatypes

x_min, y_min, z_min, x_max, y_max, z_max = -0.1, -0.1, -0.1, 0.1, 0.1, 0.1
roll_deg, pitch_deg, yaw_deg = 0.0, 0.0, 45.0
oriented_bbox = datatypes.OrientedBox3D.from_xyzxyz(
    [x_min, y_min, z_min, x_max, y_max, z_max, roll_deg, pitch_deg, yaw_deg]
)

filtered_point_cloud = vitreous.filter_point_cloud_using_oriented_bounding_box(
    point_cloud=point_cloud,
    oriented_bbox=oriented_bbox,
)
API Reference
Full parameter and return type documentation for filter_point_cloud_using_oriented_bounding_box.
View Reference →

Data Transfer Notice

There is no longer a fixed limit of 1 million points per request. However, very large datasets may result in slower data transfer and processing times. We are continuously optimizing performance as part of our beta program, with ongoing improvements to enhance speed and reliability.

Example

Raw Sensor Input

Unprocessed point cloud captured directly from the sensor. Shows full resolution, natural noise, and uneven sampling density.

Oriented Bounding Box

Oriented bounding box in red overlayed with the unprocessed point cloud.

Filtered Points

Only the points that fall within the specified 3D box defined are kept.

The Code

python
"""
Demonstrates filtering points within an oriented (rotated) bounding box.
"""

from loguru import logger
import rerun as rr

from telekinesis import vitreous, datatypes


def filter_point_cloud_using_oriented_bounding_box_example():
    """
    Filters points within an oriented (rotated) bounding box.

    Keeps only points within a 3D box that can be rotated to any orientation.
    """
    # ===================== Load Data ==========================================
    point_cloud_url = "https://assets.telekinesis.ai/examples/v1/point_clouds/can_vertical_3_downsampled.ply"
    point_cloud = datatypes.PointCloud.from_url(url=point_cloud_url, use_cache=True)

    # ===================== Run Skill ==========================================
    x_min, y_min, z_min = -205.65248652, -112.59310319, 554.42936219
    x_max, y_max, z_max = 121.88022318, -17.60647882, 698.54912862
    rot_x, rot_y, rot_z = -38.1245801, -7.89877607, -7.74440359
    bbox = [x_min, y_min, z_min, x_max, y_max, z_max, rot_x, rot_y, rot_z]
    oriented_bbox = datatypes.OrientedBox3D.from_xyzxyz(bbox)

    filtered_point_cloud = vitreous.filter_point_cloud_using_oriented_bounding_box(
        point_cloud=point_cloud, oriented_bbox=oriented_bbox
    )

    # ===================== Log ================================================
    logger.success(f"Filtered {point_cloud} using oriented bounding box")
    logger.success(f"Results: {filtered_point_cloud}")
    logger.info(
        f"Filtered point cloud positions shape: {filtered_point_cloud.positions.shape}"
    )
    logger.info(
        f"Filtered point cloud has normals shape: "
        f"{filtered_point_cloud.normals.shape if filtered_point_cloud.has_normals else None}"
    )
    logger.info(
        f"Filtered point cloud has colors shape: "
        f"{filtered_point_cloud.colors.shape if filtered_point_cloud.has_colors else None}"
    )

    # ===================== Visualization  (Optional) ===========================
    rr.init("filter_point_cloud_using_oriented_bounding_box_example", spawn=True)
    datatypes.visualize(point_cloud, entity_path="/1-input_point_cloud")
    datatypes.visualize(oriented_bbox, entity_path="/2-oriented_bounding_box")
    datatypes.visualize(filtered_point_cloud, entity_path="/3-filtered_point_cloud")


if __name__ == "__main__":
    filter_point_cloud_using_oriented_bounding_box_example()

Runnable examples are available in the Telekinesis examples repository.

Follow the README in that repository to set up the environment, run this specific example with:

bash
cd telekinesis-examples
python examples/point_cloud/filter_point_cloud_using_oriented_bounding_box.py

Parameter Configuration

oriented_bbox is checked as a single rotated 3D box, not decomposed into separate scalar knobs.

ParameterTypeDefaultDescription
point_clouddatatypes.PointCloudrequiredThe point cloud to filter
oriented_bboxdatatypes.OrientedBox3DrequiredThe rotated box to keep points within, in its native [cx, cy, cz, width, height, depth, roll_deg, pitch_deg, yaw_deg] layout (center, size, and Euler-XYZ rotation in degrees); construct one from min/max corners plus rotation with datatypes.OrientedBox3D.from_xyzxyz([x_min, y_min, z_min, x_max, y_max, z_max, roll_deg, pitch_deg, yaw_deg]) if needed

Returns

TypeDescription
datatypes.PointCloudA point cloud containing only the points that fell inside oriented_bbox; returns an empty datatypes.PointCloud if none did. Use .positions for the surviving (N, 3) position array and len(...) for the point count.

Raises

ExceptionCondition
TypeErrorpoint_cloud is not a datatypes.PointCloud, or oriented_bbox is not a datatypes.OrientedBox3D (see the Parameter Configuration table above)
ConfigurationErrorThe TELEKINESIS_API_KEY environment variable is not set
SerializationErrorThe request input failed to serialize, the response was not returned as an Arrow stream, or the response failed to deserialize
RequestTimeoutErrorThe request to the Vitreous service timed out
TransportErrorA network failure occurred before a response was received
ClientErrorThe Vitreous service rejected the request due to invalid or malformed input (HTTP 400/422), an unrecognized endpoint (HTTP 404), or another unexpected 4xx response
AuthenticationErrorThe API key was rejected as invalid or expired (HTTP 401)
AuthenticationServiceErrorThe authentication service returned an invalid response, was temporarily unavailable, or timed out (HTTP 502/503/504)
ServerErrorThe Vitreous service returned a 5xx or otherwise unexpected error response

How to Tune the Parameters

filter_point_cloud_using_oriented_bounding_box has no numeric threshold to tune — oriented_bbox is an input defining the rotated region to keep, not a knob with a range to sweep. What you control is the box itself:

oriented_bbox

  • Controls: Which points are kept — everything inside the rotated box's extent survives, everything outside is removed.
  • Construct it from min/max corners plus a rotation with datatypes.OrientedBox3D.from_xyzxyz([x_min, y_min, z_min, x_max, y_max, z_max, roll_deg, pitch_deg, yaw_deg]), or directly from a center [cx, cy, cz], size [width, height, depth], and rotation [roll_deg, pitch_deg, yaw_deg] as datatypes.OrientedBox3D([cx, cy, cz, width, height, depth, roll_deg, pitch_deg, yaw_deg]), or reuse an existing box, such as the result of calculate_oriented_bounding_box.
  • Enlarge the size (width/height/depth) to include more points; shrink it to include fewer.
  • Adjust the center [cx, cy, cz] to reposition the box without changing its size or rotation.
  • Adjust the rotation (roll_deg/pitch_deg/yaw_deg, Euler-XYZ angles in degrees) to align the box with the object's actual orientation.

TIP

If the region of interest turns out to be axis-aligned after all, filter_point_cloud_using_bounding_box (or filter_point_cloud_using_pass_through_filter) skips specifying a rotation entirely and is simpler to construct.

Where to Use the Skill

Common pipelines include:

  • Rotated part isolation – Cropping a part on an assembly line that isn't aligned with the world axes
  • Reusing a computed oriented box – Feeding the output of calculate_oriented_bounding_box straight into filtering
  • Tilted-object inspection – Focusing on an object scanned at an angle without first re-aligning the whole scene
  • Hand-held tool extraction – Isolating a tool or part held at an arbitrary orientation for manipulation

Alternative Skills

Skillvs. Filter Point Cloud Using Oriented Bounding Box
filter_point_cloud_using_bounding_boxUses an axis-aligned datatypes.Box3D instead — simpler and faster when the region of interest is already aligned with the world's X/Y/Z axes.
filter_point_cloud_using_pass_through_filterTakes six separate axis-aligned min/max scalars instead of a rotatable box object — the simplest option when no rotation is needed.

When Not to Use the Skill

Do not use Filter Point Cloud Using Oriented Bounding Box when:

  • The region of interest is already axis-alignedfilter_point_cloud_using_bounding_box or filter_point_cloud_using_pass_through_filter is simpler and avoids specifying a rotation
  • You only have loose min/max scalars, not a box objectfilter_point_cloud_using_pass_through_filter takes those directly
  • You need to filter by distance from a plane rather than a box – use filter_point_cloud_using_plane_proximity or filter_point_cloud_using_plane_defined_by_point_normal_proximity instead
  • oriented_bbox isn't a valid datatypes.OrientedBox3D – a TypeError is raised if point_cloud isn't a datatypes.PointCloud or oriented_bbox isn't a datatypes.OrientedBox3D