Skip to content

Commit 070f175

Browse files
committed
ImageExtendedMinWatershed now support 3D images
1 parent 111d032 commit 070f175

File tree

3 files changed

+320
-26
lines changed

3 files changed

+320
-26
lines changed

ImageM/+imagem/+actions/+process/ImageExtendedMinWatershed.m

Lines changed: 56 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -16,27 +16,28 @@
1616
% Copyright 2011 INRA - Cepia Software Platform.
1717

1818
properties
19-
% the set of handles to dialog widgets, indexed by their name
19+
% the set of handles to dialog widgets, indexed by their name.
2020
Handles;
2121

2222
Viewer;
2323

24-
% the min and max of values present in image. Default is [0 255]
24+
% the min and max of values present in image. Default is [0 255].
2525
ImageExtent = [0 255];
2626

27-
% the value of dynamic used to pre-filter images
27+
% the value of dynamic used to pre-filter images.
2828
ExtendedMinimaValue = 10;
2929

30-
% the connectivity of the regions
31-
Conn = 4;
30+
% the connectivity of the regions, as integer value.
31+
Conn;
3232

33-
% the list of available connectivity values
34-
ConnValues = [4, 8];
33+
% The labels used to populate the combo box.
34+
ConnLabels;
3535

36-
% boolean flag indicating is binary image of watershed should be created
36+
% boolean flag indicating is binary image of watershed should be
37+
% created.
3738
ComputeWatershed = true;
3839

39-
% boolean flag indicating if label image of basins should be created
40+
% boolean flag indicating if label image of basins should be created.
4041
ComputeBasins = false;
4142
end
4243

@@ -59,26 +60,42 @@ function run(obj, frame) %#ok<INUSD>
5960
return;
6061
end
6162

63+
% initialize initial value of parameters
64+
minVal = double(min(img));
65+
maxVal = double(max(img));
66+
if any(~isfinite([minVal maxVal]))
67+
finiteValues = img.Data(isfinite(img.Data));
68+
minVal = double(min(finiteValues));
69+
maxVal = double(max(finiteValues));
70+
end
71+
obj.ImageExtent = [minVal maxVal];
72+
73+
obj.ExtendedMinimaValue = minVal + (maxVal - minVal) * 0.25;
74+
if isGrayscaleImage(img)
75+
obj.ExtendedMinimaValue = round(obj.ExtendedMinimaValue);
76+
end
77+
78+
if ndims(img) == 2 %#ok<ISMAT>
79+
obj.Conn = value(imagem.util.enums.Connectivities2D.C4);
80+
obj.ConnLabels = imagem.util.enums.Connectivities2D.allLabels;
81+
elseif ndims(img) == 3
82+
obj.Conn = value(imagem.util.enums.Connectivities3D.C6);
83+
obj.ConnLabels = imagem.util.enums.Connectivities3D.allLabels;
84+
else
85+
error('Can only manage with dimensions 2 or 3');
86+
end
87+
6288
createWatershedFigure(obj);
6389
updateWidgets(obj);
6490
end
6591

6692
function hf = createWatershedFigure(obj)
6793

68-
% range of grayscale values
69-
img = currentImage(obj.Viewer);
70-
minVal = double(min(img));
71-
maxVal = double(max(img));
72-
obj.ImageExtent = [minVal maxVal];
73-
7494
gui = obj.Viewer.Gui;
7595

7696
% compute slider steps
77-
valExtent = maxVal - minVal;
78-
if minVal == 0
79-
valExtent = valExtent + 1;
80-
end
81-
97+
valExtent = obj.ImageExtent(2) - obj.ImageExtent(1);
98+
img = currentImage(obj.Viewer);
8299
if isGrayscaleImage(img)
83100
% set unit step equal to 1 grayscale unit
84101
sliderStep1 = 1 / valExtent;
@@ -90,7 +107,7 @@ function run(obj, frame) %#ok<INUSD>
90107
end
91108

92109
% startup dynamic value
93-
sliderValue = valExtent / 4;
110+
sliderValue = obj.ExtendedMinimaValue;
94111

95112
% background color of most widgets
96113
bgColor = getWidgetBackgroundColor(gui);
@@ -114,14 +131,14 @@ function run(obj, frame) %#ok<INUSD>
114131
mainPanel = uix.VBox('Parent', vb);
115132

116133
obj.Handles.ExtendedMinText = addInputTextLine(gui, mainPanel, ...
117-
'Basin Dynamic:', '10', ...
134+
'Basin Dynamic:', num2str(obj.ExtendedMinimaValue), ...
118135
@obj.onExtendedMinTextChanged);
119136

120137
% one slider for changing value
121138
obj.Handles.ValueSlider = uicontrol(...
122139
'Style', 'Slider', ...
123140
'Parent', mainPanel, ...
124-
'Min', 1, 'Max', valExtent, ...
141+
'Min', 0, 'Max', valExtent, ...
125142
'Value', sliderValue, ...
126143
'SliderStep', [sliderStep1 sliderStep2], ...
127144
'BackgroundColor', bgColor, ...
@@ -132,7 +149,7 @@ function run(obj, frame) %#ok<INUSD>
132149
'ContinuousValueChange', @obj.onSliderValueChanged);
133150

134151
obj.Handles.ConnectivityPopup = addComboBoxLine(gui, mainPanel, ...
135-
'Connectivity:', {'4', '8'}, ...
152+
'Connectivity:', obj.ConnLabels, ...
136153
@obj.onConnectivityChanged);
137154

138155
obj.Handles.ResultTypePopup = addComboBoxLine(gui, mainPanel, ...
@@ -196,7 +213,7 @@ function onButtonOK(obj, varargin)
196213
end
197214

198215
% add history
199-
string = sprintf('%s = watershed(%s, ''dynamic'', %f, ''conn'', %d));\n', ...
216+
string = sprintf('%s = watershed(%s, ''dynamic'', %g, ''conn'', %d);\n', ...
200217
newDoc.Tag, refDoc.Tag, obj.ExtendedMinimaValue, obj.Conn);
201218
addToHistory(obj.Viewer, string);
202219

@@ -230,13 +247,26 @@ function onExtendedMinTextChanged(obj, varargin)
230247

231248
function onSliderValueChanged(obj, varargin)
232249
val = get(obj.Handles.ValueSlider, 'Value');
250+
if isGrayscaleImage(currentImage(obj.Viewer))
251+
val = round(val);
252+
end
253+
233254
obj.ExtendedMinimaValue = val;
234255
updateWidgets(obj);
235256
end
236257

237258
function onConnectivityChanged(obj, varargin)
259+
260+
238261
index = get(obj.Handles.ConnectivityPopup, 'Value');
239-
obj.Conn = obj.ConnValues(index);
262+
label = obj.ConnLabels{index};
263+
264+
img = currentImage(obj.Viewer);
265+
if ndims(img) == 2 %#ok<ISMAT>
266+
obj.Conn = value(imagem.util.enums.Connectivities2D.fromLabel(label));
267+
elseif ndims(img) == 3
268+
obj.Conn = value(imagem.util.enums.Connectivities3D.fromLabel(label));
269+
end
240270

241271
updateWidgets(obj);
242272
end
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
classdef Connectivities2D
2+
% Enumeration of the various connectivities in 2D.
3+
%
4+
% Enumeration imagem.util.enums.Connectivities2D
5+
%
6+
% Example
7+
% enumLabels = imagem.util.enums.Connectivities2D.allLabels;
8+
% conn = imagem.util.enums.Connectivities2D.fromLabel(enumLabels{1})
9+
% conn =
10+
% Connectivities2D enumeration
11+
% C4
12+
% value(conn)
13+
% ans =
14+
% 4
15+
%
16+
% See also
17+
%
18+
19+
% ------
20+
% Author: David Legland
21+
22+
% Created: 2021-02-22, using Matlab 9.8.0.1323502 (R2020a)
23+
% Copyright 2021 INRAE - BIA-BIBS.
24+
25+
26+
%% Enumerates the different cases
27+
enumeration
28+
C4('C4', 4);
29+
C8('C8', 8);
30+
end % end properties
31+
32+
33+
%% Static methods
34+
methods (Static)
35+
function res = allNames()
36+
% Returns a cell list with all enumeration names.
37+
mc = ?imagem.util.enums.Connectivities2D;
38+
itemList = mc.EnumerationMemberList;
39+
nItems = length(itemList);
40+
res = cell(1, nItems);
41+
42+
for i = 1:nItems
43+
% retrieve current enumeration item
44+
mitem = itemList(i);
45+
res{i} = mitem.Name;
46+
end
47+
end
48+
49+
function res = fromName(name)
50+
% Identifies a imagem.util.enums.Connectivities2D from its name.
51+
if nargin == 0 || ~ischar(name)
52+
error('requires a character array as input argument');
53+
end
54+
55+
mc = ?imagem.util.enums.Connectivities2D;
56+
itemList = mc.EnumerationMemberList;
57+
for i = 1:length(itemList)
58+
% retrieve current enumeration item
59+
mitem = itemList(i);
60+
item = imagem.util.enums.Connectivities2D.(mitem.Name);
61+
if strcmpi(name, char(item))
62+
res = item;
63+
return;
64+
end
65+
end
66+
67+
error('Unrecognized imagem.util.enums.Connectivities2D name: %s', name);
68+
end
69+
70+
function res = allLabels()
71+
% Returns a cell list with all enumeration names.
72+
mc = ?imagem.util.enums.Connectivities2D;
73+
itemList = mc.EnumerationMemberList;
74+
nItems = length(itemList);
75+
res = cell(1, nItems);
76+
77+
for i = 1:nItems
78+
% retrieve current enumeration item
79+
mitem = itemList(i);
80+
item = imagem.util.enums.Connectivities2D.(mitem.Name);
81+
res{i} = item.Label;
82+
end
83+
end
84+
85+
function res = fromLabel(label)
86+
% Identifies a imagem.util.enums.Connectivities2D from its label.
87+
if nargin == 0 || ~ischar(label)
88+
error('requires a character array as input argument');
89+
end
90+
91+
mc = ?imagem.util.enums.Connectivities2D;
92+
itemList = mc.EnumerationMemberList;
93+
for i = 1:length(itemList)
94+
% retrieve current enumeration item
95+
mitem = itemList(i);
96+
item = imagem.util.enums.Connectivities2D.(mitem.Name);
97+
if strcmpi(label, item.Label)
98+
res = item;
99+
return;
100+
end
101+
end
102+
103+
error('Unrecognized imagem.util.enums.Connectivities2D label: %s', label);
104+
end
105+
end % end methods
106+
107+
%% Methods
108+
methods
109+
function v = value(obj)
110+
v = obj.Value;
111+
end
112+
end
113+
114+
%% Constructor
115+
methods (Access = private)
116+
function obj = Connectivities2D(label, value, varargin)
117+
% Constructor for imagem.util.enums.Connectivities2D class.
118+
obj.Label = label;
119+
obj.Value = value;
120+
end
121+
122+
end % end constructors
123+
124+
125+
%% Properties
126+
properties
127+
Label;
128+
Value;
129+
end % end properties
130+
131+
end % end classdef
132+

0 commit comments

Comments
 (0)