Seeded region growing imglib2



@bogovicj @imagejan @hanslovsky @maarzt

Hi All,

I have a TB sized label map image (pixel values being object Ids),
and I need (to write) a function like this:

RandomAccessibleInterval< BitType > extractObject( RandomAccessibleInterval< UnsignedLongType > labelMap, long[] seedPosition )
	final RandomAccess< UnsignedLongType > access = labelMap.randomAccess();
	access.setPosition( seedPosition );
	final long objectId = access.get().getIntegerLong();

	// perform seeded region growing extracting all pixels that are
	// (i) connected to seedPosition
	// (ii) and have value objectId
	// ...

	// create a binary image of minimal size containing all found pixels
	// ...

	return smallBinaryRAIofObjectBoundingBoxSize;

I was wondering whether such a function exists already?
For example, paintera seems to need such logic as well to show 3D objects, or are you solving this differently?

Otherwise I thought of modifying this:
…, which I think cannot use directly, because I do not apriori know the size of the target image. So, I guess I would instead populate a list of coordinates and only in the end construct an image of minimal size from it?!

I guess another idea would be to actually use the existing FloodFill and use as target image a sparse implementation of a BitType RAI?

All help is very much appreciated!


Yes, the FloodFill class that you already discovered should do the trick.

No, Paintera uses 3D marching cubes on a pre-defined set of blocks for any selected labels. The containing blocks have to be pre-computed.

You should be able to use this flood-fill method. Create a DiskCachedCellImg that is as big as your input image and wrap it into a RandomAccessibleInterval with a RandomAccess that keeps track of the bounding box that it has touched. That should be all you need (it is probably a good idea to extend input/output with appropriate values). Feel free to copy/modify that bounding box tracking RAI as you need.

Yes that should work. I do not know if that would be more efficient than the disk cached cell img option.


Great! I’ll try this! The bounding box tracking is exactly what I need in order to later use Views.interval() to crop out the relevant part.


I got something working :slight_smile:
If you have a few seconds to check whether this could still be improved let me know:
But anyway: @hanslovsky thanks a lot!!


@haesleinhuepf @skalarproduktraum
I did some benchmarking and extracting an object from an imglib2 label mask using a floodFill is now reasonably fast. This yields me a binary mask which I then want to view using the ImageJ 3D Viewer. This second step (i.e. creating a mesh and displaying it) however is rather slow (several seconds):

final long start = System.currentTimeMillis();
final Image3DUniverse univ = new Image3DUniverse();;
final Content content = univ.addMesh( objectMask, new Color3f( 1.0f, 1.0f, 1.0f ), "object at level " + ll, 250, new boolean[]{ true, true, true }, 1 );
Utils.log( "Computed mesh and created 3D display in " + (System.currentTimeMillis() - start) + " ms" );

How could I speed this up?
@hanslovsky potentially directly creating a mesh while extracting the voxels?
…but I do not want you use JavaFX for display as I heard this is difficult to install…

and does someone know Benjamin Schmidts handle here in the Forum? He presented a new 3D Viewer at I2K.


That might be a speed-up if the actual object/foreground is sparse within the bounding box. Otherwise, I recommend parallelizing mesh creation (marching cubes).

Mesh creation is independent of the UI framework you use, so I do not see how that matters here. That begin said, JavaFX should be easily installed as it is shipped with oracle JRE/JDK 8 and is available in the Linux package managers that I know of (Arch Linux, Ubuntu) for use with OpenJDK8.


Would you have code for that (in Painterra) which I could “steal”? Or is there something in imglib2 core?


Afaik there is no marching cubes in imglib2. You can c&p what you need from the Paintera implementation:

Original algorithm

Also, check out the ops implementation


Thanks a lot! For my untrained eye the ops implementation and the one in Paintera look kind of similar. Are there significant differences that one should consider?


None that I am aware of.