Code covered by the BSD License  

Highlights from
OrthoView3D

image thumbnail

OrthoView3D

by

 

11 Feb 2012 (Updated )

MATLAB GUI for exploring 3D datasets through a sleek and simple interface (sample dataset included)

orthoview3d(varargin)
function varargout = orthoview3d(varargin)
%ORTHOVIEW3D GUI for interactive viewing of 3D Volumes
%   ORTHOVIEW3D is used to view orthographic slices of 3D volumes
%    
%   Type in an expression that generates a 3D array
%   then press the Display button
%
%   3D expressions such as: rand(50,40,30) or
%   the name or a 3D array variable in the workspace
%
%   Use the scroll bars to change the number of the slice viewed
%
%   Use the transpose, flipud, or fliplr to
%   transpose the view, flip it vertically, or horizontally
%
%   Change the Pixel Size values to the volume's physical dimensions
%   so the aspect ratio is displayed properly
%   (note: you can use relative values
%   for example use 1,3,2 instead of 0.5,1.5,1.0
%   then press "Adjust Pixel Size"
%
%   Example:
%       load defrise
%       orthoview3d
%       (Type 'defrise' in the box where 'rand(50,40,30)' appears)
%       (Press 'Display')
%
%   See also: VIEW3D, SLICE, MONTAGE, ISOSURFACE
%
%   Jered R Wells
%   02/10/2012
%   jered [dot] wells [at] gmail [dot] com
%
%   Author's Note
%   This file was adapted from ORTHOVIEW by Ghassan Hamarneh (see ref).
%   It has been accelerated and simplified for viewing larger volumes.
%   A simple window/level tool has also been added to supplement the
%   viewing of medical images with familiar tools.
%
%   Acknowledgement to:
%   http://www.mathworks.de/matlabcentral/fileexchange/2256-orthoview
%   Ghassan Hamarneh, ghamarneh@yahoo.com
% 


if ~isempty(varargin) & (all(size(varargin{1})==[3 1])  | all(size(varargin{1})==[1 3]))
    spanvar=varargin{1};
end

if nargin == 0 | exist('spanvar')% LAUNCH GUI    
    fig = openfig(mfilename,'reuse');        % Generate a structure of handles to pass to callbacks, and store it. 
    handles = guihandles(fig);
    guidata(fig, handles);    
    if nargout > 0
        varargout{1} = fig;
    end
    
    if exist('spanvar')
        set(handles.edit2,'string',num2str(spanvar(1))) 
        set(handles.edit3,'string',num2str(spanvar(2)))         
        set(handles.edit4,'string',num2str(spanvar(3))) 
    end
elseif ischar(varargin{1}) % INVOKE NAMED SUBFUNCTION OR CALLBACK
    try
        if (nargout)
            [varargout{1:nargout}] = feval(varargin{:}); % FEVAL switchyard
        else
            feval(varargin{:}); % FEVAL switchyard
        end
    catch
        disp(lasterr);
    end
end


%| ABOUT CALLBACKS:
%| GUIDE automatically appends subfunction prototypes to this file, and 
%| sets objects' callback properties to call them through the FEVAL 
%| switchyard above. This comment describes that mechanism.
%|
%| Each callback subfunction declaration has the following form:
%| <SUBFUNCTION_NAME>(H, EVENTDATA, HANDLES, VARARGIN)
%|
%| The subfunction name is composed using the object's Tag and the 
%| callback type separated by '_', e.g. 'slider2_Callback',
%| 'view3d_CloseRequestFcn', 'axis1_ButtondownFcn'.
%|
%| H is the callback object's handle (obtained using GCBO).
%|
%| EVENTDATA is empty, but reserved for future use.
%|
%| HANDLES is a structure containing handles of components in GUI using
%| tags as fieldnames, e.g. handles.orthoview3d, handles.slider2. This
%| structure is created at GUI startup using GUIHANDLES and stored in
%| the figure's application data using GUIDATA. A copy of the structure
%| is passed to each callback.  You can store additional information in
%| this structure at GUI startup, and you can change the structure
%| during callbacks.  Call guidata(h, handles) after changing your
%| copy to replace the stored original so that subsequent callbacks see
%| the updates. Type "help guihandles" and "help guidata" for more
%| information.
%|
%| VARARGIN contains any extra arguments you have passed to the
%| callback. Specify the extra arguments by editing the callback
%| property in the inspector. By default, GUIDE sets the property to:
%| <MFILENAME>('<SUBFUNCTION_NAME>', gcbo, [], guidata(gcbo))
%| Add any extra arguments after the last argument, before the final
%| closing parenthesis.

% --------------------------------------------------------------------
function varargout = slider1_Callback(h, eventdata, handles, varargin)
myplot1(handles);

% --------------------------------------------------------------------
function varargout = slider2_Callback(h, eventdata, handles, varargin)
myplot2(handles);

% --------------------------------------------------------------------
function varargout = slider3_Callback(h, eventdata, handles, varargin)
myplot3(handles);

% --------------------------------------------------------------------
function varargout = edit1_Callback(h, eventdata, handles, varargin)

% --------------------------------------------------------------------
function varargout = pushbutton1_Callback(h, eventdata, handles, varargin)

a=get(handles.edit1,'String');
handles.vol=double(squeeze(evalin('base',a)));

if ndims(handles.vol)~=3,
    disp('Requested volume is not 3-D')
    return
end

% Make all objects visible
set(handles.checkbox1,'Visible','on')
set(handles.checkbox2,'Visible','on')
set(handles.checkbox3,'Visible','on')
set(handles.checkbox4,'Visible','on')
set(handles.checkbox5,'Visible','on')
set(handles.checkbox6,'Visible','on')
set(handles.checkbox7,'Visible','on')
set(handles.checkbox8,'Visible','on')
set(handles.checkbox9,'Visible','on')
set(handles.checkbox11,'Visible','on')
set(handles.axes1,'Visible','on')
set(handles.axes2,'Visible','on')
set(handles.axes3,'Visible','on')
set(handles.slider1,'Visible','on')
set(handles.slider2,'Visible','on')
set(handles.slider3,'Visible','on')
set(handles.text1,'Visible','on')
set(handles.text2,'Visible','on')
set(handles.text3,'Visible','on')
set(handles.text7,'Visible','on')
set(handles.text8,'Visible','on')
set(handles.text9,'Visible','on')
set(handles.edit2,'Visible','on')
set(handles.edit3,'Visible','on')
set(handles.edit4,'Visible','on')
set(handles.pushbutton7,'Visible','on')

[handles.sx,handles.sy,handles.sz]=size(handles.vol);
set(handles.slider1,'min',1);
set(handles.slider2,'min',1);
set(handles.slider3,'min',1);
set(handles.slider1,'max',handles.sx);
set(handles.slider2,'max',handles.sy);
set(handles.slider3,'max',handles.sz);
set(handles.slider1,'SliderStep',[1/handles.sx 5/handles.sx]);
set(handles.slider2,'SliderStep',[1/handles.sy 5/handles.sy]);
set(handles.slider3,'SliderStep',[1/handles.sz 5/handles.sz]);
set(handles.slider1,'value',round(handles.sx/2)+1);
set(handles.slider2,'value',round(handles.sy/2)+1);
set(handles.slider3,'value',round(handles.sz/2)+1);

global vmx vmn sp1 sp2 sp3

vmx=max(handles.vol(:));
vmn=min(handles.vol(:));

sp1=handles.sx/str2double(get(handles.edit2,'string'));
sp2=handles.sy/str2double(get(handles.edit3,'string'));
sp3=handles.sz/str2double(get(handles.edit4,'string'));


%axes(handles.axes1);imagesc(squeeze(handles.vol(1,:,:)));axis image;
%axes(handles.axes2);imagesc(squeeze(handles.vol(:,1,:)));axis image;
%axes(handles.axes3);imagesc(squeeze(handles.vol(:,:,1)));axis image;

set(gcf,'DoubleBuffer','on');

% myplot(handles,[1 2 3]);
myplot1(handles)
myplot2(handles)
myplot3(handles)

%%% produced error in matlab 7.0
%if ~isfield(handles,'clrmnu')
%    handles.clrmnu=0;
%end
%if ~handles.clrmnu; 
%    colormenu; 
%    handles.clrmnu=1;
%end

guidata(h,handles);

% --------------------------------------------------------------------
function varargout = checkbox1_Callback(h, eventdata, handles, varargin)
myplot1(handles);
% --------------------------------------------------------------------
function varargout = checkbox2_Callback(h, eventdata, handles, varargin)
myplot2(handles);
% --------------------------------------------------------------------
function varargout = checkbox3_Callback(h, eventdata, handles, varargin)
myplot3(handles);
% --------------------------------------------------------------------
function varargout = checkbox4_Callback(h, eventdata, handles, varargin)
myplot1(handles);
% --------------------------------------------------------------------
function varargout = checkbox5_Callback(h, eventdata, handles, varargin)
myplot2(handles);
% --------------------------------------------------------------------
function varargout = checkbox6_Callback(h, eventdata, handles, varargin)
myplot3(handles);
% --------------------------------------------------------------------
function varargout = checkbox7_Callback(h, eventdata, handles, varargin)
myplot1(handles);
% --------------------------------------------------------------------
function varargout = checkbox8_Callback(h, eventdata, handles, varargin)
myplot2(handles);
% --------------------------------------------------------------------
function varargout = checkbox9_Callback(h, eventdata, handles, varargin)
myplot3(handles);

% --------------------------------------------------------------------
function varargout = pushbutton2_Callback(h, eventdata, handles, varargin)
helpdlg({'3D Volume Orthoslice Viewer','Jered Wells v1.2'})

% --------------------------------------------------------------------
function myplot1(handles)

global dmx dmn sp1 sp2 sp3
% x -- y z

s1=round(get(handles.slider1,'value'));

I=squeeze(handles.vol(s1,:,:))';
if get(handles.checkbox1,'value'), I=I'; end
if get(handles.checkbox4,'value'), I=flipud(I); end
if get(handles.checkbox7,'value'), I=fliplr(I); end
%    axes(handles.axes1);imagesc(I);
axes(handles.axes1); 
if get(handles.checkbox11,'value');imagesc(I,[dmn,dmx]);else imagesc(I);end
colormap gray
axis off
% axis image
pbaspect('manual')
pbaspect(handles.axes1,[sp1,sp3,sp2]);
%    c=get(handles.axes1,'Children'); set(c(1),'cdata',I);
set(handles.text1,'string',['x=',num2str(s1)])
% title('y-z')


function myplot2(handles)

global dmx dmn sp1 sp2 sp3
% y -- x z

s2=round(get(handles.slider2,'value'));

I=squeeze(handles.vol(:,s2,:));
if get(handles.checkbox2,'value'), I=I'; end
if get(handles.checkbox5,'value'), I=flipud(I); end
if get(handles.checkbox8,'value'), I=fliplr(I); end
%    axes(handles.axes2);imagesc(I);
axes(handles.axes2); 
if get(handles.checkbox11,'value');imagesc(I,[dmn,dmx]);else imagesc(I);end
colormap gray
axis off
% axis image
pbaspect('manual')
pbaspect(handles.axes2,[sp3,sp2,sp1]);
%    c=get(handles.axes2,'Children'); set(c(1),'cdata',I);
set(handles.text2,'string',['y=',num2str(s2)])
% title('x-z')


function myplot3(handles)
% z -- x y

global dmx dmn sp1 sp2 sp3

s3=round(get(handles.slider3,'value'));

I=squeeze(handles.vol(:,:,s3));
if get(handles.checkbox3,'value'), I=I'; end
if get(handles.checkbox6,'value'), I=flipud(I); end
if get(handles.checkbox9,'value'), I=fliplr(I); end
%    axes(handles.axes3); imagesc(I);
axes(handles.axes3);
if get(handles.checkbox11,'value');imagesc(I,[dmn,dmx]);else imagesc(I);end
colormap gray
axis off
% axis image
pbaspect('manual')
pbaspect(handles.axes3,[sp1,sp2,sp3]);
%    c=get(handles.axes3,'Children'); set(c(1),'cdata',I);
set(handles.text3,'string',['z=',num2str(s3)])
% title('x-y')

% --------------------------------------------------------------------
function varargout = edit2_Callback(h, eventdata, handles, varargin)
% myplot(handles,[1 2 3]);
% myplot1(handles)
% myplot2(handles)
% myplot3(handles)

% --------------------------------------------------------------------
function varargout = edit3_Callback(h, eventdata, handles, varargin)
% myplot(handles,[1 2 3]);
% myplot1(handles)
% myplot2(handles)
% myplot3(handles)

% --------------------------------------------------------------------
function varargout = edit4_Callback(h, eventdata, handles, varargin)
% myplot(handles,[1 2 3]);
% myplot1(handles)
% myplot2(handles)
% myplot3(handles)

% --------------------------------------------------------------------
function pushbutton5_Callback(hObject, eventdata, handles)
helpdlg({'Type in an expression that generates a 3D array                     ',...
        '   then press the Load  button                                         ',...
        '3D expressions such as: rand(50,40,30) or                            ',...
        '  the name or a 3D array variable in the workspace                   ',...
        'The 3 views display orthographic projections                         ',...
        'Use the scroll bars to change the number of the slice viewed         '...
        'Use the transpose, flipud, or fliplr to                              '...
        '  transpose the view, flip it vertically, or horizontally            ',...
        'Change the pixel sizes to adjust display dimensions                  ',...
        '  so the aspect ratio is displayed properly                          ',...
        '  (note: you can use relative values                                 ',...
        '  for example use 1,3,2 instead of 0.5,1.5,1.0)                      ',...
        '  then press "Apply Pixel Values"                                    '})

function pushbutton6_Callback(hObject, eventdata, handles)
if strcmp(questdlg('Exit OrthoView3D?','OrthoView3D','Yes','No','No'),'Yes')
    close(handles.orthoview3d);
end

function pushbutton7_Callback(hObject, eventdata, handles)
global sp1 sp2 sp3

sp1=handles.sx*str2double(get(handles.edit2,'string'));
sp2=handles.sy*str2double(get(handles.edit3,'string'));
sp3=handles.sz*str2double(get(handles.edit4,'string'));

% myplot(handles,[1 2 3]);
myplot1(handles)
myplot2(handles)
myplot3(handles)


% --- Executes on button press in checkbox11.
function checkbox11_Callback(hObject, eventdata, handles)
% hObject    handle to checkbox11 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hint: get(hObject,'Value') returns toggle state of checkbox11
global vmx vmn 

if get(handles.checkbox11,'Value')
    set(handles.text10,'Visible','on')
    set(handles.text11,'Visible','on')
    set(handles.axes6,'Visible','on')
    set(handles.slider4,'Visible','on')
    set(handles.slider5,'Visible','on')

    set(handles.slider4,'min',vmn);
    set(handles.slider5,'min',vmn);
    set(handles.slider4,'max',vmx);
    set(handles.slider5,'max',vmx);
    set(handles.slider4,'value',vmx);
    set(handles.slider5,'value',vmn);
    
    plothist(handles)
    
else
    set(handles.text10,'Visible','off')
    set(handles.text11,'Visible','off')
    axes(handles.axes6); cla
    set(handles.axes6,'Visible','off')
    set(handles.slider4,'Visible','off')
    set(handles.slider5,'Visible','off')
end

myplot1(handles)
myplot2(handles)
myplot3(handles)

function plothist(handles)

global dmn dmx

n = numel(handles.vol(:));
axes(handles.axes6); cla
hist(handles.vol(:),100);
a = axis;
l = get(handles.slider5,'Value');
w = get(handles.slider4,'Value');
dmn = min(max(l,a(1)),a(2));
dmx = max(min(dmn+w,a(2)),dmn);
x = [a(1) dmn dmx a(2)];
axis off
hold on
y = [a(3) a(3) a(4) a(4)];
plot(x,y,'r-','LineWidth',2)


% --- Executes on slider movement.
function slider4_Callback(hObject, eventdata, handles)
plothist(handles)
myplot1(handles)
myplot2(handles)
myplot3(handles)

% --- Executes on slider movement.
function slider5_Callback(hObject, eventdata, handles)
plothist(handles)
myplot1(handles)
myplot2(handles)
myplot3(handles)


% --- Executes during object creation, after setting all properties.
function slider4_CreateFcn(hObject, eventdata, handles)
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor',[.9 .9 .9]);
end

% --- Executes during object creation, after setting all properties.
function slider5_CreateFcn(hObject, eventdata, handles)
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
    set(hObject,'BackgroundColor',[.9 .9 .9]);
end


Contact us