Fill hole work only on 2D

the fill hole works only on 2D images ??

1 Like

Hey @pmailly,

it’s supposed to work in 3D as well. Let me just demonstrate with a short macro:

run("CLIJ2 Macro Extensions", "cl_device=");

	// first plane
	1, 1, 1, 1,
	1, 1, 1, 1,
	1, 1, 1, 1,
	// second plane
	1, 1, 1, 1,
	1, 0, 0, 1,
	1, 1, 1, 1,
	// third plane
	1, 1, 1, 1,
	1, 1, 1, 1,
	1, 1, 1, 1),
	4, 3, 3 // width, height, depth

Ext.CLIJ2_binaryFillHoles(input_image, output_image);


This outputs:

If it doesn’t work in your case, please share an example image and the code you are executing. It’s then much easier to guess what might go wrong.


Left is a stack and right 2D. Using CLIJ2 fiji menu or in java plugin.


Can you please share a dataset? It’s then much easier to guess what might go wrong :wink:

MaskTest.tif (6.7 MB)

Hey @pmailly,

thanks for the dataset. The reason is that the hole isn’t closed in the 3rd dimension:

Thus, you may be looking for applying the fill-holes operation slice by slice, right?

This little macro does the job:

run("CLIJ2 Macro Extensions", "cl_device=");

stack = getTitle();

Ext.CLIJ2_getDimensions(stack, width, height, depth);

for (z = 0; z < depth; z++) {
	// get a single slice from the stack
	Ext.CLIJ2_copySlice(stack, slice, z);	
	// fill holes in it
	Ext.CLIJ2_binaryFillHoles(slice, slice_filled);
	// copy the slice back to the stack
	Ext.CLIJ2_copySlice(slice_filled, stack, z);	


I’ve also put an entry to the wish-list. Binary fill holes slice by slice would be a cool feature in a future version of clij.

Thanks for raising this and let me know if the workaround works!


1 Like

Thanks Robert, effectively I did slice by slice. Could you put also in the whish-list clear outside, I didn’t find it :grinning:

1 Like

“clear outside” is something similar to “mask”, right?

Not exactly, fill outside in Fiji take in account a roi.

“Fill outside” not “Clear outside”. Ok
But you know, there are no ROIs, just binary images in CLIJ :wink:

Something like that :

* Clear outside
* create mask image with roi
* and use clij2 mask
private ClearCLBuffer ClearOutSide(ClearCLBuffer imgCL, Roi roi) {
    ImagePlus img = clij2.pull(imgCL);
    ClearCLBuffer imgCLMask = clij2.create(imgCL);
    roi.setLocation(0, 0);
    for (int z = 0; z < img.getNSlices(); z++) {
        ImagePlus mask = new ImagePlus("",img.createRoiMask());
        ClearCLBuffer maskCL = clij2.push(mask);
        clij2.copySlice(maskCL, imgCLMask, z);
    ClearCLBuffer imgCLFillOutSide = clij2.create(imgCL);
    clij2.mask(imgCL, imgCLMask, imgCLFillOutSide);

Ok. I see. Just one minor comment: You’re creating more and more images in GPU-memory in this line inside the for-loop:

ClearCLBuffer maskCL = clij2.push(mask);

You may want to release it inside the loop.

Furthermore, have a look at Create Mask and maskStackWithPlane. I think they do what want :wink:

Yes I’m still not very familiar with push and release in the GPU :grinning:
Creating_Masks is working on 2D

It’s fine. You’ll pick that up soon!

But an ROI is 2D, right?

Yes the roi is done on a projection of the stack. Usually it’s to remove from image objects that we don’t want as process from aother cells etc…

1 Like

That’s what I thought. And that’s why I pointed at maskStackWithPlane :wink:

You’r right !