Code covered by the BSD License  

Highlights from
imOverlay

image thumbnail
from imOverlay by David Legland
Add colored markers to an image, that can be 2D or 3D, grayscale or color.

imOverlay(img, varargin)
function res = imOverlay(img, varargin)
%IMOVERLAY Add colored markers to an image (2D or 3D, grayscale or color)
%
%   Usage
%   OVR = imOverlay(IMG, MASK);
%   OVR = imOverlay(IMG, MASK, COLOR);
%   OVR = imOverlay(IMG, MASK1, COLOR1, MASK2, COLOR2...);
%   OVR = imOverlay(IMG, RED, GREEN, BLUE);
%   
%   Description
%   OVR = imOverlay(IMG, MASK);
%   where IMG and MASK are 2 images the same size, returns the image BASE
%   with red markers given by MASK superposed on it.
%   IMG can be either color or gray-scale image, 2D or 3D (actually
%   Ny*Nx*3*Nz in the case of 3D color image)
%   MASK is a binary image with same size as IMG 
%   OVR is a color image, the same size as the original image
%
%   OVR = imOverlay(IMG, MASK, COLOR);
%   assumes that binary image MASK and image BASE have the same size,
%   replace all pixels of MASK by the color COLOR. The argument COLOR is
%   either a vector with 3 elements, or a character belonging to {'r', 'g',
%   'b', 'c', 'm', 'y', 'k', 'w'}.
%
%   This syntax can be repeated:
%   OVR = imOverlay(IMG, MASK1, COLOR1, MASK2, COLOR2, MASK3, COLOR3)
%
%   OVR = imOverlay(IMG, RED, GREEN, BLUE);
%   where RED, GREEN and BLUE are binary images the same size as IMG image,
%   puts 3 overlays of different colors on the base image.
%   It is possible to specify only one overlay by using empty data:
%   OVR = imOverlay(BASE, [], [], BLUE);
%
%
%   Example
%   %% Display two binary overlays on a grayscale image
%   % Read demo image and binarize it
%   img = imread('coins.png');
%   bin = imfill(img>100,'holes');
%   % compute disc boundary
%   circ = bin ~= imdilate(bin, [0 1 0;1 1 1;0 1 0]);
%   % compute inluence zone o feach disc
%   wat = watershed(bwdist(bin), 8);
%   % compute and display overlay as 3 separate bands
%   res = imOverlay(img, circ, [], wat==0);
%   figure; imshow(res);
%   % display result with different colors
%   res = imOverlay(img, circ, 'y', wat==0, [1 0 1]);
%   figure; imshow(res);
%
%   %% colorize a part of a grayscale image
%   % read input grayscale image
%   img = imread('cameraman.tif');
%   % create a colorized version of the grayscale image
%   yellow = cat(3, img, img, zeros(size(img), 'uint8'));
%   % compute binary a mask around the head of the cameraman
%   mask = false(size(img));
%   mask(20:120, 80:180) = true;
%   % compute and show the overlay
%   imshow(imOverlay(img, mask, yellow));
%
%   %% Compute overlay on a 3D image
%   metadata = analyze75info('brainMRI.hdr');
%   I = analyze75read(metadata);    % read 3D data
%   se = ones([3 3 3]);
%   bin = imclose(I>0, se);         % binarize, remove small holes
%   bnd = imerode(bin, se)~=bin;    % compute boundary
%   ovr = imOverlay(I*3, bnd);      % compute overlay
%   montage(ovr);                   % display each slice
%
%
% ------
% Author: David Legland
% e-mail: david.legland@grignon.inra.fr
% created the 11/12/2003.
% Copyright 2010 INRA - Cepia Software Platform.

% HISTORY
% 01-04-2004 add support for three color overlays, with possibility of
%   empty ones
% 10-06-2004 correct bug for 3D RGB images
% 25-06-2004 small bug for 3D color images
% 29-06-2004 add possibility to use binary images
% 15-11-2004 reduce memory used by program
% 08-08-2006 add support for floating point images
% 29-08-2007 major rewriting, add possibility to specify couples of mask
%   and colors
% 23-07-2009 update doc
% 06-01-2010 cleanup
% 19-07-2010 major rewriting, add tests


if length(varargin)==1
    % If only one input => this is the mask, the color is assumed to be red
    res = imOverlay(img, varargin{1}, [1 0 0]);
    return;

elseif length(varargin)==3
    % If three inputs are given, there are supposed to be the red, green
    % and blue mask, in that order, possibly empty
    res = img;
    if ~isempty(varargin{1})
        res = imOverlay(res, varargin{1}, [1 0 0]);
    end
    if ~isempty(varargin{2})
        res = imOverlay(res, varargin{2}, [0 1 0]);
    end
    if ~isempty(varargin{3})
        res = imOverlay(res, varargin{3}, [0 0 1]);
    end
    return;
end

    
% Ensure input image has uint8 type
img = im2uint8(img);


%% Initializations

% compute size and info flags
[dim isColor is3D] = computeImageInfo(img);


% initialize each band of the result image with the original image
if isColor
    red     = squeeze(img(:,:,1,:));
    green   = squeeze(img(:,:,2,:));
    blue    = squeeze(img(:,:,3,:));
else
    red     = img;
    green   = img;
    blue    = img;
end


%% Main processing

% Recursively process input arguments
% As long as we find inputs, mask is extracted and overlaid on result image
while ~isempty(varargin)
    % First argument is the mask, second argument specifies color
    mask    = varargin{1};
    [r g b]  = parseOverlayBands(varargin{2});
    
    varargin(1:2) = [];
    
    % type cast
    mask = uint8(mask);
        
    % update each band
    red     = red.*uint8(mask==0)   + mask.*r;
    green   = green.*uint8(mask==0) + mask.*g;
    blue    = blue.*uint8(mask==0)  + mask.*b;
end


% create result image by concatenating all bands
if is3D
    res = zeros([dim(1:2) 3 dim(3)], 'uint8');
    res(:,:,1,:) = red;
    res(:,:,2,:) = green;
    res(:,:,3,:) = blue;
else
    res = cat(3, red, green, blue);
end



function [dim isColor is3D] = computeImageInfo(img)
% Compute image size, and determines if image is 3D and/or color
% Returns the dimension of image witghout the color channel, and two binary
% flags indicating if image is color, and 3D.


% size of matlab matrix
dim0    = size(img);

% detect 3D and color image
if length(dim0)==2
    % Default case: planar grayscale image
    dim     = dim0(1:2);
    isColor = false;
    is3D    = false;
    
elseif length(dim0)==3
    % either 3D grayscale, or planar color image
    if dim0(3)==3
        % third dimension equals 3 ==> color image
        dim     = dim0(1:2);
        isColor = true;
        is3D    = false;
    else
        % third dimension <> 3 ==> gray-scale 3D image
        dim     = dim0;
        isColor = false;
        is3D    = true;
    end
    
elseif length(dim0)==4
    % 3D color image
    dim     = dim0([1 2 4]);
    isColor = true;
    is3D    = true;
    
else
    error('Unprocessed dimension');
end


function [r g b] = parseOverlayBands(color)
% determines r g and b values from argument value
%
% argument COLOR can be one of:
% - a 1*3 row vector containing rgb values between 0 and 1
% - a string containing color code
% - a grayscale image
% - a color image
%
% The result are the R, G and B values coded as uint8 between 0 and 255
%

if ischar(color)
    % parse character to  a RGB triplet
    [r g b] = parseColorString(color);
    
elseif isnumeric(color)
    if size(color, 1)==1
        % normalize color between 0 and 255
        if max(color)<=1
            color = color*255;
        end
        
        % extract each component
        r = color(1);
        g = color(2);
        b = color(3);
    else
        % otherwise, color is another image
        [dim isColor is3D] = computeImageInfo(color); %#ok<ASGLU>
        if isColor
            if is3D
                r = squeeze(color(:,:,1,:));
                g = squeeze(color(:,:,2,:));
                b = squeeze(color(:,:,3,:));
            else
                r = color(:,:,1);
                g = color(:,:,2);
                b = color(:,:,3);
            end
        else
            r = color;
            g = color;
            b = color;
        end
    end
else
    error('Wrong data type for specifying color');
end

            
function varargout = parseColorString(color)
% PARSECOLOR Parse color character to  a RGB triplet, between 0 and 1

% process special colors
if strcmp(color, 'black')
    color = 'k'; 
end

% tests the first character of the string
color = color(1);
switch color
    case 'r', r=1; g=0; b=0;
    case 'g', r=0; g=1; b=0;
    case 'b', r=0; g=0; b=1;
    case 'c', r=0; g=1; b=1;
    case 'm', r=1; g=0; b=1;
    case 'y', r=1; g=1; b=0;
    case 'k', r=0; g=0; b=0;
    case 'w', r=1; g=1; b=1;
end

% convert to uint8
r = uint8(r*255);
g = uint8(g*255);
b = uint8(b*255);

% format output 
if nargout==3
    varargout{1} = r;
    varargout{2} = g;
    varargout{3} = b;
else
    varargout{1} = [r g b];
end

Contact us