Coverage for /usr/local/lib/python3.10/site-packages/spam/label/ITKwatershed.py: 100%
31 statements
« prev ^ index » next coverage.py v7.8.0, created at 2025-04-24 17:26 +0000
« prev ^ index » next coverage.py v7.8.0, created at 2025-04-24 17:26 +0000
1# Library of wrapper functions for Simple ITK
2# Copyright (C) 2020 SPAM Contributors
3#
4# This program is free software: you can redistribute it and/or modify it
5# under the terms of the GNU General Public License as published by the Free
6# Software Foundation, either version 3 of the License, or (at your option)
7# any later version.
8#
9# This program is distributed in the hope that it will be useful, but WITHOUT
10# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12# more details.
13#
14# You should have received a copy of the GNU General Public License along with
15# this program. If not, see <http://www.gnu.org/licenses/>.
17import numpy
18import SimpleITK
19import spam.label
22def watershed(binary, markers=None, watershedLevel=1):
23 """
24 This function runs an ITK watershed on a binary image and returns a labelled image.
25 This function uses an interpixel watershed.
27 Parameters
28 -----------
29 binary : 3D numpy array
30 This image which is non-zero in the areas which should be split by the watershed algorithm
32 markers : 3D numpy array (optional, default = None)
33 Not implemented yet, but try!
35 watershedLevel : int, optional
36 Watershed level for merging maxima
38 Returns
39 --------
40 labelled : 3D numpy array of ints
41 3D array where each object is numbered
42 """
44 # def plotme(im):
45 # im = SimpleITK.GetArrayFromImage(im)
46 # plt.imshow(im[im.shape[0]//2])
47 # plt.show()
49 binary = binary > 0
51 # Let's convert it 8-bit
52 binary = binary.astype(numpy.uint8) * 255
54 bdata = SimpleITK.GetImageFromArray(binary)
56 if markers is not None:
57 markers = markers.astype("<u4") if markers.max() > 65535 else markers.astype("<u2")
58 markers = SimpleITK.GetImageFromArray(markers)
60 # watershedLevel=1
61 watershedLineOn = False
62 fullyConnected = True
64 # thresholdFilt = SimpleITK.OtsuThresholdImageFilter()
65 # bdata = thresholdFilt.Execute(data)
67 # rescaleFilt = SimpleITK.RescaleIntensityImageFilter()
68 # rescaleFilt.SetOutputMinimum(0)
69 # rescaleFilt.SetOutputMaximum(65535)
70 # bdata = rescaleFilt.Execute(data)
72 # threshold = thresholdFilt.GetThreshold()
74 # fillFilt = SimpleITK.BinaryFillholeImageFilter()
75 # bdata = fillFilt.Execute(bdata)
77 invertFilt = SimpleITK.InvertIntensityImageFilter()
78 bdata = invertFilt.Execute(bdata)
80 distanceMapFilt = SimpleITK.DanielssonDistanceMapImageFilter()
81 distance = distanceMapFilt.Execute(bdata)
83 distance = invertFilt.Execute(distance)
85 if markers is None:
86 watershedFilt = SimpleITK.MorphologicalWatershedImageFilter()
87 else:
88 watershedFilt = SimpleITK.MorphologicalWatershedFromMarkersImageFilter()
89 watershedFilt.SetFullyConnected(fullyConnected)
90 watershedFilt.SetMarkWatershedLine(watershedLineOn)
92 if markers is None:
93 watershedFilt.SetLevel(watershedLevel)
94 labelImage = watershedFilt.Execute(distance)
95 else:
96 labelImage = watershedFilt.Execute(distance, markers)
98 bdata = invertFilt.Execute(bdata)
100 maskFilt = SimpleITK.MaskImageFilter()
101 mask = maskFilt.Execute(labelImage, bdata)
103 # overlayFilt = SimpleITK.LabelOverlayImageFilter()
104 # overlay = overlayFilt.Execute(bdata, mask)
106 lab = SimpleITK.GetArrayFromImage(mask).astype(spam.label.labelType)
108 return lab