Watershed segmentation using ops

Dear all,

I am trying to perform watershed of a binary image (form imagej, so with 0 and 255 value) using imglib2 and ops of the following image binary.tif (512.2 KB) and I almost there.

// @OpService ops
// @Dataset inputData


import net.imagej.ops.Ops
import net.imglib2.img.display.imagej.ImageJFunctions
import net.imglib2.type.numeric.integer.UnsignedByteType

//Thresold the Output mask from fiji (where 0 is false and 255 is true)
maskBitType = ops.threshold().apply(inputData, new UnsignedByteType(128));
//Fill the holes
maskFilled = ops.morphology().fillHoles(maskBitType);

//Perform the watershed
useEightConnectivity=true
drawWatersheds=true
double sigma=2.0
watershedImgLabeling=ops.image().watershed(maskFilled,useEightConnectivity,drawWatersheds,sigma)

//Display the result
watershedImg=watershedImgLabeling.getIndexImg()
watershedImgLabelingImp=ImageJFunctions.wrap(watershedImg, "wrapped")
watershedImgLabelingImp.show()

I obtain the following:

But I would like to have more:

Is there a way to do it, like by passing a mask argument that will output a label of each nuclei?
It looks available

net.imagej.ops.image.watershed.Watershed(
		ImgLabeling out?,
		RandomAccessibleInterval in,
		boolean useEightConnectivity,
		boolean drawWatersheds,
		RandomAccessibleInterval mask?)

But i run the following:
watershedImgLabeling=ops.image().watershed(maskFilled,useEightConnectivity,drawWatersheds,maskFilled)

I got an error saying no such method exist.

Benjamin

1 Like

I ran into a similar problem recently when preparing some jupyter notebooks as teaching material: when calling ops with optional parameters, they will be filled from left to right, i.e. in your case, you’ll have to provide the out parameter before being able to add a mask parameter.

See specifically this cell (somehow it’s not possible to link to specific lines on GitHub when the file is a notebook… :worried:):

result = ops.run("watershed", blurred_distMap, true, false)
label_display(ops.image().watershed(result, blurred_distMap, true, false, 3, thresholded))

Hope that helps.

2 Likes

Thanks for your help, I didn’t know this trick.

So basically, adding null for the optional output parameter fixed it.

The following code give me what I wanted

// @OpService ops
// @Dataset inputData


import net.imagej.ops.Ops
import net.imglib2.img.display.imagej.ImageJFunctions

//Thresold the Output mask from fiji (where 0 is false and 255 is true)
maskBitType = ops.threshold().apply(inputData, new UnsignedByteType(128));
//Fill the holes
maskFilled = ops.morphology().fillHoles(maskBitType);

//Perform the watershed
useEightConnectivity=true
drawWatersheds=false
double sigma=2.0
watershedImgLabeling=ops.image().watershed(null,maskFilled,useEightConnectivity,drawWatersheds,sigma,maskFilled)

//Display the result
watershedImg=watershedImgLabeling.getIndexImg()
watershedImgLabelingImp=ImageJFunctions.wrap(watershedImg, "wrapped")
watershedImgLabelingImp.show()

Thanks a lot Jan for your answer, and thanks for the link to your notebooks, it’s a very precious resource,

Benjamin

2 Likes