clEsperanto / CLIc

GPU-accelerated Image Processing library
https://clesperanto.github.io/CLIc/
BSD 3-Clause "New" or "Revised" License
14 stars 15 forks source link

threshold_otsu does not work as expected for floating point images with very small values #342

Closed thawn closed 3 weeks ago

thawn commented 1 month ago

cle.threshold_otsu gives wrong segmentations for float32 images with very small values (<0,003)

example:

image = np.array([[0,0,0],
                  [0,0.003,0],
                  [0,0,0]])

thresholded = cle.threshold_otsu(image)

pyclesperanto returns array([[1, 1, 1], [1, 1, 1], [1, 1, 1]], dtype=uint8, mtype=buffer)

pyclesperanto_prototype returns as expected array([[0,0,0], [0, 1, 0], [0,0,0]], dtype=uint8, mtype=buffer)

a notebook for reproducing the issue is attached clesperanto_bug.ipynb.zip

StRigaud commented 1 month ago

If you increase the number it works correctly?

StRigaud commented 1 month ago

Also, do you know if you have the same issue with the prototype? I will test on my side, but interested if you know already the answer

thawn commented 1 month ago

@StRigaud thanks for looking into this :-)

yes, with larger numbers (even 0.004) it works as expected.

no the prototype does not have the same problem

StRigaud commented 1 month ago

Thanks! That narrow it a bit down.

Weird for the 0.004 though.

I might need a bit of time before fixing this but will try to do it quick!

thawn commented 1 month ago

Just in case someone else runs into this problem, scaling the image intensities to 0-255 before applying threshold_otsu works as a workaround. I am using the following code:

scaled = cle.add_image_and_scalar(image, scalar=-cle.minimum_of_all_pixels(image))
scaled = cle.multiply_image_and_scalar(scaled, scalar=255 / cle.maximum_of_all_pixels(scaled))
thresholded = cle.threshold_otsu(scaled)
StRigaud commented 3 weeks ago

This should be fix at the next release :)

thawn commented 2 weeks ago

@StRigaud thanks a lot for fixing this bug :-)