Skip to content

Conversation

@tpietzsch
Copy link
Member

This PR adds alpha masks for Sources.

When accumulating multiple sources into a final picture, these can be used to determine whether a rendered pixel comes from inside the source interval (or outside, or which ratio). This can be used for example to do a weighted average of sources such that black background pixels are excluded from the average (but black foreground pixels are not).

There is a new "blend mode" toggle in the UI (new icon in the Display Modes side panel, shortcut "U") that switches between the default "sum" interpolation and the new alpha-weighted "average":

Screenshot 2025-08-08 at 17 12 32 Screenshot 2025-08-08 at 17 12 41

If you set up your own AccumulateProjectorFactory via BdvOptions, this will show up as a third option ("custom") in the blend mode toggle. Custom AccumulateProjectorFactory can override the default boolean requiresMaskedSources() method if they want to have the masked version of the individual sources rendered to then be able to work with the RGBA alpha values. (This is a bit more work, so a bit slower compared to rendering the sources without masks.)

All existing sources just support this without any code change. The default implementations of the new Source.getMaskedSource() and Source.getInterpolatedMaskedSource() methods add a constant 1 mask inside the image interval, then extend that with 0 mask outside.

To make this work, the new Masked<T> types and interpolators from imglib2-8.0.0 are used (see Class hierarchy and interpolation of Masked types (v2) #381).

... by the AccumulateProjectorFactory
combines sources using alpha-weighted average
and fix interpolator selection bug
RandomAccessibleSource and RandomAccessibleSource4D
need special treatment because the underlying data is
in (un-bounded) RandomAccessible. The mask should be 1
everywhere, which is not what AbstractSource.getInterpolatedMaskedSource
would do.
mask is 1 everywhere (also outside of interval bounds, because interval
is only needed for the navigation box overlay in BDV)
Everything except the inner loop over a single line is now in
AbstractVolatileHierarchyProjector. It is extended by
VolatileHierarchyProjector and MaskedVolatileHierarchyProjector.
VolatileHierarchyProjector handles "normal" Volatile<T> (as before).
MaskedVolatileHierarchyProjector handles Masked<Volatile<T>>.
@tpietzsch tpietzsch merged commit cbf7db7 into master Aug 9, 2025
1 check passed
@tpietzsch tpietzsch deleted the masked-sources-pr branch August 9, 2025 21:47
@tpietzsch
Copy link
Member Author

Of course this can be extended to support other types of masks besides "inside-1-outside-0".
See this example for combining a DoubleType mask image with a UnsignedIntType value image.

Screenshot 2025-08-09 at 23 32 16

The API for this needs a bit more thought, so I will postpone it to a separate PR.

@imagesc-bot
Copy link

This pull request has been mentioned on Image.sc Forum. There might be relevant details there:

https://forum.image.sc/t/fiji-friends-weekly-dev-update-thread/103718/111

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants