Code covered by the BSD License  

Highlights from
Vessel branch segmentation

image thumbnail

Vessel branch segmentation

by

 

Segment the vessel branches from dynamic image of fluorescent microscopy

VesselBranchSegmentation
function VesselBranchSegmentation
% Gui main function to segment vessel branches from dynamic fluorocent
% imaging. 

% Copyright(c) 2012 Hiroshi Kawaguchi


% =#=*==#=*==#=*==#=*==#=*==#=*==#=*==#=*==#=*==#=*==#=*==#=*==#=*==#=*==#=
%
%%  - # - # - # - Start of Main function - # - # - # -
%
% =#=*==#=*==#=*==#=*==#=*==#=*==#=*==#=*==#=*==#=*==#=*==#=*==#=*==#=*==#=

% =========================================================================
%% ## Gloval Variables ##
% =========================================================================

orgImg  =[];
appImg  =[];
bgIndex=1;
imhBgImg  =[];

masks=InitMasks;
imSize=[];
saveFileName=[];

% =========================================================================
%% ## UI Figure, Axis, Slider ##
% =========================================================================

% --------------------------------------------------------------------------
% UI Objects;
% --------------------------------------------------------------------------

% figure ------------------------------------------------------------------
figureSize = round([1200,800]);
fgh = figure(...
    'Position'    , [ 100 100 figureSize],...
    'Name'        , '5xAVTT Analysis',...
    'Units'       , 'pixels',...
    'NumberTitle' , 'off',...
    'Resize'      , 'off',...
    'ToolBar'     , 'figure',...
    'MenuBar'     , 'none',...
    'Renderer'    , 'OpenGL',...
    'Colormap'    , gray(256),...
    'HandleVisibility','callback',...
    'DeleteFcn','clear GLOBAL dlgH fgh'...
);

% axis XY--------------------------------------------------------------------
axh = axes(...
    'Parent',fgh,...
    'Units','pixels',...
    'Position',round(min(figureSize)*[.025 .075 .9 .9]),...
    'Box','on',...
    'DrawMode','fast',...
    'YDir','reverse',...
    'XTickLabel','',...
    'YTickLabel','');
set(axh,'Units','pixels');
defaultAxesPosition = get(axh, 'Position');

% axis T --------------------------------------------------------------------
axth = axes(...
    'Parent',fgh,...
    'Units','pixels',...
    'Position',round(min(figureSize)*[1.0 .075  .45 .25]),...
    'Box','on',...
    'DrawMode','fast');
set(axth,'Units','pixels');


% slider -------------------------------------------------------------------
sltexth = zeros(1,3);                              % 3 text below the slider
sltexth(1) = uicontrol('Parent',fgh,'String','1', 'Style','text',... min
    'Position',[round(min(figureSize)*[.025 .025]) 20 10]);
sltexth(2) = uicontrol('Parent',fgh,'String','1', 'Style','text',... current
    'Position',[round(min(figureSize)*[.47 .02])  20 10]  );
sltexth(3) = uicontrol('Parent',fgh,'String','1', 'Style','text',... max
    'Position',[round(min(figureSize)*[.91 .025]) 20 10] );
slh = uicontrol('Style','slider',...
    'Parent',fgh,'BusyAction','Cancel','Callback',@CBslider, ...
    'Position',round(min(figureSize)*[.025 .035 .9 .025]));

% dialog
    


% -------------------------------------------------------------------------
% Functions
% -------------------------------------------------------------------------

% CBslider ----------------------------------------------------------------
    function CBslider(oh,event) %#ok<INUSD>
        set(sltexth(2),'string', int2str(CurrentSlice));
        DrawImages;
    end

% =========================================================================
%% ## UIMenu - File ##
% =========================================================================

% --------------------------------------------------------------------------
% UI Objects;
% --------------------------------------------------------------------------

ohMenu= uimenu('Parent',fgh, 'Label', 'File ');
uimh.File.New =uimenu('Parent',ohMenu,'Label','New ', 'Callback', @CBMfileNew,  'Accelerator','n');
uimh.File.Open=uimenu('Parent',ohMenu,'Label','Open', 'Callback', @CBMfileOpen, 'Accelerator','o')  ;
uimh.File.Save=uimenu('Parent',ohMenu,'Label','Save', 'Callback', @CBMfileSave, 'Accelerator','s',...
    'Enable','off', 'Separator', 'on');

% -------------------------------------------------------------------------
% Functions
% -------------------------------------------------------------------------

% CBMfileNew ---------------------------------------------------------------
    function CBMfileNew(oh,event) %#ok<INUSD>
        [tmporgImg  saveFileName] = ReadOrgImg('Pick a mat file.');
        if isempty(tmporgImg);  return; end; % canceled case

        orgImg =tmporgImg;
        
        masks=InitMasks;
        
        InitGUI;
        InitMenu(1:length(masks));
        bgIndex=1;
        [~, f]=fileparts(saveFileName);
        set(fgh,'Name',f)
    end

% CBMfileOpen --------------------------------------------------------------
    function CBMfileOpen(oh,event)%#ok<INUSD>
        if isempty(saveFileName)
            pathName=[pwd , filesep];
        else
            pathName=fileparts(saveFileName);
        end
        
        [fileName, pathName] = uigetfile({'*.mat','MAT-files (*.mat)'}, 'Pick a MAT-file', pathName);
        
        if isnumeric(fileName) && fileName==0; return; end; % canceled

        if isempty(whos('-file',fullfile(pathName,fileName),'orgImg'))
            errordlg('Selected file seems not to be suited to this program.');
            return;
        end

        vals=load(fullfile(pathName,fileName));
        masks=InitMasks;
        valname=fieldnames(vals);
        for n=1:length(valname)
            eval([valname{n} '=vals.' valname{n} ';']);
        end

        for n=1:length(masks)
            masks(n).handle=[];
        end
        saveFileName=fullfile(pathName,fileName);
        InitGUI;
        InitMenu(1:length(masks));
        InitMaskHandles(1:length(masks));
        [~, f]=fileparts(saveFileName);
        set(fgh,'Name',f)
    end

% CBMfileSave --------------------------------------------------------------
    function CBMfileSave(oh,event)%#ok<INUSD>
        uisave({'orgImg','masks','appImg',...
            'arterySkelGam','veinSkelGam',...
            'arteryBranches','veinBranches ',...
            'arteryBranchOrder','veinBranchOrder'}, saveFileName);

    end

% InitGUI ------------------------------------------------------------------
    function InitGUI
        
        delete(get(axh,'Children'));
        set(findobj(fgh,'Type','uicontrol'),'Enable','off');
        set(findobj(fgh,'Type','uicontrol','Style','text'),'Enable','on');
        set(uih.panel.MaskProp.textHandles, 'Enable','off');
        drawnow;
        
        imSize = size(orgImg);
        
        % axis
        axPos=AxesPosition;
        set(axh, 'XLim', [0.5, imSize(2)], 'YLim', [0.5, imSize(1)],...
            'CLim', [min(orgImg(:)) max(orgImg(:)) ], 'Position', axPos) ;
        % slider texts
        set(sltexth,'Enable','on');
        set(sltexth(3),'string',int2str(imSize(3)));
        set(sltexth(1:2),'string','1');
        % slider
        if imSize(3) > 1
            set(slh,'min',1,'max',imSize(3),'sliderstep', [1 10]./(imSize(3)-1), 'value',1,'Enable','on');
        end
        % image
        imhBgImg=image('Parent',axh,'CData',orgImg(:,:,1),'CDataMapping','Scaled');
        % axPos=AxesPosition --------------------------------------------
        function axPos=AxesPosition
            axPos=zeros(1,4);
            axPos(2)=defaultAxesPosition(2);

            if     imSize(1) > imSize(2) % height > width
                axPos(4) = defaultAxesPosition(4);
                axPos(3) = round(imSize(2)/imSize(1) * defaultAxesPosition(4));
                axPos(1) = defaultAxesPosition(1) + round((defaultAxesPosition(3) - axPos(3))*0.5);
            elseif imSize(1) < imSize(2) % height < width
                axPos(3) = defaultAxesPosition(3);
                axPos(4) = round(imSize(1)/imSize(2) * defaultAxesPosition(3));
                axPos(1) = defaultAxesPosition(1);
            else
                axPos=defaultAxesPosition;
            end

            
        end
        
    end

% InitMenu ------------------------------------------------------------------
    function InitMenu(maskid)
        if isempty(masks(1).img) 
            set([struct2array(uimh.Estimate)  uimh.File.Save],'Enable','off');            
        end
        
        if ~isempty(orgImg);
            set([uimh.Estimate.VesselMask   uimh.File.Save], 'Enable', 'on');
        end
        
        for n=maskid
            if ~isempty(masks(n).img)
                switch n
                    case 1; set(uimh.Estimate.ArteryMask,  'Enable','on');
                    case 2; set([uimh.Estimate.ROIs get(uimh.Estimate.ROIs, 'Children')'],      'Enable','on');
                    case 3; set([uimh.Ana get(uimh.Ana,'Children')'],'Enable','on');
                end
            else
                switch n
                    case 1; set(uimh.Estimate.ArteryMask,  'Enable','off');
                    case 2; set([uimh.Estimate.ROIs get(uimh.Estimate.ROIs, 'Children')'],      'Enable','off');
                    case 3; set([uimh.Ana get(uimh.Ana,'Children')'],'Enable','off');
                end
            end
        end
    end

% =========================================================================
%% ## UIMenu - Estimate ##
% =========================================================================

% -------------------------------------------------------------------------
% UI Objects;
% -------------------------------------------------------------------------
ohMenu= uimenu('Parent',fgh, 'Label','Estimation');
uimh.Estimate.VesselMask = uimenu('Parent',ohMenu,'Label','Vessel Mask', ...
    'Callback', @CBestimateVesselMask, 'Enable', 'off');
uimh.Estimate.ArteryMask  = uimenu('Parent',ohMenu,'Label','Vessel Class' , ...
    'Callback', @CBestimateArteryMask,  'Enable', 'off') ;

uimh.Estimate.ROIs      = uimenu('Parent',ohMenu,'Label','ROIs','Enable', 'off','Visible','off') ;
uimenu('Parent',ohMenu,'Label','Segmentation to Branches', ...
    'Callback', @CBestimateSkeleton,      'Enable', 'on') ;

% -------------------------------------------------------------------------
% Global Values
% -------------------------------------------------------------------------
arterySkelGam=[];
veinSkelGam  =[];
arteryBranches=[];
veinBranches   =[];

% -------------------------------------------------------------------------
% Functions
% -------------------------------------------------------------------------

% CBestimateVesselMask -----------------------------------------------------
    function CBestimateVesselMask(oh,event)%#ok<INUSD>

        if isempty(orgImg)
            errordlg('No orgImg defined.')
        end
        
        if ~isempty(masks(1).img)
            masks(1).img = false(size(masks(1).img));
%             delete(masks(1).handle)
        end
        
        dlgH=DialogShow('Calculating Vessel Mask.');
        [appImg masks(1).img]= VBSvesselMask(orgImg);
        masks(1).visible = true;
        InitMaskHandles(1);
        set(uimh.Estimate.ArteryMask,'Enable','on');
        DialogHide(dlgH);
    end


% CBestimateArteryMask ------------------------------------------------------
    function CBestimateArteryMask(oh,event)%#ok<INUSD>
        if isempty(masks(1).img) 
            errordlg('No VesselMask defined.')
        end

        [maxInArtery, maxInVein]=FindLocalMax(appImg);
        masks(2).img = (appImg<=maxInArtery) & masks(1).img;
        masks(3).img = (appImg>=maxInVein)   & masks(1).img;
        masks(4).img = ~masks(3).img & ~masks(2).img &  masks(1).img;

        dlgH=DialogShow('Calculating Artery & Vein Mask.');
        tmpAppImg = masks(3).img.*maxInVein + masks(2).img.*maxInArtery +  masks(4).img.*appImg;
        [map sepTime]=VBSregionMerge(tmpAppImg);
        DialogHide(dlgH);
        %             delete(masks(2).handle)
        masks(2).img = (map < min(sepTime)) & masks(1).img;
        masks(3).img = (map > max(sepTime)) & masks(1).img;

        masks(2).img=~CutSmallRegions(~CutSmallRegions(masks(2).img));
        masks(3).img=~CutSmallRegions(~CutSmallRegions(masks(3).img));
        masks(1).img=masks(1).img | masks(2).img | masks(3).img;
        masks(4).img = ~masks(3).img & ~masks(2).img &  masks(1).img;
        
        
        masks(2).visible = true;
        masks(3).visible = true;
        masks(4).visible = true;
        
        InitMaskHandles(2:4);
        set([uimh.Estimate.ROIs get(uimh.Estimate.ROIs, 'Children')'],   'Enable', 'on');
        
        
        function bw=CutSmallRegions(bw)
            cc=bwconncomp(bw,4);
            bw =false(cc.ImageSize);
            for n=1:cc.NumObjects
                tmpbw=false(cc.ImageSize);
                tmpbw(cc.PixelIdxList{n}) = true;
                tmpbw=bwmorph(tmpbw,'erode',1);
                if  sum(tmpbw(:))~=0
                    bw(cc.PixelIdxList{n})=true;
                end
            end
        end


        function [maxInArtery, maxInVein]=FindLocalMax(appTimeImg)
            nonZeroAppTime=appTimeImg(appTimeImg(:)>1);
            histCentre=min(nonZeroAppTime):max(nonZeroAppTime);
            histBins=hist(nonZeroAppTime,histCentre);
            histCentre=[histCentre(1)-1, histCentre, histCentre(end)+1];
            histBins  =[ 0 histBins 0];
            localMaxs =(histBins(2:end-1)>histBins(1:end-2)) & (histBins(2:end-1)>histBins(3:end));
            localMaxBins  = histBins([false, localMaxs , false]);
            localMaxCentre= histCentre([false, localMaxs , false]);
            localMaxCentre= localMaxCentre(localMaxBins>(100));
            maxInArtery = localMaxCentre(1);
            maxInVein   = localMaxCentre(end);
            return;
        end
    end

% CBestimateSkeleton --------------------------------------------
    function CBestimateSkeleton(oh,event)%#ok<INUSD>
        if isempty(masks(2).img) || isempty(masks(3).img)
            errordlg('No Artery or Vein Mask defined.')
        end
        h=GuiSegmantBranch(masks(2).img,oh);% retarn values are in userdata of oh
        waitfor(h);
        userdata=get(oh,'Userdata');
        if isempty(userdata);
            h=msgbox('canceled');pause(0.5);delete(h);
            return;
        else
            set(oh,'Userdata',[])
            arterySkelGam=userdata.gamMap; %#ok<SETNU,UNUSD>
            arteryBranches=userdata.segVessels;%#ok<SETNU,UNUSD>
        end

        h=GuiSegmantBranch(masks(3).img,oh);% retarn values are in userdata of oh
        waitfor(h);
        userdata=get(oh,'Userdata');
        if isempty(userdata);
            h=msgbox('canceled');pause(0.5);delete(h);
            return;
        else
            set(oh,'Userdata',[])
            veinSkelGam=userdata.gamMap;%#ok<SETNU,UNUSD>
            veinBranches =userdata.segVessels;%#ok<SETNU,UNUSD>
        end
        h=msgbox('Complete!');pause(0.5);delete(h);
        
    end

% InitMaskHandles ---------------------------------------------------------
    function InitMaskHandles(vec)
        for n=vec
            if isempty(masks(n).img); 
                set(uih.panel.MaskProp.visibleHandles(n), 'Value', 0);
                continue;
            end;
            [trueImg alphaData]=PrepMaskOverlay(...
                masks(n).img,...
                masks(n).color, masks(n).alpha);
            masks(n).visible = true;
            set(uih.panel.MaskProp.visibleHandles(n), 'Value', 1);
            if isempty(masks(n).handle)
                masks(n).handle = image('Parent',axh,'CData',trueImg,'CDataMapping','direct',...
                    'AlphaData', alphaData ,'AlphaDataMapping', 'scaled');
            else
                set(masks(n).handle,'CData',trueImg, 'AlphaData', alphaData);
            end
            SwitchUIEnableWithMask(n,'on','all');
        end
        drawnow;
        % refresh;
    end

% SwitchUIEnableWithMask --------------------------------------------------
    function SwitchUIEnableWithMask(maskIds,onoff,varargin)
        if nargin ==3 && strcmp(varargin{1},'all')
            objects={'text', 'editable', 'visible', 'color', 'alpha'};
        else
            objects=varargin;
        end
        for n=maskIds
            for m=objects
                switch char(m)
                    case 'text';    set(uih.panel.MaskProp.textHandles(n),    'Enable',onoff);
                    case 'editable';set(uih.panel.MaskProp.editHandles(n),    'Enable',onoff);
                    case 'visible'; set(uih.panel.MaskProp.visibleHandles(n), 'Enable',onoff);
                    case 'color';   set(uih.panel.MaskProp.colorHandles(n),   'Enable',onoff);
                    case 'alpha';   set(uih.panel.MaskProp.alphaHandles(n),   'Enable',onoff);
                end
            end

        end
    end

% SwitchMaskVisible -------------------------------------------------------
    function SwitchMaskVisible(maskIds,onoff,mode)        
        if nargin < 3
            mode = 'wStruct';
        end
        
        for n=maskIds
            set(masks(n).handle, 'Visible', onoff);
            set(uih.panel.MaskProp.visibleHandles(n), 'Value',   OnOffToBool(onoff));
            if strcmp(mode,     'wStruct')
                masks(n).visible=OnOffToBool(onoff);
            end
        end
    end


% =========================================================================
%% ## UIMenu - Analysis ##
% =========================================================================

% --------------------------------------------------------------------------
% UI Objects;
% --------------------------------------------------------------------------

uimh.Ana = uimenu('Parent',fgh, 'Label','Analysis','Enable','off');
uimenu('Parent',uimh.Ana,'Label','Histgram',   'Callback', @CBManaHist, 'Enable','off');


% =========================================================================
%%% ## UI Toolbar ##
% =========================================================================
% ------------------------------------------------------------------------
% UI Objects
% ------------------------------------------------------------------------
dcmh=datacursormode(fgh);
set(dcmh,'SnapToDataVertex','on', 'DisplayStyle','datatip','Updatefcn', @DCMupdateFcn)
% ------------------------------------------------------------------------
% Functions
% ------------------------------------------------------------------------
% 

% DCMupdateFcn
    function outText=DCMupdateFcn(oh,event) %#ok<INUSL>
        pos = get(event,'Position');
        outText = {...
            ['X:   ', num2str(pos(1),4)],...
            ['Y:   ', num2str(pos(2),4)]};
        xdata=1:size(orgImg,3);
        ydata=double(squeeze(orgImg(pos(2), pos(1), :)));
        plot(axth, xdata, ydata,'b-',  xdata, medfilt1(ydata,5),'r-')
        set(axth,'Ylim',[0 4095])
    end


% =========================================================================
%% ## UIPANEL Mask Properties ##
% =========================================================================

% --------------------------------------------------------------------------
% global vals
% --------------------------------------------------------------------------
uih.panel.MaskProp.textHandles    = [[] [] [] []]; % handles of edit checkboxes
uih.panel.MaskProp.editHandles    = [[] [] [] []]; % handles of edit checkboxes
uih.panel.MaskProp.visibleHandles = [[] [] [] []];
uih.panel.MaskProp.colorHandles   = [[] [] [] []];
uih.panel.MaskProp.alphaHandles   = [[] [] [] []];
imh=[];                   % handle of current image
editMaskIndex = [];       % index of current editting mask

% --------------------------------------------------------------------------
% UI Objects;
% --------------------------------------------------------------------------
phMaskProp=uipanel('Parent',fgh,'Units','pixels',...
    'Position', [(min(figureSize)*[1 1]+[0 -250]) 275 200],'Title','Mask Properties');
propName={'Editable', 'Visible', 'Color', 'Alpha'};

for N=1:4
    uicontrol('Parent', phMaskProp, 'Units','pixels','Style','text','String',char(propName{N}),...
        'Position', [60+(N-1)*50 150 40 20]);
end
clear propName;

for N=1:length(masks)
    uih.panel.MaskProp.textHandles(N)=...
        uicontrol('Parent', phMaskProp, 'Units','pixels',...
        'Style','text','String',masks(N).description,...
        'Position', [10 155-(N)*35 55 20]);

    uih.panel.MaskProp.editHandles(N)=...
        uicontrol('Parent', phMaskProp, 'Units','pixels',...
        'Style','checkbox','Value',masks(N).editable,...
        'Position', [ 70 160-(N)*35 20 20],'UserData', N, 'Callback', @CBPMaskPropEditable);

    uih.panel.MaskProp.visibleHandles(N) = ...
        uicontrol('Parent', phMaskProp, 'Units','pixels',...
        'Style','checkbox','Value',masks(N).visible,...
        'Position', [120 160-(N)*35 20 20],'UserData', N, 'Callback', @CBPMaskPropVisible);

    uih.panel.MaskProp.colorHandles(N) = ...
        uicontrol('Parent', phMaskProp, 'Units','pixels',...
        'Style','pushbutton','BackgroundColor',masks(N).color,...
        'Position', [160 160-(N)*35 40 20],'UserData', N, 'Callback', @CBPMaskPropColor);

    uih.panel.MaskProp.alphaHandles(N) = ...
        uicontrol('Parent', phMaskProp, 'Units','pixels',...
        'Style','edit', 'String', num2str(masks(N).alpha),...
        'Position', [210 160-(N)*35 40 20],'UserData', N, 'Callback', @CBPMaskPropAlpha);
end

% -------------------------------------------------------------------------
% Functions
% -------------------------------------------------------------------------

% CBPMaskPropEditable ------------------------------------------------------
    function CBPMaskPropEditable(oh,event)%#ok<INUSD>

        set(imh,'ButtonDownFcn',[])
        
        index=get(oh,'UserData');

        if sum(cell2mat(get(uih.panel.MaskProp.editHandles,'Value')))>1
            set(uih.panel.MaskProp.editHandles,'Value',false);
            set(oh,'Value',true);
        end
        
        set(findobj(phBgSelect,'style','edit'),'enable','on');

        value =  get(oh,'Value');
        masks(index).editable = value;

        if value % case on
            set(findobj(fgh,'type','uimenu'),'Enable','off')
            imh = masks(index).handle;
            set(get(phEditTools,'Children'),'Enable','on')
            set(imh,'ButtonDownFcn',get(get(phEditTools,'SelectedObject'),'UserData'))
            for n=1:length(masks)
                if n ~= index;
                    SwitchUIEnableWithMask(n,'off','text','editable');
                end;
            end
            editMaskIndex = index;
            if index<4
                SwitchMaskVisible(index+1:length(masks),'off');
            end
        else     % case off
            set(get(phEditTools,'Children'),'Enable','off')
            set(findobj(fgh,'type','uimenu'),'Enable','on')
            imh=[];
            editMaskIndex = [];
            for n=1:length(masks)
                if ~isempty(masks(n).img);
                    SwitchUIEnableWithMask(n,'on','text','editable');
                    SwitchMaskVisible(n,'on');
                end;
            end
        end

        
        
    end

% CBPMaskPropVisible -------------------------------------------------------
    function CBPMaskPropVisible(oh,event)%#ok<INUSD>
        SwitchMaskVisible(get(oh,'UserData'), BoolToOnOff(get(oh,'Value')));
        DrawImages;
    end

% CBPMaskPropColor -------------------------------------------------------
    function CBPMaskPropColor(oh,event)%#ok<INUSD>
        index=get(oh,'UserData');
        newcolor=uisetcolor;
        if numel(newcolor) == 3 % not canceled case
            set(oh,'BackgroundColor',newcolor)
            masks(index).color = newcolor;
            DrawImages;
        end
    end

% CBPMaskPropAlpha ---------------------------------------------------------
    function CBPMaskPropAlpha(oh,event)%#ok<INUSD>
        index=get(oh,'UserData');
        val  =str2double(get(oh,'String'));
        if val < 0;val=0; elseif val > 1;val=1;end
        set(oh,'String',num2str(val));
        masks(index).alpha=val;
        DrawImages;
    end



% =========================================================================
%% ## UI ButtonGroup Edit Tool ##
% =========================================================================

% --------------------------------------------------------------------------
% global vals
% --------------------------------------------------------------------------


% --------------------------------------------------------------------------
% UI Objects
% --------------------------------------------------------------------------

phEditTools=uibuttongroup('Parent',fgh,'Units','pixels',...
    'Position', [(min(figureSize)*[1 1]+[0 -370]) 200 100],'Title','Edit Tools');...'SelectionChangeFcn',@SCFeditTools);


uicontrol('Style','pushbutton','Parent',phEditTools,'String','Ellipse', 'Callback',@CBeditDrawROI,'Position', [ 10 10 50 20]);
uicontrol('Style','pushbutton','Parent',phEditTools,'String','Rect',    'Callback',@CBeditDrawROI,'Position', [ 60 10 50 20]);
uicontrol('Style','pushbutton','Parent',phEditTools,'String','Freehand','Callback',@CBeditDrawROI,'Position', [110 10 50 20]);
uicontrol('Style','pushbutton','Parent',phEditTools,'String','Line',    'Callback',@CBeditDrawROI,'Position', [ 10 30 50 20]);
uicontrol('Style','pushbutton','Parent',phEditTools,'String','Point',   'Callback',@CBeditDrawROI,'Position', [ 60 30 50 20]);
uicontrol('Style','pushbutton','Parent',phEditTools,'String','Poly',    'Callback',@CBeditDrawROI,'Position', [110 30 50 20]);
uicontrol('Style','popupmenu', 'Parent',phEditTools,'String',{'Write','Erase'},'CallBack',@CBeditChangeColor,'Position',[10 60 100 20],...
    'Value',1,'ForegroundColor',[1 0 0]);

% -------------------------------------------------------------------------
% Functions
% -------------------------------------------------------------------------

% SCFeditTools ------------------------------------------------------------
%     function SCFeditTools(oh,event)%#ok<INUSD>
%         set(imh,'ButtonDownFcn',get(get(oh,'SelectedObject'),'UserData'));
%     end


% EDITpenEraser -----------------------------------------------------------

    function CBeditChangeColor(oh,event)%#ok<INUSD>
        switch get(findobj(phEditTools,'Style','popupmenu'),'Value')
            case 1; fgcolor=[1 0 0]; % Write: 1
            case 2; fgcolor=[0 0 1]; % Erase: 2
        end
        set(oh,'ForegroundColor',fgcolor)
    end

    function CBeditDrawROI(oh,event)%#ok<INUSD>
        set(get(phEditTools,'Children'),'Enable','off')
        bgc=get(oh,'BackgroundColor');
        set(oh,'BackgroundColor','r');
        switch lower(get(oh,'String'))
            case 'ellipse' ; p=imellipse(axh);
            case 'rect'    ; p=imrect(axh);
            case 'freehand'; p=imfreehand(axh);
            case 'line'    ; p=imline(axh);
            case 'point'   ; p=impoint(axh);
            case 'poly'    ; p=impoly(axh);
        end
        wait(p);
        img  = sum(get(imh,'CData'),3) > 0;
        if isempty(p)
            EDITupdateImage(img);
            set(get(phEditTools,'Children'),'Enable','on')
            set(oh,'BackgroundColor',bgc)
            return;
        end
        
        BW = createMask(p,imh);
        delete(p);clear p;
        switch get(findobj(phEditTools,'Style','popupmenu'),'Value')
            case 1; img=(img |  BW); % Write
            case 2; img=(img & ~BW); % Erase
        end
        EDITupdateImage(img);
        set(get(phEditTools,'Children'),'Enable','on')
        set(oh,'BackgroundColor',bgc)
    end



% EDITupdateImage ---------------------------------------------------------
    function EDITupdateImage(bwimg)
        switch editMaskIndex
            case {2,3,4}
                bwimg = (bwimg & masks(1).img);
        end
        
        masks(editMaskIndex).img=bwimg;
        [trueImg alphaData]=PrepMaskOverlay(bwimg, masks(editMaskIndex).color ,masks(editMaskIndex).alpha);
        set(imh,'CData', trueImg, 'AlphaData', alphaData);
        
        
        switch editMaskIndex
            case 1
                bwimg2=SFEDITupdateOtherImg(1, bwimg);
                SFEDITupdateOtherImg(3, bwimg2);
                SFEDITupdateOtherImg(4, bwimg2);
        end
        
        
        function newbwimg = SFEDITupdateOtherImg(n, bwimg)
            if ~isempty(masks(n).img)
                newbwimg = masks(n).img & bwimg;
                masks(n).img = newbwimg;
                [trueImg alphaData]=PrepMaskOverlay(newbwimg, masks(n).color ,masks(n).alpha);
                set(masks(n).handle,'CData', trueImg, 'AlphaData', alphaData);
            else
                newbwimg =[];
            end
        end
        refresh;drawnow;
    end


% =========================================================================
%% ## Sub Functions using gloval vals in main function ##
% =========================================================================
%% DrawImages
    function DrawImages
        currentSlice = CurrentSlice;
        switch bgIndex
            case 1
                set(imhBgImg,'CData',orgImg(:,:,currentSlice));
            case 2
                
            otherwise
                errordlg('under construction')
                return;
        end
        for n=1:length(masks)
            if ~isempty(masks(n).img)
                [trueImg, alphaData]=PrepMaskOverlay(...
                    masks(n).img,...
                    masks(n).color, masks(n).alpha);
                set(masks(n).handle,'CData',trueImg, 'AlphaData', alphaData);%,...
                % 'Visible',BoolToOnOff(masks(n).visible));
            end
        end
        drawnow;
    end

%% CurrentSlice
    function val=CurrentSlice
        val = round(get(slh,'Value'));
    end


% =#=*==#=*==#=*==#=*==#=*==#=*==#=*==#=*==#=*==#=*==#=*==#=*==#=*==#=*==#=
%
%%  - # - # - # - End of Main function - # - # - # -
%
% =#=*==#=*==#=*==#=*==#=*==#=*==#=*==#=*==#=*==#=*==#=*==#=*==#=*==#=*==#=
set(findobj(fgh,'Type','uicontrol'),'Enable','on'); %DBG
set(findobj(fgh,'Type','uicontrol','Style','text'),'Enable','on');
set(uih.panel.MaskProp.textHandles, 'Enable','on'); %DBG

end




% =========================================================================
%% ## SUBFUNCTIONS ##
% =========================================================================

%% Dialogs 
function dlgH=DialogShow(words)
fgh=gcf;
dlgH=dialog('Position',[0 0 300 100]);
uicontrol('Style','text','Parent',dlgH,'BackgroundColor',get(dlgH,'Color'),'String','','Units','normalized',...
    'Position',[0 0 0.9 1]);
centerfig(dlgH,fgh);
set(get(dlgH,'Children'),'String',words)
drawnow;
end
function DialogHide(dlgH)
set(get(dlgH,'Children'),'String','Complete.');
drawnow;pause(0.5);
set(dlgH, 'WindowStyle','normal','Visible','off')
drawnow;
end


%---------------------------------------------------------------------------
%% [img dirName]= ReadOrgImg(dirName)
%---------------------------------------------------------------------------
function [img saveFileName]= ReadOrgImg(description)
        
% uiPos=get(fgh,'Position');
% uiPos=round(uiPos(1:2)+uiPos(3:4)*0.5-[280 210]);

% get filelist
[fileName, pathName] = uigetfile({'*.mat','MAT-files (*.mat)';},description);
if isnumeric(fileName) && fileName==0 % canceled case
    img = []; 
    saveFileName = []; 
    return;
end

%dlgh=DialogShow('Reading File.');
switch fileName(end-2:end)
    case 'mat' % mat
        [img fileprefix]=LoadMatFile(pathName,fileName);
    otherwise
        return;
end

%DialogHide(dlgh);
% setting outputs

if nargout  >= 2
    saveFileName = fullfile(pathName,['ana' fileprefix '.mat']);
end


end


%---------------------------------------------------------------------------


function [img fileprefix]=LoadMatFile(pathName,fileName)%#ok<STOUT>
load(fullfile(pathName,fileName));
eval(['img=' sprintf('%s',fileName(1:end-4)) '.img;']);
fileprefix=fileName(1:end-4);
end

%%



%% [trueImg alphaData]=PrepMaskOverlay(logicalImg,imColor,alphaValue)
%---------------------------------------------------------------------------
function [trueImg alphaData]=PrepMaskOverlay(logicalImg,imColor,alphaValue)

trueImg=double(repmat(logicalImg,[1 1 3]));
for n=1:3
    trueImg(:,:,n) = trueImg(:,:,n) * imColor(n);
end
alphaData = logicalImg.*alphaValue;

end

%---------------------------------------------------------------------------
%% str=BoolToOnOff(val)
%---------------------------------------------------------------------------
function str=BoolToOnOff(val)
if val; str = 'on';
else    str = 'off';
end
end

%---------------------------------------------------------------------------
%% bool=OnOffToBool(onoff)
%---------------------------------------------------------------------------
function bool=OnOffToBool(onoff)
switch onoff
    case 'on'; bool = true;
    case 'off';bool = false;
end
end


%---------------------------------------------------------------------------
%% masks=InitMasks
%---------------------------------------------------------------------------
function masks=InitMasks
descriptions={'VesselMask', 'Artery', 'Vein', 'Unknown'};
colors =     [1 1 0;        1 0 0;      0 0 1;       0 .5 0];

masks = struct(...
    'description', descriptions,...
    'img',     [],...
    'color',   [],...
    'alpha',   0.5,...
    'visible', false,...
    'editable',false,...
    'handle',  []);

for n=1:length(descriptions)
    masks(n).color   =colors(n,:);
end

end

Contact us