You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The minimum distance passed to starfish.morphology.Filter.MinDistanceLabel is not enforced. In particular, if multiple local maxima exist with identical values, all of them are retained, independent of their distance. This leads to surprising cases of over-segmentation, where perfectly contiguous masks are split into multiple components (see example below).
Steps/Code to Reproduce
Using this exemplary mask (saved as mask.png):
importnumpyasnpimportskimageasskiimportmatplotlib.pyplotaspltfromstarfishimportImageStackfromstarfish.morphologyimportBinarize, Filter# Load the image, transform it to a BinaryMaskCollection and apply the MinDistanceLabelimg=ImageStack.from_numpy(np.expand_dims(ski.util.img_as_float32(ski.io.imread("mask.png")), (0,1,2)))
binarized=Binarize.ThresholdBinarize(.5).run(img)
masks=Filter.MinDistanceLabel(120, 120).run(binarized)
print("Nuclei found:", len(list(masks.masks())))
plt.imshow(masks.to_label_image().xarray.squeeze(),interpolation="nearest")
Expected Results
Two clearly separated nuclei.
Actual Results
Four detected nuclei, the top one separated into three distinct areas (the small line between the top and bottom has its own class).
Cause and possible solution
The cause of this problem is, that the internally called skimage.filter.peak_local_max (
) is not passed an appropriate value for min_distance, so the default value of 1 is used. Setting the footprint according to the minimum_distance ensures, that there can be only one maximum value in the respective area, but if that value occurs multiple times, all occurrences are returned as local maxima and thus used as seeds in a watershed. This is certainly undesirable as it leads to cases of over-segmentation, as exemplified.
As I'm currently working with 2D data only, changing the starfish code above to pass min_distance=self._minimum_distance_xy fixes this problem for me. However, for 3D data, a more sophisticated solution might be desirable.
@iimog this looks like a good candidate for a bugfix PR! Please make one with your change and reference this issue. I agree a 3D version may require more work, but it would be great to solve this problem first anyway.
iimog
added a commit
to BioMeDS/starfish
that referenced
this issue
Nov 17, 2023
otherwise multiple local maxima are returned even within the distance if
their values are identical. This lead to lots of over-segmentation. In
particular, multiple perfectly contigous nuclei were split in half.
Related spacetx#2006
* Add min_distance parameter to peak_local_max call
otherwise multiple local maxima are returned even within the distance if
their values are identical. This lead to lots of over-segmentation. In
particular, multiple perfectly contigous nuclei were split in half.
Related #2006
* Fix iss test
adjust assumption on number of detected cells
* Fix docker build
the docker build was failing, because botocore needs urllib3 to be in a
certain version range. Pinning urllib3 to that range fixes the issue.
Description
The minimum distance passed to
starfish.morphology.Filter.MinDistanceLabel
is not enforced. In particular, if multiple local maxima exist with identical values, all of them are retained, independent of their distance. This leads to surprising cases of over-segmentation, where perfectly contiguous masks are split into multiple components (see example below).Steps/Code to Reproduce
Using this exemplary mask (saved as
![mask](https://private-user-images.githubusercontent.com/7403236/283127086-49f361c1-bf45-40bf-bb45-6575d78ca88e.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk3NDMwOTMsIm5iZiI6MTczOTc0Mjc5MywicGF0aCI6Ii83NDAzMjM2LzI4MzEyNzA4Ni00OWYzNjFjMS1iZjQ1LTQwYmYtYmI0NS02NTc1ZDc4Y2E4OGUucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIxNiUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMTZUMjE1MzEzWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9MTM1M2RhMDJiZmE1MjhlNGU2NWY1ZDYzOTMyNWE5ZTZjM2Y2ODYyYjQ5NmZiMDE3ZWNkMjZhM2Q0ZTcwN2NhOCZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.9Er9p5r4PBP_q9Oe7RW0KbeOxqvh7N0yN3ZjdXTlzYM)
mask.png
):Expected Results
Two clearly separated nuclei.
![properseg](https://private-user-images.githubusercontent.com/7403236/283133984-ba7d4d8c-d99c-4df3-b7d8-ec7855cc188e.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk3NDMwOTMsIm5iZiI6MTczOTc0Mjc5MywicGF0aCI6Ii83NDAzMjM2LzI4MzEzMzk4NC1iYTdkNGQ4Yy1kOTljLTRkZjMtYjdkOC1lYzc4NTVjYzE4OGUucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIxNiUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMTZUMjE1MzEzWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9MjI2MThlNDlkODcwMDYwYTNjNzUxYzE0MDVlOWIyZGE1ZmIzMWEzZTEwZTM3OTVlNTkyYTU4ZWIxMDRkZDgzZSZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.t_wIU7imLx6-0Zv947bVGIbRZ8UzWLtoZv3NQ-PcZCM)
Actual Results
Four detected nuclei, the top one separated into three distinct areas (the small line between the top and bottom has its own class).
![overseg](https://private-user-images.githubusercontent.com/7403236/283129622-e12d9c1f-8c23-4900-9433-1b4a817afd15.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk3NDMwOTMsIm5iZiI6MTczOTc0Mjc5MywicGF0aCI6Ii83NDAzMjM2LzI4MzEyOTYyMi1lMTJkOWMxZi04YzIzLTQ5MDAtOTQzMy0xYjRhODE3YWZkMTUucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIxNiUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMTZUMjE1MzEzWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9OGUyMDYyY2M0NTIzODM1NDYxNTgxNTExOTQzMjg4MzRlMzYwNDZkNzlhYTZlNDY2NTk5NTg0NmU1ZmJhMzBlNyZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.GY6I144amlcE2n3E2E7W5EEReidnJO1gVxaZq71Btzc)
Cause and possible solution
The cause of this problem is, that the internally called
skimage.filter.peak_local_max
(starfish/starfish/core/morphology/Filter/min_distance_label.py
Lines 61 to 66 in 853f56c
min_distance
, so the default value of 1 is used. Setting thefootprint
according to the minimum_distance ensures, that there can be only one maximum value in the respective area, but if that value occurs multiple times, all occurrences are returned as local maxima and thus used as seeds in a watershed. This is certainly undesirable as it leads to cases of over-segmentation, as exemplified.As I'm currently working with 2D data only, changing the starfish code above to pass
min_distance=self._minimum_distance_xy
fixes this problem for me. However, for 3D data, a more sophisticated solution might be desirable.Versions
Linux-5.15.0-84-generic-x86_64-with-glibc2.35
Python 3.9.16 | packaged by conda-forge | (main, Feb 1 2023, 21:39:03)
[GCC 11.3.0]
NumPy 1.26.0
SciPy 1.11.3
scikit-image 0.18.3
pandas 1.3.2
sklearn 0.24.2
xarray 0.19.0
sympy 1.5.1
starfish 0.2.2+41.g0e668d12
The text was updated successfully, but these errors were encountered: