Skip to content

Commit

Permalink
Merge pull request #15 from haesleinhuepf/more-operations
Browse files Browse the repository at this point in the history
More operations
  • Loading branch information
haesleinhuepf authored Aug 27, 2022
2 parents 99f2a71 + b522341 commit 0a987ff
Show file tree
Hide file tree
Showing 6 changed files with 752 additions and 252 deletions.
855 changes: 633 additions & 222 deletions docs/demo.ipynb

Large diffs are not rendered by default.

65 changes: 46 additions & 19 deletions docs/labeling.ipynb

Large diffs are not rendered by default.

70 changes: 64 additions & 6 deletions napari_segment_blobs_and_things_with_membranes/__init__.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@

__version__ = "0.3.1"
__version__ = "0.3.2"
__common_alias__ = "nsbatwm"

#from napari.types import ImageData, LabelsData

from napari_plugin_engine import napari_hook_implementation

import numpy as np
from scipy import ndimage as ndi

from skimage.filters import threshold_otsu as sk_threshold_otsu, gaussian, sobel
from skimage.segmentation import watershed
from skimage.feature import peak_local_max
Expand All @@ -21,11 +17,11 @@
from skimage.segmentation import relabel_sequential
from skimage.segmentation import clear_border
from skimage.segmentation import expand_labels as sk_expand_labels

from skimage import filters
import scipy
from scipy import ndimage
from napari_time_slicer import time_slicer
from stackview import jupyter_displayable_output

@napari_hook_implementation
def napari_experimental_provide_function():
Expand Down Expand Up @@ -89,6 +85,7 @@ def _sobel_3d(image):


@register_function(menu="Segmentation post-processing > Split touching objects (nsbatwm)")
@jupyter_displayable_output(library_name='nsbatwm', help_url='https://www.napari-hub.org/plugins/napari-segment-blobs-and-things-with-membranes')
@time_slicer
def split_touching_objects(binary:"napari.types.LabelsData", sigma: float = 3.5) -> "napari.types.LabelsData":
"""
Expand Down Expand Up @@ -128,6 +125,7 @@ def split_touching_objects(binary:"napari.types.LabelsData", sigma: float = 3.5)


@register_function(menu="Segmentation / binarization > Threshold (Otsu et al 1979, scikit-image, nsbatwm)")
@jupyter_displayable_output(library_name='nsbatwm', help_url='https://www.napari-hub.org/plugins/napari-segment-blobs-and-things-with-membranes')
@time_slicer
def threshold_otsu(image:"napari.types.ImageData") -> "napari.types.LabelsData":
"""
Expand All @@ -146,6 +144,7 @@ def threshold_otsu(image:"napari.types.ImageData") -> "napari.types.LabelsData":


@register_function(menu="Segmentation / binarization > Threshold (Yen et al 1995, scikit-image, nsbatwm)")
@jupyter_displayable_output(library_name='nsbatwm', help_url='https://www.napari-hub.org/plugins/napari-segment-blobs-and-things-with-membranes')
@time_slicer
def threshold_yen(image :"napari.types.ImageData") -> "napari.types.LabelsData":
"""
Expand All @@ -167,6 +166,7 @@ def threshold_yen(image :"napari.types.ImageData") -> "napari.types.LabelsData":


@register_function(menu="Segmentation / binarization > Threshold (Isodata, Ridler et al 1978, scikit-image, nsbatwm)")
@jupyter_displayable_output(library_name='nsbatwm', help_url='https://www.napari-hub.org/plugins/napari-segment-blobs-and-things-with-membranes')
@time_slicer
def threshold_isodata(image :"napari.types.ImageData") -> "napari.types.LabelsData":
"""
Expand All @@ -190,6 +190,7 @@ def threshold_isodata(image :"napari.types.ImageData") -> "napari.types.LabelsDa


@register_function(menu="Segmentation / binarization > Threshold (Li et al 1993, scikit-image, nsbatwm)")
@jupyter_displayable_output(library_name='nsbatwm', help_url='https://www.napari-hub.org/plugins/napari-segment-blobs-and-things-with-membranes')
@time_slicer
def threshold_li(image:"napari.types.ImageData") -> "napari.types.LabelsData":
"""
Expand All @@ -211,6 +212,7 @@ def threshold_li(image:"napari.types.ImageData") -> "napari.types.LabelsData":


@register_function(menu="Segmentation / binarization > Threshold (Ridler et al 1978, scikit-image, nsbatwm)")
@jupyter_displayable_output(library_name='nsbatwm', help_url='https://www.napari-hub.org/plugins/napari-segment-blobs-and-things-with-membranes')
@time_slicer
def threshold_mean(image :"napari.types.ImageData") -> "napari.types.LabelsData":
"""
Expand All @@ -232,6 +234,7 @@ def threshold_mean(image :"napari.types.ImageData") -> "napari.types.LabelsData"


@register_function(menu="Segmentation / binarization > Threshold (Mean, scikit-image, nsbatwm)")
@jupyter_displayable_output(library_name='nsbatwm', help_url='https://www.napari-hub.org/plugins/napari-segment-blobs-and-things-with-membranes')
@time_slicer
def threshold_minimum(image :"napari.types.ImageData") -> "napari.types.LabelsData":
"""
Expand All @@ -253,6 +256,7 @@ def threshold_minimum(image :"napari.types.ImageData") -> "napari.types.LabelsDa


@register_function(menu="Segmentation / binarization > Threshold (Triangle method, Zack et al 1977, scikit-image, nsbatwm)")
@jupyter_displayable_output(library_name='nsbatwm', help_url='https://www.napari-hub.org/plugins/napari-segment-blobs-and-things-with-membranes')
@time_slicer
def threshold_triangle(image:"napari.types.ImageData") -> "napari.types.LabelsData":
"""
Expand All @@ -274,6 +278,7 @@ def threshold_triangle(image:"napari.types.ImageData") -> "napari.types.LabelsDa


@register_function(menu="Filtering / noise removal > Gaussian (scikit-image, nsbatwm)")
@jupyter_displayable_output(library_name='nsbatwm', help_url='https://www.napari-hub.org/plugins/napari-segment-blobs-and-things-with-membranes')
@time_slicer
def gaussian_blur(image:"napari.types.ImageData", sigma: float = 1) -> "napari.types.ImageData":
"""
Expand All @@ -283,6 +288,7 @@ def gaussian_blur(image:"napari.types.ImageData", sigma: float = 1) -> "napari.t


@register_function(menu="Filtering / edge enhancement > Gaussian Laplace (scipy, nsbatwm)")
@jupyter_displayable_output(library_name='nsbatwm', help_url='https://www.napari-hub.org/plugins/napari-segment-blobs-and-things-with-membranes')
@time_slicer
def gaussian_laplace(image:"napari.types.ImageData", sigma: float = 2)-> "napari.types.ImageData":
"""
Expand All @@ -307,6 +313,7 @@ def gaussian_laplace(image:"napari.types.ImageData", sigma: float = 2)-> "napari


@register_function(menu="Filtering / noise removal > Median (scipy, nsbatwm)")
@jupyter_displayable_output(library_name='nsbatwm', help_url='https://www.napari-hub.org/plugins/napari-segment-blobs-and-things-with-membranes')
@time_slicer
def median_filter(image:"napari.types.ImageData", radius: float = 2)-> "napari.types.ImageData":
"""
Expand All @@ -320,6 +327,7 @@ def median_filter(image:"napari.types.ImageData", radius: float = 2)-> "napari.t


@register_function(menu="Filtering / noise removal > Percentile (scipy, nsbatwm)")
@jupyter_displayable_output(library_name='nsbatwm', help_url='https://www.napari-hub.org/plugins/napari-segment-blobs-and-things-with-membranes')
@time_slicer
def percentile_filter(image:"napari.types.ImageData", percentile : float = 50, radius: float = 2)-> "napari.types.ImageData":
"""The percentile filter is similar to the median-filter but it allows specifying the percentile.
Expand All @@ -329,6 +337,7 @@ def percentile_filter(image:"napari.types.ImageData", percentile : float = 50, r


@register_function(menu="Filtering / background removal > White top-hat (scipy, nsbatwm)")
@jupyter_displayable_output(library_name='nsbatwm', help_url='https://www.napari-hub.org/plugins/napari-segment-blobs-and-things-with-membranes')
@time_slicer
def white_tophat(image:"napari.types.ImageData", radius: float = 2)-> "napari.types.ImageData":
"""
Expand All @@ -340,6 +349,7 @@ def white_tophat(image:"napari.types.ImageData", radius: float = 2)-> "napari.ty


@register_function(menu="Filtering / background removal > Black top-hat (scipy, nsbatwm)")
@jupyter_displayable_output(library_name='nsbatwm', help_url='https://www.napari-hub.org/plugins/napari-segment-blobs-and-things-with-membranes')
@time_slicer
def black_tophat(image:"napari.types.ImageData", radius: float = 2)-> "napari.types.ImageData":
"""
Expand All @@ -349,6 +359,7 @@ def black_tophat(image:"napari.types.ImageData", radius: float = 2)-> "napari.ty


@register_function(menu="Filtering / background removal > Minimum (scipy, nsbatwm)")
@jupyter_displayable_output(library_name='nsbatwm', help_url='https://www.napari-hub.org/plugins/napari-segment-blobs-and-things-with-membranes')
@time_slicer
def minimum_filter(image:"napari.types.ImageData", radius: float = 2)-> "napari.types.ImageData":
"""
Expand All @@ -360,6 +371,7 @@ def minimum_filter(image:"napari.types.ImageData", radius: float = 2)-> "napari.


@register_function(menu="Filtering / background removal > Maximum (scipy, nsbatwm)")
@jupyter_displayable_output(library_name='nsbatwm', help_url='https://www.napari-hub.org/plugins/napari-segment-blobs-and-things-with-membranes')
@time_slicer
def maximum_filter(image:"napari.types.ImageData", radius: float = 2)-> "napari.types.ImageData":
"""
Expand All @@ -372,6 +384,7 @@ def maximum_filter(image:"napari.types.ImageData", radius: float = 2)-> "napari.


@register_function(menu="Filtering / edge enhancement > Morphological Gradient (scipy, nsbatwm)")
@jupyter_displayable_output(library_name='nsbatwm', help_url='https://www.napari-hub.org/plugins/napari-segment-blobs-and-things-with-membranes')
@time_slicer
def morphological_gradient(image:"napari.types.ImageData", radius: float = 2)-> "napari.types.ImageData":
"""
Expand All @@ -397,6 +410,7 @@ def morphological_gradient(image:"napari.types.ImageData", radius: float = 2)->


@register_function(menu="Filtering / background removal > Rolling ball (scikit-image, nsbatwm)")
@jupyter_displayable_output(library_name='nsbatwm', help_url='https://www.napari-hub.org/plugins/napari-segment-blobs-and-things-with-membranes')
@time_slicer
def subtract_background(image:"napari.types.ImageData", rolling_ball_radius: float = 5) -> "napari.types.ImageData":
"""
Expand All @@ -411,6 +425,7 @@ def subtract_background(image:"napari.types.ImageData", rolling_ball_radius: flo


@register_function(menu="Segmentation post-processing > Invert binary image (nsbatwm)")
@jupyter_displayable_output(library_name='nsbatwm', help_url='https://www.napari-hub.org/plugins/napari-segment-blobs-and-things-with-membranes')
@time_slicer
def binary_invert(binary_image:"napari.types.LabelsData") -> "napari.types.LabelsData":
"""
Expand All @@ -420,6 +435,7 @@ def binary_invert(binary_image:"napari.types.LabelsData") -> "napari.types.Label


@register_function(menu="Segmentation / labeling > Connected component labeling (scikit-image, nsbatwm)")
@jupyter_displayable_output(library_name='nsbatwm', help_url='https://www.napari-hub.org/plugins/napari-segment-blobs-and-things-with-membranes')
@time_slicer
def connected_component_labeling(binary_image: "napari.types.LabelsData", exclude_on_edges: bool = False) -> "napari.types.LabelsData":
"""
Expand All @@ -440,6 +456,7 @@ def connected_component_labeling(binary_image: "napari.types.LabelsData", exclud


@register_function(menu="Segmentation post-processing > Remove labeled objects at the image border (scikit-image, nsbatwm)")
@jupyter_displayable_output(library_name='nsbatwm', help_url='https://www.napari-hub.org/plugins/napari-segment-blobs-and-things-with-membranes')
@time_slicer
def remove_labels_on_edges(label_image: "napari.types.LabelsData") -> "napari.types.LabelsData":
"""
Expand All @@ -457,6 +474,7 @@ def remove_labels_on_edges(label_image: "napari.types.LabelsData") -> "napari.ty


@register_function(menu="Segmentation post-processing > Expand labels (scikit-image, nsbatwm)")
@jupyter_displayable_output(library_name='nsbatwm', help_url='https://www.napari-hub.org/plugins/napari-segment-blobs-and-things-with-membranes')
@time_slicer
def expand_labels(label_image: "napari.types.LabelsData", distance: float = 1) -> "napari.types.LabelsData":
"""
Expand All @@ -472,6 +490,7 @@ def expand_labels(label_image: "napari.types.LabelsData", distance: float = 1) -


@register_function(menu="Segmentation / labeling > Voronoi-Otsu-labeling (nsbatwm)")
@jupyter_displayable_output(library_name='nsbatwm', help_url='https://www.napari-hub.org/plugins/napari-segment-blobs-and-things-with-membranes')
@time_slicer
def voronoi_otsu_labeling(image:"napari.types.ImageData", spot_sigma: float = 2, outline_sigma: float = 2) -> "napari.types.LabelsData":
"""Voronoi-Otsu-Labeling is a segmentation algorithm for blob-like structures such as nuclei and
Expand Down Expand Up @@ -514,6 +533,7 @@ def voronoi_otsu_labeling(image:"napari.types.ImageData", spot_sigma: float = 2,


@register_function(menu="Segmentation / labeling > Gauss-Otsu-labeling (nsbatwm)")
@jupyter_displayable_output(library_name='nsbatwm', help_url='https://www.napari-hub.org/plugins/napari-segment-blobs-and-things-with-membranes')
@time_slicer
def gauss_otsu_labeling(image:"napari.types.ImageData", outline_sigma: float = 2) -> "napari.types.LabelsData":
"""Gauss-Otsu-Labeling can be used to segment objects such as nuclei with bright intensity on
Expand Down Expand Up @@ -542,6 +562,7 @@ def gauss_otsu_labeling(image:"napari.types.ImageData", outline_sigma: float = 2


@register_function(menu="Segmentation / labeling > Seeded watershed (scikit-image, nsbatwm)")
@jupyter_displayable_output(library_name='nsbatwm', help_url='https://www.napari-hub.org/plugins/napari-segment-blobs-and-things-with-membranes')
@time_slicer
def seeded_watershed(membranes:"napari.types.ImageData", labeled_nuclei:"napari.types.LabelsData") -> "napari.types.LabelsData":
"""
Expand All @@ -559,6 +580,7 @@ def seeded_watershed(membranes:"napari.types.ImageData", labeled_nuclei:"napari.
return cells

@register_function(menu="Segmentation / labeling > Seeded watershed with mask (scikit-image, nsbatwm)")
@jupyter_displayable_output(library_name='nsbatwm', help_url='https://www.napari-hub.org/plugins/napari-segment-blobs-and-things-with-membranes')
@time_slicer
def seeded_watershed_with_mask(membranes:"napari.types.ImageData", labeled_nuclei:"napari.types.LabelsData", mask:"napari.types.LabelsData") -> "napari.types.LabelsData":
"""
Expand All @@ -578,6 +600,7 @@ def seeded_watershed_with_mask(membranes:"napari.types.ImageData", labeled_nucle


@register_function(menu="Segmentation / labeling > Seeded watershed using local minima as seeds (nsbatwm)")
@jupyter_displayable_output(library_name='nsbatwm', help_url='https://www.napari-hub.org/plugins/napari-segment-blobs-and-things-with-membranes')
@time_slicer
def local_minima_seeded_watershed(image:"napari.types.ImageData", spot_sigma: float = 10, outline_sigma: float = 0) -> "napari.types.LabelsData":
"""
Expand Down Expand Up @@ -607,6 +630,7 @@ def local_minima_seeded_watershed(image:"napari.types.ImageData", spot_sigma: fl


@register_function(menu="Segmentation / labeling > Seeded watershed using local minima as seeds and an intensity threshold (nsbatwm)")
@jupyter_displayable_output(library_name='nsbatwm', help_url='https://www.napari-hub.org/plugins/napari-segment-blobs-and-things-with-membranes')
@time_slicer
def thresholded_local_minima_seeded_watershed(image:"napari.types.ImageData", spot_sigma: float = 3, outline_sigma: float = 0, minimum_intensity: float = 500) -> "napari.types.LabelsData":
"""
Expand All @@ -632,27 +656,31 @@ def thresholded_local_minima_seeded_watershed(image:"napari.types.ImageData", sp
return new_labels

@register_function(menu="Image math > Sum images (numpy, nsbatwm)", factor1={'min': -1000000, 'max': 1000000}, factor2={'min': -1000000, 'max': 1000000})
@jupyter_displayable_output(library_name='nsbatwm', help_url='https://www.napari-hub.org/plugins/napari-segment-blobs-and-things-with-membranes')
@time_slicer
def sum_images(image1: "napari.types.ImageData", image2: "napari.types.ImageData", factor1: float = 1, factor2: float = 1) -> "napari.types.ImageData":
"""Add two images"""
return image1 * factor1 + image2 * factor2


@register_function(menu="Image math > Multiply images (numpy, nsbatwm)")
@jupyter_displayable_output(library_name='nsbatwm', help_url='https://www.napari-hub.org/plugins/napari-segment-blobs-and-things-with-membranes')
@time_slicer
def multiply_images(image1: "napari.types.ImageData", image2: "napari.types.ImageData") -> "napari.types.ImageData":
"""Multiply two images"""
return image1 * image2


@register_function(menu="Image math > Divide images (numpy, nsbatwm)")
@jupyter_displayable_output(library_name='nsbatwm', help_url='https://www.napari-hub.org/plugins/napari-segment-blobs-and-things-with-membranes')
@time_slicer
def divide_images(image1: "napari.types.ImageData", image2: "napari.types.ImageData") -> "napari.types.ImageData":
"""Divide one image by another"""
return image1 / image2


@register_function(menu="Image math > Invert image (scikit-image, nsbatwm)")
@jupyter_displayable_output(library_name='nsbatwm', help_url='https://www.napari-hub.org/plugins/napari-segment-blobs-and-things-with-membranes')
@time_slicer
def invert_image(image: "napari.types.ImageData") -> "napari.types.ImageData":
"""Invert an image. The exact math behind depends on the image type.
Expand All @@ -666,6 +694,7 @@ def invert_image(image: "napari.types.ImageData") -> "napari.types.ImageData":


@register_function(menu="Segmentation post-processing > Skeletonize (scikit-image, nsbatwm)")
@jupyter_displayable_output(library_name='nsbatwm', help_url='https://www.napari-hub.org/plugins/napari-segment-blobs-and-things-with-membranes')
@time_slicer
def skeletonize(image: "napari.types.LabelsData") -> "napari.types.LabelsData":
"""
Expand Down Expand Up @@ -745,3 +774,32 @@ def Manually_split_labels(labels_layer: "napari.layers.Labels", points_layer: "n
points_layer.data = []


@register_function(menu="Filtering / noise removal > Butterworth (scikit-image, nsbatwm)")
@jupyter_displayable_output(library_name='nsbatwm', help_url='https://www.napari-hub.org/plugins/napari-segment-blobs-and-things-with-membranes')
@time_slicer
def butterworth(image: "napari.types.ImageData", cutoff_frequency_ratio: float = 0.005, high_pass: bool = False,
order: float = 2) -> "napari.types.ImageData":
"""Apply a Butterworth filter to enhance high or low frequency features.
This filter is defined in the Fourier domain.
Parameters
----------
image : (M[, N[, ..., P]][, C]) ndarray
Input image.
cutoff_frequency_ratio : float, optional
Determines the position of the cut-off relative to the shape of the
FFT.
high_pass : bool, optional
Whether to perform a high pass filter. If False, a low pass filter is
performed.
order : float, optional
Order of the filter which affects the slope near the cut-off. Higher
order means steeper slope in frequency space.
See also
--------
..[0] https://scikit-image.org/docs/stable/api/skimage.filters.html#skimage.filters.butterworth
"""
from skimage.filters import butterworth as skimage_butterworth
return skimage_butterworth(image, cutoff_frequency_ratio, high_pass, order)
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ def test_something():
multiply_images,\
divide_images,\
invert_image, \
skeletonize
skeletonize, \
butterworth

import numpy as np

Expand Down Expand Up @@ -67,7 +68,8 @@ def test_something():
white_tophat,
morphological_gradient,
local_minima_seeded_watershed,
invert_image]:
invert_image,
butterworth]:

print(operation)

Expand Down
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@

scikit-image
scipy
napari-tools-menu
napari-tools-menu>=0.1.17
napari-time-slicer
napari-assistant
stackview>=0.3.2
-e .
5 changes: 3 additions & 2 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = napari-segment-blobs-and-things-with-membranes
version = 0.3.1
version = 0.3.2
author = Robert Haase
author_email = [email protected]
url = https://github.com/haesleinhuepf/napari-segment-blobs-and-things-with-membranes
Expand Down Expand Up @@ -37,9 +37,10 @@ install_requires =
numpy
scikit-image
scipy
napari-tools-menu
napari-tools-menu>=0.1.17
napari-time-slicer>=0.4.8
napari-assistant
stackview>=0.3.2

[options.entry_points]
napari.plugin =
Expand Down

0 comments on commit 0a987ff

Please sign in to comment.