Taimoor Khan
Taimoor Khan

Reputation: 615

Draw a line in a 3D set of images

In other words the same line should appear atop each image. Im using the imshow3D function to preview my images.

Upvotes: 0

Views: 230

Answers (1)

Benoit_11
Benoit_11

Reputation: 13945

Here is a way to do it without imshow3D (just create a new .m file with the function below). I think it will be easier for you to understand what is going on behind the code then.

The trick is to add a pushbutton and the function imline in the callback in order to interactively draw a line. Then, as the user scrolls through the stack we use the function line to actually draw a line using the position of the previously drawn line.

I used the mri data that ships with Matlab but that should work with your data/dicom images/whatever.

Code:

function ScrollMRI(~)
clc
clear
close all

%// Load demo data
S = load('mri');

%// Get dimensions and number of slices.
ImageHeight = S.siz(1); %// Not used here
ImageWidth = S.siz(2); %// Not used here
NumSlices = S.siz(3);

S.D = squeeze(S.D);

%// Create GUI
hFig = figure('Position',[100 100 400 400],'Units','normalized');

%// create axes with handle
handles.axes1 = axes('Position', [0.2 0.2 0.6 0.6]);

%// create y slider with handle
handles.y_slider = uicontrol('style', 'Slider', 'Min', 1, 'Max', NumSlices, 'Value',1, 'Units','normalized','position', [0.08 0.2 0.08 0.6], 'callback', @(s,e) UpdateY);
handles.SlideryListener = addlistener(handles.y_slider,'Value','PostSet',@(s,e) YListenerCallBack);

%// Create pusbutton to draw line
handles.DrawLineButton= uicontrol('style', 'push','position', [40 40 100 30],'String','Draw line', 'callback', @(s,e) DrawLine);

%// Flag to know whether pushbutton has been pushed
handles.LineDrawn = false;

%// Show 1st slice
imshow(S.D(:,:,1))

guidata(hFig,handles);

%// Listeners callbacks followed by sliders callbacks. Used to display each
%// slice smoothly.
    function YListenerCallBack

        handles = guidata(hFig);

        %// Get current slice
        CurrentSlice = round(get(handles.y_slider,'value'));

        hold on
        imshow(S.D(:,:,CurrentSlice));

        %// If button was button, draw line
        if handles.LineDrawn
            line([handles.LinePos(1,1) handles.LinePos(2,1)],[handles.LinePos(1,2) handles.LinePos(2,2)],'LineWidth',2,'Color','y');
        end
        drawnow

        guidata(hFig,handles);

    end

    function UpdateY(~)

        handles = guidata(hFig); %// Get handles.
        CurrentSlice = round(get(handles.y_slider,'value'));

        hold on
        imshow(S.D(:,:,CurrentSlice));

        if handles.LineDrawn
            line([handles.LinePos(1,1) handles.LinePos(2,1)],[handles.LinePos(1,2) handles.LinePos(2,2)],'LineWidth',2,'Color','y');
        end
        drawnow

        guidata(hFig,handles);

    end

%// Pushbutton callback to draw line.
    function DrawLine(~)
        handles = guidata(hFig); %// Get handles.

        hLine = imline(gca);

        %// Get position of line and store it in handles structure.
        handles.LinePos = hLine.getPosition(); %// handles.LinePos is a 2-by-2 array [X1 Y1; X2 Y2]

        %// Set tag to true.
        handles.LineDrawn = true;
        guidata(hFig,handles);
    end

end

Here is a screenshot of the GUI before pressing the button:

enter image description here

and then after pressing it and drawing a line:

enter image description here

The line stays at the same position as you scroll through the stack.

Hope that helps get you started!

Upvotes: 2

Related Questions