1"""Benchmarks for `skimage.segmentation`.
2
3See "Writing benchmarks" in the asv docs for more information.
4"""
5
6import numpy as np
7from numpy.lib import NumpyVersion as Version
8
9import skimage
10from skimage import data, filters, segmentation
11
12from . import _channel_kwarg
13
14try:
15    from skimage.segmentation import watershed
16except ImportError:
17    # older scikit-image had this function under skimage.morphology
18    from skimage.morphology import watershed
19
20
21class SlicSegmentation:
22    """Benchmark for segmentation routines in scikit-image."""
23    def setup(self):
24        self.image = np.random.random((200, 200, 100))
25        self.image[:100, :100, :] += 1
26        self.image[150:, 150:, :] += 0.5
27        self.msk = np.zeros((200, 200, 100))
28        self.msk[10:-10, 10:-10, 10:-10] = 1
29        self.msk_slice = self.msk[..., 50]
30        if Version(skimage.__version__) >= Version('0.17.0'):
31            self.slic_kwargs = dict(start_label=1)
32        else:
33            self.slic_kwargs = {}
34
35    def time_slic_basic(self):
36        segmentation.slic(self.image, enforce_connectivity=False,
37                          **_channel_kwarg(False), **self.slic_kwargs)
38
39    def time_slic_basic_multichannel(self):
40        segmentation.slic(self.image, enforce_connectivity=False,
41                          **_channel_kwarg(True), **self.slic_kwargs)
42
43    def peakmem_setup(self):
44        """peakmem includes the memory used by setup.
45
46        Peakmem benchmarks measure the maximum amount of RAM used by a
47        function. However, this maximum also includes the memory used
48        by ``setup`` (as of asv 0.2.1; see [1]_)
49
50        Measuring an empty peakmem function might allow us to disambiguate
51        between the memory used by setup and the memory used by slic (see
52        ``peakmem_slic_basic``, below).
53
54        References
55        ----------
56        .. [1]: https://asv.readthedocs.io/en/stable/writing_benchmarks.html#peak-memory
57        """
58        pass
59
60    def peakmem_slic_basic(self):
61        segmentation.slic(self.image, enforce_connectivity=False,
62                          **_channel_kwarg(False), **self.slic_kwargs)
63
64    def peakmem_slic_basic_multichannel(self):
65        segmentation.slic(self.image, enforce_connectivity=False,
66                          **_channel_kwarg(True), **self.slic_kwargs)
67
68
69class MaskSlicSegmentation(SlicSegmentation):
70    """Benchmark for segmentation routines in scikit-image."""
71    def setup(self):
72        try:
73            mask = np.zeros((64, 64)) > 0
74            mask[10:-10, 10:-10] = 1
75            segmentation.slic(np.ones_like(mask), mask=mask)
76        except TypeError:
77            raise NotImplementedError("masked slic unavailable")
78
79        self.image = np.random.random((200, 200, 100))
80        self.image[:100, :100, :] += 1
81        self.image[150:, 150:, :] += 0.5
82        self.msk = np.zeros((200, 200, 100))
83        self.msk[10:-10, 10:-10, 10:-10] = 1
84        self.msk_slice = self.msk[..., 50]
85        if Version(skimage.__version__) >= Version('0.17.0'):
86            self.slic_kwargs = dict(start_label=1)
87        else:
88            self.slic_kwargs = {}
89
90    def time_mask_slic(self):
91        segmentation.slic(self.image, enforce_connectivity=False,
92                          mask=self.msk, **_channel_kwarg(False))
93
94    def time_mask_slic_multichannel(self):
95        segmentation.slic(self.image, enforce_connectivity=False,
96                          mask=self.msk_slice, **_channel_kwarg(True))
97
98
99class Watershed(object):
100
101    param_names = ["seed_count", "connectivity", "compactness"]
102    params = [(5, 500), (1, 2), (0, 0.01)]
103
104    def setup(self, *args):
105        self.image = filters.sobel(data.coins())
106
107    def time_watershed(self, seed_count, connectivity, compactness):
108        watershed(self.image, seed_count, connectivity,
109                  compactness=compactness)
110
111    def peakmem_reference(self, *args):
112        """Provide reference for memory measurement with empty benchmark.
113
114        Peakmem benchmarks measure the maximum amount of RAM used by a
115        function. However, this maximum also includes the memory used
116        during the setup routine (as of asv 0.2.1; see [1]_).
117        Measuring an empty peakmem function might allow us to disambiguate
118        between the memory used by setup and the memory used by target (see
119        other ``peakmem_`` functions below).
120
121        References
122        ----------
123        .. [1]: https://asv.readthedocs.io/en/stable/writing_benchmarks.html#peak-memory  # noqa
124        """
125        pass
126
127    def peakmem_watershed(self, seed_count, connectivity, compactness):
128        watershed(self.image, seed_count, connectivity,
129                  compactness=compactness)
130