Fill hole work only on 2D

Hi,
the fill hole works only on 2D images ??
Philippe

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=");

Ext.CLIJ2_pushArray(input_image, 
	newArray(
	// 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);

Ext.CLIJ2_print(output_image);

This outputs:
image

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.

Cheers,
Robert

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

Philippe

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_push(stack);

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);	
}

Ext.CLIJ2_pull(stack);

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!

Cheers,
Robert

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:
Philippe

1 Like

“clear outside” is something similar to “mask”, right?
https://clij.github.io/clij2-docs/reference_mask

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);
    img.setRoi(roi);
    for (int z = 0; z < img.getNSlices(); z++) {
        img.setSlice(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);
    clij2.release(imgCL);
    clij2.release(imgCLMask);
    return(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
Philippe

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…
Philippe

1 Like

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

You’r right !
Philippe