Code covered by the BSD License  

Highlights from
SegmentTool: An Interactive GUI for Segmenting Images

image thumbnail

SegmentTool: An Interactive GUI for Segmenting Images

by

 

09 Nov 2012 (Updated )

Interactively find the best approach to segmenting (masking) your image

showMaskAsOverlay(opacity, mask, overlaycolor, varargin)
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, DELEMASKS, PARENT)
%     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.
%
%     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.

% Copyright 2010-2013 The Mathworks Inc

error(nargchk(1,5,nargin));
if nargin >= 4
    if ~isempty(varargin{1})
        if ishandle(varargin{1})
            imgax = varargin{1};
        else
            figure;
            imshow(varargin{1});
            imgax = imgca;
        end
    else
        imgax = imgca;
    end
    %fig = get(imgax,'parent');
    fig = ancestor(imgax,'figure');
    axes(imgax);
else
    fig = gcf;
    imgax = imgca;
end

if nargin == 5
    deleMasks = logical(varargin{2});
else
    deleMasks = true;
end

%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 on;
h = imshow(newmask);
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.
    varargout{1} = imhandles(imgca);
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

Contact us