-
Notifications
You must be signed in to change notification settings - Fork 0
/
showMaskAsOverlay.m
294 lines (283 loc) · 10.4 KB
/
showMaskAsOverlay.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
function varargout = showMaskAsOverlay(opacity, mask, overlaycolor, varargin)
% Show segmentation (mask) with user-specified transparency/color as overlay on image
%
% Using optional input DELEMASK argument, one can
% easily show multiple segmentation masks on a single image.
%
% SYNTAX:
%
% SHOWMASKASOVERLAY(OPACITY, MASK, OVERLAYCOLOR)
% Operates on the image in the current figure, overlays a
% MASK of opacity OPACITY and of color OVERLAYCOLOR.
%
% SHOWMASKASOVERLAY(OPACITY, MASK, OVERLAYCOLOR, IMG)
% Takes a handle to an image or axes, or an image itself.
%
% SHOWMASKASOVERLAY(OPACITY, MASK, OVERLAYCOLOR, IMG, DELEMASKS)
% DELEMASKS is a logical binary, indicating whether existing masks
% should be deleted before new masks are displayed. Default is TRUE.
%
% SHOWMASKASOVERLAY(OPACITY, MASK, OVERLAYCOLOR, IMG, PARENT, DELEMASKS)
% By default, showMaskAsOverlay operates on the current axes in the
% current figure. Use the optional PARENT argument to specify the AXES
% you want to show the mask on.
%
% SHOWMASKOVERLAY(OPACITY)
% If an overlayed mask already exists in the current figure,
% this shorthand command will modify its opacity.
%
% HNDLS = SHOWMASKASOVERLAY(...)
% Returns a structure of handles to the original image (FIRST) and
% generated overlays in the current axes.
%
% [HNDLS, IMGOUT] = SHOWMASKASOVERLAY(...)
% Also returns an RGB image of class double, capturing the combined IMG
% and OVERLAY(s) as image IMGOUT.
%
% INPUTS:
%
% OPACITY The complement of transparency; a variable on [0,1]
% describing how opaque the overlay should be. A
% mask of opacity of 0 is 100% transparent. A mask
% of opacity 1 is completely solid.
% MASK A binary image to be shown on the image of
% interest. (Must be the same size as the image operated
% on.)
% OVERLAYCOLOR A triplet of [R G B] value indicating the color
% of the overlay. (Standard "color strings"
% like 'r','g','b','m' are supported.) Default
% is red.
% IMG (Optional) A handle to an image-containing axes, or an
% image. By default, SHOWIMAGEASOVERLAY operates on the
% image displayed in the current axes. (If this argument
% is omitted, or if the current axes does not contain an
% image, an error will be thrown.)
%
% Alternatively, IMG may be an image, in which case a new
% figure is generated, the image is displayed, and the
% overlay is generated on top of it.
%
% PARENT Optional; indicates handle of target axes. Default is
% imgca (current image-containing axes).
%
% DELEMASKS Delete previously displayed masks?
% This operates at a figure-level. (Default = 1.)
%
% OUTPUTS:
%
% HNDLS A structure containing handles of all images (including
% overlays) in the current axes. The structure will have
% fields:
% Original: The underlying (non-overlaid) image in
% the parent axes.
% Overlays: All overlays created by
% SHOWMASKASOVERLAY.
% (NOTE: To get the IMAGES themselves, extract
% the CDATA from the image handles.)
%
% NEWIMG An output image, matching the class of
% the input image, of the color-coded
% mask.
%
% EXAMPLES:
% 1)
% I = imread('rice.png');
% I2 = imtophat(I, ones(15, 15));
% I2 = im2bw(I2, graythresh(I2));
% I2 = bwareaopen(I2, 5);
% figure;
% imshow(I);
% showMaskAsOverlay(0.4,I2)
% title('showMaskAsOverlay')
%
% 2)
% I = imread('rice.png');
% AllGrains = imtophat(I, ones(15, 15));
% AllGrains = im2bw(AllGrains, graythresh(AllGrains));
% AllGrains = bwareaopen(AllGrains, 5);
% PeripheralGrains = AllGrains -imclearborder(AllGrains);
% InteriorGrains = AllGrains - PeripheralGrains;
% figure;
% subplot(2,2,1.5)
% imshow(I); title('Original')
% subplot(2,2,3)
% imshow(I)
% showMaskAsOverlay(0.4,AllGrains)
% title('All grains')
% subplot(2,2,4)
% imshow(I)
% % Note: I set DELEMASKS explicity to 0 here so
% % 'AllGrains' mask is not cleared from figure
% showMaskAsOverlay(0.4,InteriorGrains,[1 1 0],0)
% showMaskAsOverlay(0.4,PeripheralGrains,'g',0)
% title('Interior and Peripheral Grains')
%
% 3) I = imread('peppers.png');
% mask = im2bw(I(:,:,1),graythresh(I(:,:,1)));
% imshow(I);
% [h,newImg] = showMaskAsOverlay(1,mask,[0.65 0.47 0.69]);
% cla;
% imshow(newImg);
% Brett Shoelson, PhD
% brett.shoelson@mathworks.com
% V 1.0 07/05/2007
% V 1.5 03/02/2009: Modified to provide the new-colored image as
% an output, matching the class of the underlying image (over
% which the overlay is displayed).
% V 1.6 10/19/2011: Fixed casting problem for optional
% "burned" output image.
% V 1.7 12/18/2011: Replaced deprecated IPTCHECKINPUTS with
% VALIDATEATTRIBUTES.
% V 1.8 10/12/2012: Allow for optional specification of parent axes.
% V 1.8.1 4/25/2014: fixed description of inputs. (Had parent and delemasks
% in the wrong order.
% V 1.9 1/15/2015: fixed a problem with passed parent arguments. (Wasn't
% necessarily writing to the correct axes.)
% V 1.9.1 5/20/2015: fixed bug in output handle.
% Copyright 2010-2013 The Mathworks Inc
narginchk(1,5);
deleMasks = true; %Default
imgax = [];
for ii = 1:numel(varargin)
if isempty(varargin{ii}),continue,end;
if ishandle(varargin{ii})&&varargin{ii}~=0
imgax = varargin{ii};
else
deleMasks = varargin{ii};
end
end
if isempty(imgax)
imgax = imgca; %Default
end
if isa(deleMasks,'double'),deleMasks = logical(deleMasks);end
fig = ancestor(imgax,'figure');
%iptcheckinput(opacity, {'double','logical'},{'nonempty'},mfilename, 'opacity', 1);
validateattributes(opacity, {'double','logical'},{'nonempty'},mfilename, 'opacity', 1);
%iptcheckinput(deleMasks, {'logical'},{'nonempty'}, mfilename, 'deleMasks', 5);
validateattributes(deleMasks, {'logical'},{'nonempty'}, mfilename, 'deleMasks', 5);
if nargin == 1
overlay = findall(gcf,'tag','opaqueOverlay');
if isempty(overlay)
error('SHOWMASKASOVERLAY: No opaque mask found in current figure.');
end
mask = get(overlay,'cdata');
newmask = max(0,min(1,double(any(mask,3))*opacity));
set(overlay,'alphadata',newmask);
figure(fig);
%tofront(get(fig,'name'));
return
else
%iptcheckinput(mask, {'double','logical'},{'nonempty'}, mfilename, 'mask', 2);
validateattributes(mask, {'double','logical'},{'nonempty'}, mfilename, 'mask', 2);
end
% If the user doesn't specify the color, use red.
DEFAULT_COLOR = [1 0 0];
if nargin < 3
overlaycolor = DEFAULT_COLOR;
elseif ischar(overlaycolor)
switch overlaycolor
case {'y','yellow'}
overlaycolor = [1 1 0];
case {'m','magenta'}
overlaycolor = [1 0 1];
case {'c','cyan'}
overlaycolor = [0 1 1];
case {'r','red'}
overlaycolor = [1 0 0];
case {'g','green'}
overlaycolor = [0 1 0];
case {'b','blue'}
overlaycolor = [0 0 1];
case {'w','white'}
overlaycolor = [1 1 1];
case {'k','black'}
overlaycolor = [0 0 0];
otherwise
disp('Unrecognized color specifier; using default.');
overlaycolor = DEFAULT_COLOR;
end
end
figure(fig);
%tofront(get(fig,'name'));
if isempty(imgax)
tmp = imhandles(fig);
else
tmp = imhandles(imgax);
end
if isempty(tmp)
error('There doesn''t appear to be an image in the current figure.');
end
try
a = imattributes(tmp(1));
catch
error('There doesn''t appear to be an image in the current figure.');
end
imsz = [str2num(a{2,2}),str2num(a{1,2})]; %#ok
if ~isequal(imsz,size(mask(:,:,1)))
error('Size mismatch');
end
if deleMasks
%delete(findall(fig,'tag','opaqueOverlay'))
delete(findall(imgax,'tag','opaqueOverlay'))
end
overlaycolor = im2double(overlaycolor);
% Ensure that mask is logical
mask = logical(mask);
if size(mask,3) == 1
newmaskR = zeros(imsz);
newmaskG = newmaskR;
newmaskB = newmaskR;
%Note: I timed this with logical indexing (as currently implemented),
%with FIND, and with logical indexing after converting the mask to type
%logical. All three were roughly equivalent in terms of performance.
newmaskR(mask) = overlaycolor(1);
newmaskG(mask) = overlaycolor(2);
newmaskB(mask) = overlaycolor(3);
elseif size(mask,3) == 3
newmaskR = mask(:,:,1);
newmaskG = mask(:,:,2);
newmaskB = mask(:,:,3);
else
beep;
disp('Unsupported masktype in showImageAsOverlay.');
return
end
newmask = im2uint8(cat(3,newmaskR,newmaskG,newmaskB));
hold(imgax,'on');
h = imshow(newmask,'parent',imgax);
try
set(h,'alphadata',double(mask)*opacity,'tag','opaqueOverlay');
catch
set(h,'alphadata',opacity,'tag','opaqueOverlay');
end
if nargout > 0
% This returns handles to two images, im1 and im2.
% im1 is the handle of the "COLORED MASK" imge.
% im2 is the handle of the image over which you are
% overlaying.
% To get the actual image for either, refer to the cdata of
% the image handles.
% BDS 5/20/15: I believe this was a bug:
%varargout{1} = imhandles(imgca);
varargout{1} = findall(imgax,'tag','opaqueOverlay');
end
if nargout > 1
% This returns a "concatenated" rgb image of the
% color-coded overlaid mask.
tmp = get(varargout{1}(1),'cdata');
switch a{3,2}
case 'uint8'
mult = 255;
case 'uint16'
mult = 2^16;
otherwise
mult = 1;
end
r = tmp(:,:,1);
g = tmp(:,:,2);
b = tmp(:,:,3);
r(mask) = overlaycolor(1)*mult;
g(mask) = overlaycolor(2)*mult;
b(mask) = overlaycolor(3)*mult;
varargout{2} = cast(cat(3,r,g,b),a{3,2});
end