pub struct MergingWatershed<T = ()> { /* private fields */ }
Expand description

Implementation of the merging watershed algorithm.

See crate-level documentation for a general introduction to the algorithm.

The merging watershed transform is a slight variation on the segmenting algorithm (see docs of the SegmentingWatershed struct). Instead of creating a wall whenever two lakes meet, the merging watershed transform merges the two lakes.

On a statistics level, the main difference between the merging and segmenting watershed transforms is that the number of distinct lakes in the merging watershed transform depends on the features in the image rather than the number of (somewhat arbitrarily chosen) lake-seeds. Therefore, one can do statistics with the number of lakes. In addition, the output of the merging transform does not depend strongly on the precise way the minima were chosen.

Memory usage

The watershed transform creates an Array2<usize> of the same size as the input array, which takes up a considerable amount of memory. In addition, it allocates space for a colour-map (Vec<usize> with a length equal to the number of seeds) and some other intermediate, smaller vec’s. One can count on the memory usage being about ~2.5x the size of the input array.

Memory usage of transform_history

The transform_history method makes a copy of the Array2<usize> image used during the watershed transform to keep track of the intermediate images. As such, it allocates a new Array2<usize> for each water level, which increases memory usage by a factor equal to the maximum water level as configured by the TransformBuilder.

Output

The three methods of the Watershed trait each return a different set of parameters based on the watershed transform of the input image:

  • transform simply returns the watershed transform of the image. This is not very interesting in the case of the merging watershed transform, since its output is just an image with all pixels having the same colour.
  • transform_to_list returns a list of the areas of all the lakes at each water level. Its return type isVec<(u8, Vec<usize>)>, where the u8 equals the water level and the Vec<usize> is the list of areas of all the lakes at each water level. The Vec<usize> is the same length for each water level, but may contain zero-sided lakes. The water levels are returned in order.
  • transform_history returns a list of intermediate images of the watershed transform at every water level. Its return type is Vec<(u8, ndarray::Array2<usize>), where the u8 holds the water level that each Array2 snapshot was taken at. The water levels are returned in order.

Artifacts and peculiarities

Due to some implementation details, the 1px-wide edges of the input array are not accessible to the watershed transform. They will thus remain unfilled for the entire duration of the transform.

A workaround can be enabled by calling enable_edge_correction on the TransformBuilder. Enabling this setting copies the input image into a new array, 1px wider on all sides. This padded array is then used as the actual input to the watershed transform. The final output of the transform is a copy of this intermediate array with the padding removed. The padding also does not show up in the output of intermediate plots.

Trait Implementations§

source§

impl<T> Watershed<T> for MergingWatershed<T>

source§

fn transform_with_hook( &self, input: ArrayView2<'_, u8>, seeds: &[(usize, usize)] ) -> Vec<T>

Runs the watershed transform, executing the hook specified by the TransformBuilder (if there is one) each time the water level is raised. The results from running the hook each time are collected into a vec and returned by this function.
source§

fn transform( &self, input: ArrayView2<'_, u8>, _seeds: &[(usize, usize)] ) -> Array2<usize>

Returns watershed transform of input image.
source§

fn transform_history( &self, input: ArrayView2<'_, u8>, seeds: &[(usize, usize)] ) -> Vec<(u8, Array2<usize>)>

Returns a list of images where each image corresponds to a snapshot of the watershed transform at a particular water level. Read more
source§

fn transform_to_list( &self, input: ArrayView2<'_, u8>, seeds: &[(usize, usize)] ) -> Vec<(u8, Vec<usize>)>

Returns a Vec containing the areas of all the lakes per water level. The length of the nested Vec is always equal to the number of seeds, although some lakes may have zero area (especially for the merging transform, see docs for MergingWatershed)
source§

impl<T> WatershedUtils for MergingWatershed<T>

source§

fn pre_processor<T, D>(&self, img: ArrayView<'_, T, D>) -> Array<u8, D>where T: Num + Copy + ToPrimitive + PartialOrd, D: Dimension,

The pre_processor function can convert an array of any numeric data-type T into an array of u8. It converts special float values (if T is a float type) to u8 values that implementations of the watershed transform in this crate know how to handle. Read more
source§

fn pre_processor_with_max<const MAX: u8, T, D>( &self, img: ArrayView<'_, T, D> ) -> Array<u8, D>where T: Num + Copy + ToPrimitive + PartialOrd, D: Dimension,

T into an array of u8. It converts special float values (if T is a float type) to u8 values that implementations of the watershed transform in this crate know how to handle. Read more
source§

fn find_local_minima(&self, img: ArrayView2<'_, u8>) -> Vec<(usize, usize)>

returns a vec of the positions of all the pixels that have a lower value than all their 8-way connected neighbours. Useful for generating seeds for the watershed transform.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

const: unstable · source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

const: unstable · source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

const: unstable · source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere U: From<T>,

const: unstable · source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<T> Pointable for T

§

const ALIGN: usize = mem::align_of::<T>()

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
const: unstable · source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
const: unstable · source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for Twhere V: MultiLane<T>,

§

fn vzip(self) -> V