from SPatial ANnotation (SPAN v1.3) by Nele Dael
manual frame-by-frame tracking of target points in video clips.

annotation.m
% SPAN Version 1.3 (20.08.2008)
% SPatial ANnotation program for the manual frame-by-frame tracking of target points in video clips
% developed by N'Diaye, Gille and Dael

close all
clear all
clc

global Npts S M_button I matfilename txtfilename

% Ask the user for a directory where the video's are stored and change working directory
cd(uigetdir('D:\','Pick a directory'))

% Ask the user for a file name, and set the filename variable
[filename, pathname] = uigetfile({'*.avi','AVI movie'},'Pick a movie clip');

% Change working directory to where this file file is stored
cd('D:\')

% Makes it into a long filename (path + file name)
filename = fullfile(pathname,filename);

% Load the frames of the movie in a 'movie' variable
movie = aviread(filename);

% Compute the number of frames
N = length(movie);

% Ask the user for the number of points he/she wants to click on each frame
Npts = inputdlg({'How many points?'},'Points to click',1,{'6'});

% Convert the answer into a number
Npts = str2num(Npts{1});

% Define the filename where the data will be saved in matlab and text format
[ignore,fname,ext] = fileparts(filename);
matfilename = fullfile(pathname,[fname '.mat']);
txtfilename = fullfile(pathname,[fname '.dat']);

% Open a new figure
figure

% Creates axes where to draw
ha(1) = subplot(5,4,[1 2 3 5 6 7 9 10 11 13 14 15]);
ha(2) = subplot(5,4,[4 8 12 16]);
ha(3) = subplot(5,4,17:19);
ha(4) = subplot(5,4,20);

% Loop on each frame
i = 1;
k = i;
S = ['+.ox'];
button = ones(Npts,1);
M_button = [];
I = [];
while i <= N
    % Use the first axis to plot the image
    axes(ha(1));
    % Plot the image
    imagesc(movie(i).cdata)
    % Keeps image to its original size to make it look visually unstretched
    axis image
    axis tight
    % Add a title
    title(sprintf('Movie : %s ; Image : %d / %d ',fname,i,N));
    % "Listen" to Npts clicks from the user on the image & save the
    % position in the i-th column of the x and y matrices (which have Npts
    % rows)
    if ((button(:) == 1) | (button(:) == 2) | (button(:) == 3)) & (size(button,1) == size(ones(Npts,1),1))
        [x(i,:),y(i,:),button] = ginput2(Npts,114);
        if (size(button,1) == size(ones(Npts,1),1))
            M_button(i,:) = [button'];
            I(i,:) = [i];
        else
            M_button = M_button;
        end
        if k ~= i
            button = 114*ones(Npts,1);
        else
            % Use the second axis to plot the x data
            axes(ha(2));
            plot(x(1:i,:),repmat([1:i]',[1,size(y,2)]))
            % Makes vertical axes to be N frames long and reverse: goes from top to
            % bottom
            set(ha(2),'Ylim',[0 N],'YDir','reverse');
        
            % Use the third axis to plot the y data
            axes(ha(3));
            plot(repmat([1:i]',[1,size(y,2)]),y(1:i,:))
            set(ha(3),'Xlim',[0 N],'YDir','reverse');
    
            % Use the fourth axis to plot the x-by-y data
            axes(ha(4));
            plot(x,y)
            set(ha(4),'YDir','reverse','YTick',[])

            if ((button(:) == 1) | (button(:) == 2) | (button(:) == 3)) & (size(button,1) == size(ones(Npts,1),1))
                i = i+1;
                k = k+1;
            else
                i = i;
            end
        end
    elseif button == 114*ones(Npts,1)
        button = 28;
        k = size(x,1);
        while button == 28 | button == 29
            [aa,bb,button] = ginput(1);
            if button == 28 & i > 1
                i = i-1;
            elseif button == 29 & i < k
                i = i+1;
            else
                i = i;
            end
            axes(ha(1));
            imagesc(movie(i).cdata)
            axis image
            axis tight
            title(sprintf('Movie : %s ; Image : %d / %d ',fname,i,N));
            hold on
            for j = 1:Npts
                color = ['bgrcmyw'];
                if M_button(i,j) == 1
                    s = 1;
                elseif M_button(i,j) == 2 
                    s = 2;
                elseif M_button(i,j) == 3
                    s = 3;
                else
                    s = 4;
                end
                plot(x(i,j),y(i,j),sprintf('%s %s',S(s),color(j)));
            end
            axes(ha(2));cla
            plot(x(1:i,:),repmat([1:i]',[1,size(y,2)]))
            set(ha(2),'Ylim',[0 N],'YDir','reverse');
    
            axes(ha(3));cla
            plot(repmat([1:i]',[1,size(y,2)]),y(1:i,:))
            set(ha(3),'Xlim',[0 N],'YDir','reverse');
    
            axes(ha(4));cla
            plot(x(1:i,:),y(1:i,:))
            set(ha(4),'YDir','reverse','YTick',[])
        end
    else
        choice = menu('Choose an option:','Annotate current frame','Scroll through frames');

        switch choice
    
        case 1
            button = ones(Npts,1);
        case 2
            button = 114*ones(Npts,1);
        end
    end
end

% Launch the replay of the annotation
replay_annotation(movie,x,y)

Contact us