Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .cursor/rules/git-commit.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
description: Git commit message preferences for this project
alwaysApply: true
---

# Git Commits

When creating git commits in this project:

- Do **not** add `Co-authored-by: Cursor` (or any Cursor co-author trailer) to commit messages.
- Keep commit messages focused on the change itself, following the repository's existing style.
75 changes: 75 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,81 @@ removed no sooner than the next major (see `docs/API_STABILITY.md`).

### Added

- **Canonical 2D → AI → 3D roadmap and image IO (Epic 83)**: `docs/ROADMAP.md`
reserves Epics 83–90; new `spatialrust-image-io` provides bounded path,
reader/writer, and memory PNG/JPEG/PNM codecs, independently gated TIFF and
OpenEXR, typed pixels, Exif orientation handling, Python/NumPy bindings,
property tests, and 640p/1080p/4K decode benchmarks.

- **Shared CPU filters (Epic 84A–84B)**: `spatialrust-vision` now exposes a
common `BorderMode`, validated 1D/2D kernels, OpenCV-style filter2D
correlation, explicit convolution, f32-output and separable filters, and
normalized box/Gaussian blur, median and bilateral filters, signed
Sobel/Scharr/Laplacian derivatives, and Gaussian pyramids. The feature
includes strided-view property coverage, Python bindings/stubs, OpenCV
comparison, and 640p/1080p/4K benchmarks.

- **CPU morphology (Epic 84C)**: validated rectangular, cross, elliptical,
diamond, and custom structuring elements; explicit-anchor erode/dilate;
open/close/gradient/top-hat/black-hat operations; additive feature and meta
feature; u8/u16/f32 and strided-view tests; Python bindings; exact OpenCV
comparisons; and 640p/1080p/4K benchmarks.

- **CPU image analysis (Epic 84D)**: fixed and adaptive thresholds, u8/u16
Otsu selection, masked configurable histograms, exact u8 equalization,
contrast-limited adaptive equalization, and checked summed-area tables;
additive Rust/meta features, Python bindings/stubs, strided properties,
OpenCV comparisons, and representative-resolution benchmarks.

- **Canny edge detection (Epic 84E)**: configurable 3/5/7 Sobel apertures,
L1/L2 gradient magnitude, directional non-maximum suppression, 8-neighbor
hysteresis, and inspectable intermediate stages; additive Rust/meta features,
strided and property tests, Python binding/stub, 640p/1080p/4K benchmark, and
exact OpenCV comparison across all six aperture/magnitude combinations.

- **Tensor foundation (Epic 85A)**: new dependency-light `spatialrust-tensor`
crate with byte-addressable dtype, arbitrary-rank shape, signed element
strides, checked byte offsets/spans, explicit device identity, safe borrowed
CPU views, and named owned copies. Non-host device memory cannot be exposed as
a Rust byte slice, and the meta-crate integration is opt-in through `tensor`.

- **Image/spatial tensor bridges (Epic 85B)**: packed interleaved images expose
zero-copy HWC views, packed planar images expose zero-copy CHW views, and
Schema-SoA `f32` point fields expose zero-copy one-dimensional views. Explicit
`pack_*` operations handle padded/ROI images, with feature-alone tests and
640p/1080p/4K packing benchmarks.

- **DLPack and Python tensor interoperability (Epic 85C–85D)**: audited
`DLManagedTensorVersioned` major-version 1 CPU import/export, explicit deleter
transfer, read-only/copy flags, signed strides and byte offsets, malformed ABI
rejection, and zero-copy Python `__dlpack__`/`__dlpack_device__`. NumPy and
PyTorch round trips preserve allocations and producer lifetimes; device or
host copy requests remain explicit.

- **Inference contracts and ONNX Runtime CPU (Epic 86)**: new optional
`spatialrust-ai` crate with named dynamic model metadata, stable backend and
session traits, explicit input/output copy permissions, CPU ONNX Runtime,
separately gated CUDA/TensorRT/DirectML providers, typed zero-copy I/O
Binding, caller-preallocated u8/u16/f32 outputs, runtime-allocation retention,
output-to-input chaining, Python bindings/stubs, reference-runtime comparison,
and 640p/1080p/4K Criterion coverage. Multi-byte raw storage is rejected at
zero-copy boundaries instead of being cast from an under-aligned byte buffer.

- **Feature2D and ORB matching (Epic 87)**: checked keypoint, binary/float
descriptor, feature-set, and match contracts; Harris and Shi–Tomasi corners;
OpenCV-exact FAST-9/16 detection and scores; deterministic multi-scale ORB
with 256-bit rotated BRIEF; Hamming/L2 brute-force matching with ratio,
cross-check, and distance filters; Python/NumPy bindings and stubs; property
tests, OpenCV comparison, and 640p/1080p/4K Criterion baselines.

- **Camera geometry, motion, and stereo (Epic 88)**: checked correspondence and
projective contracts; normalized DLT and deterministic RANSAC for homography,
fundamental, and essential matrices; triangulation and essential pose
disambiguation; EPnP-class PnP with iterative refine and RANSAC; sparse
pyramidal Lucas–Kanade tracking; stereo rig, rectify remap grids, SAD block
matching, and disparity-to-depth/XYZ reproject; Python bindings; OpenCV
comparison with documented tolerances; property tests; and Criterion coverage.

- **AI-ready image and vision foundation (Epics 75–79)**: mutable ROI views,
planar/interleaved layouts and color metadata in `spatialrust-image`; new
feature-gated `spatialrust-vision` preprocessing, warp, detection, mask/RLE,
Expand Down
10 changes: 10 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ members = [
"crates/spatialrust-transform",
"crates/spatialrust-voxelize",
"crates/spatialrust-image",
"crates/spatialrust-image-io",
"crates/spatialrust-tensor",
"crates/spatialrust-ai",
"crates/spatialrust-camera",
"crates/spatialrust-vision",
]
Expand Down Expand Up @@ -47,6 +50,9 @@ spatialrust-metrics = { path = "crates/spatialrust-metrics", version = "1.0.0",
spatialrust-transform = { path = "crates/spatialrust-transform", version = "1.0.0", default-features = false }
spatialrust-voxelize = { path = "crates/spatialrust-voxelize", version = "1.0.0", default-features = false }
spatialrust-image = { path = "crates/spatialrust-image", version = "1.0.0" }
spatialrust-image-io = { path = "crates/spatialrust-image-io", version = "1.0.0", default-features = false }
spatialrust-tensor = { path = "crates/spatialrust-tensor", version = "1.0.0", default-features = false }
spatialrust-ai = { path = "crates/spatialrust-ai", version = "1.0.0", default-features = false }
spatialrust-camera = { path = "crates/spatialrust-camera", version = "1.0.0" }
spatialrust-vision = { path = "crates/spatialrust-vision", version = "1.0.0", default-features = false }

Expand All @@ -63,6 +69,10 @@ thiserror = "2"
wgpu = "24"
criterion = { version = "0.5", features = ["html_reports"] }
proptest = "1"
image = { version = "0.24.9", default-features = false }
kamadak-exif = "0.6.1"
exr = { version = "=1.72.0", default-features = false }
tempfile = "3"

[profile.release]
lto = "thin"
Expand Down
25 changes: 24 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,11 @@ One dataflow, focused crates — each pipeline stage maps to the crate that impl
| `spatialrust-core` | Point schema, metadata, execution traits |
| `spatialrust-math` | Vec/Mat/Pose math primitives |
| `spatialrust-image` | Typed image buffers and zero-copy strided views |
| `spatialrust-image-io` | Bounded PNG/JPEG/PNM codecs; opt-in TIFF/OpenEXR |
| `spatialrust-tensor` | Runtime-independent dtype/shape/stride/device ownership and DLPack |
| `spatialrust-ai` | Explicit-copy inference contracts and opt-in ONNX Runtime providers |
| `spatialrust-camera` | Pinhole/Brown–Conrady camera models and RGB-D conversion |
| `spatialrust-vision` | Resize/preprocess, warps, detection postprocess, masks, and dense spatial maps |
| `spatialrust-vision` | CPU filters, Feature2D/ORB matching, resize/preprocess, warps, detection postprocess, masks, and dense spatial maps |
| `spatialrust-io` | Point cloud readers/writers (PCD, PLY, LAS, COPC) |
| `spatialrust-search` | KD-tree search, k-NN / radius graphs |
| `spatialrust-filtering` | Voxel / FPS downsample, outlier removal, crop, MLS |
Expand Down Expand Up @@ -220,6 +223,26 @@ The reproducible algorithm comparison is in
`bench/opencv_vision_comparison/`; the complete synthetic demo is
`crates/spatialrust-py/examples/vision_ai_pipeline.py`.

The same feature includes Harris, Shi–Tomasi, exact FAST-9/16, multi-scale ORB,
and checked Hamming/L2 descriptor matching. Python exposes `orb_features` and
NumPy matcher functions; OpenCV is used only by the numerical comparison suite.

An ONNX Runtime wheel is opt-in (`maturin develop --features onnxruntime`). Its
Python API uses named CPU I/O Binding by default; `copy=True` is the explicit
fallback for inputs that must be repacked:

```python
session = sr.OnnxRuntimeSession("model.onnx", deterministic=True)
input_tensor = sr.tensor_copy_from_numpy(chw)
outputs = session.run({"images": input_tensor})
scores = np.from_dlpack(outputs["scores"])
```

The Rust features are `ai`, `ai-onnxruntime`, and separate
`ai-onnxruntime-{cuda,tensorrt,directml}` provider gates. The optional ONNX
Runtime adapter currently has a feature-specific Rust 1.88 MSRV; it does not
raise the default workspace MSRV.

<p align="center">
<img src="docs/assets/python_segmentation.png" alt="Top-down view of clusters segmented from the public PCL table_scene_lms400 point cloud via a single Python run_pipeline() call" width="540">
</p>
Expand Down
10 changes: 8 additions & 2 deletions bench/opencv_vision_comparison/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
# OpenCV vision comparison

This deterministic harness compares SpatialRust's Python-visible CPU vision
primitives with OpenCV: four resize filters, RGB-to-gray/HSV conversion,
bilinear remap, NMS, and connected-component areas.
primitives with OpenCV: linear, median, and bilateral filters; Sobel, Scharr,
Laplacian, Gaussian pyramids, morphology, thresholds, histograms, CLAHE, integral images,
and Canny across 3/5/7 Sobel apertures and L1/L2 gradients;
Harris, Shi–Tomasi, and FAST-9/16 keypoint coordinates/order (plus exact FAST scores);
Hamming/L2 brute-force nearest matches; ORB keypoint repeatability and descriptor layout;
homography transfer residuals, PnP translation vs OpenCV, and StereoBM center disparity
on a synthetic textured pair; four resize filters; RGB-to-gray/HSV conversion;
bilinear remap; NMS; and connected-component areas.

From the repository root, after installing the editable Python extension:

Expand Down
Loading
Loading