@@ -1565,7 +1565,9 @@ Implementation notes:
15651565### Distance Transforms
15661566
15671567` bioimage-cpp ` exposes exact binary Euclidean distance transforms under
1568- ` bic.distance ` .
1568+ ` bic.distance ` . The implementation uses the separable
1569+ Felzenszwalb–Huttenlocher algorithm, complexity O(N · ndim), with optional
1570+ multithreading across the orthogonal lines of each axis sweep.
15691571
15701572SciPy / vigra:
15711573
@@ -1582,7 +1584,19 @@ bioimage-cpp:
15821584``` python
15831585import bioimage_cpp as bic
15841586
1587+ # One call can return any combination of distances, feature indices, and
1588+ # difference vectors — the C++ kernel computes them in a single sweep.
15851589dist = bic.distance.distance_transform(mask, sampling = (2.0 , 1.0 ))
1590+ dist, idx, vec = bic.distance.distance_transform(
1591+ mask,
1592+ sampling = (2.0 , 1.0 ),
1593+ return_distances = True ,
1594+ return_indices = True ,
1595+ return_vectors = True ,
1596+ )
1597+
1598+ # Short alias kept for parity with vigra; equivalent to the call above with
1599+ # return_distances=False, return_indices=False, return_vectors=True.
15861600vec = bic.distance.vector_difference_transform(mask, sampling = (2.0 , 1.0 ))
15871601```
15881602
@@ -1595,14 +1609,33 @@ Name mapping:
15951609
15961610Important differences:
15971611
1598- - Distance-valued outputs are ` float32 ` , not SciPy's ` float64 ` .
1612+ - Distance-valued outputs are ` float32 ` , not SciPy's ` float64 ` . Indices are
1613+ ` int32 ` with shape ` (ndim, *mask.shape) ` (matches SciPy's layout). Vectors
1614+ are ` float32 ` with shape ` (*mask.shape, ndim) ` ; components are sampled
1615+ displacements ` (feature_coord - pixel_coord) * sampling[ax] ` per axis.
15991616- ` distance_transform ` follows SciPy's binary convention: nonzero values are
16001617 foreground and distances are measured to the nearest zero-valued element.
1601- - ` vector_difference_transform ` returns ` float32 ` vectors with shape
1602- ` mask.shape + (mask.ndim,) ` . Components are sampled displacements from each
1603- foreground element to its nearest zero-valued element in NumPy axis order.
1604- - The initial implementation prioritizes correctness and API coverage over
1605- performance; benchmarks and optimized kernels are planned separately.
1618+ ` bool ` and ` uint8 ` C-contiguous inputs are fast-pathed without a copy;
1619+ other dtypes are converted via ` array != 0 ` .
1620+ - A single ` distance_transform ` call can return any non-empty subset of
1621+ ` distances ` , ` indices ` , and ` vectors ` via the corresponding
1622+ ` return_distances ` / ` return_indices ` / ` return_vectors ` flags. The result
1623+ is the array itself when only one output is requested, otherwise a tuple
1624+ in ` (distances, indices, vectors) ` order with omitted entries skipped.
1625+ - Pre-allocated output buffers are supported via the ` distances= ` ,
1626+ ` indices= ` , and ` vectors= ` keyword arguments. They must be C-contiguous,
1627+ writable, of the documented shape and dtype, and are written into in
1628+ place. Pre-allocated outputs are excluded from the return value (matching
1629+ SciPy's convention); the call returns ` None ` if every requested output
1630+ was preallocated.
1631+ - ` number_of_threads ` selects the thread count for the per-axis sweep.
1632+ ` 1 ` (the default) is single-threaded; ` 0 ` uses
1633+ ` std::thread::hardware_concurrency() ` ; positive values pin an explicit
1634+ count. Output is deterministic and bitwise identical across thread counts.
1635+ - For an all-foreground input (no zero-valued elements), the result matches
1636+ SciPy: distances and indices report a virtual background point at
1637+ axis-0 coordinate ` -1 ` and ` 0 ` on all other axes. The first row of
1638+ ` indices ` will then contain ` -1 ` everywhere.
16061639
16071640## I/O and Build Dependencies
16081641
0 commit comments