Code covered by the BSD License  

Highlights from
Cell Segmentation and Tracking

image thumbnail

Cell Segmentation and Tracking

by

 

16 Dec 2011 (Updated )

This program opens a GUI, segments and tracks cells from videos using the parallelization toolbox.

correction.m
function [new_tracks, jump] = correction(tracks, len)
% ------------------------------------------------------------------------
% CORRECTION executes a first step of post processing removing false
% postives and adding false negatives using cell number computing.
% For example if cell number is 4 4 4 5 5 4 3 4, this function changes it
% into 4 4 4 4 4 4 4 4
%
%[finaltracks, jump] = correction(tracks, length(VIDEO));
%
%   Input: -tracks: matrix of track in CellTracking function after jump analysis.
%          -len= length(video)
%
%   Output: -new_tracks: matrix of track modified after false postive removal or false negative adding
%           - jump: array containing the information if a cell jumped
%           modified by the function.
%
% V. 1.0 - F. Plissier, LSCB, EPFL, December 2011
% lscb.epfl.com
% ------------------------------------------------------------------------
%%
tracks2 = tracks;
jump = zeros(len,1);
cell_number = zeros(len,1);
index =[];
ind =[];

% We have to remove cells which are outside the well. 
for i = 1 : size(tracks,1)
    index = tracks(i,3); %Time frame
     if tracks(i, end) ~= 0 %Check if a cell jumped
    jump(index) =tracks(i, end) ;
     end
end

for i = 1 : size(tracks,1)
     index = tracks(i,3); %Time frame
    if tracks(i, end-1) == 0  %Check for cells outside the well
        ind = [ind, i]; %Store the index
    end
end
tracks2(ind,:) =[]; %Remove cells outside

for i = 1 : size(tracks2,1)
    index = tracks2(i,3); %Time frame
    if tracks2(i, end-1) ~= 0
    cell_number(index) = cell_number(index)+1; %Count the number of cells inside a well
    end
end

%%
ind=[];
flag=1;
cell_num = cell_number;
while(flag)
    flag=0;
for i=7: length(cell_number)
    
    %Create a window of 7 index: the 2x2 ends should correct the 3 middle
    %ones
    if cell_num(i) == cell_num(i-1) && cell_num(i) == cell_num(i-5)...
            && cell_num(i) == cell_num(i-6) && isempty(find(jump(i-4:i)~=0,1))
    
        if cell_num(i) ~= cell_num(i-2) 
        cell_num(i-2) = cell_num(i);
        ind = [ind,i-2];
        flag =1;
        end
        if cell_num(i) ~= cell_num(i-3) 
        cell_num(i-3) = cell_num(i);
        ind = [ind,i-3];
        flag=1;
        end
        
        if cell_num(i) ~= cell_num(i-4) 
        cell_num(i-4) = cell_num(i);
         ind = [ind,i-4];
         flag=1;
        end
    end

end
end
%ind contains the index where there are false positives or false negatives
ind = sort(ind);
%%
j=0;
Neighbor=cell(size(ind,2),1);
l=0;
PosNeigh=cell(size(ind,2),1);
coor=cell(size(ind,2),1);% False positive
coor2=cell(size(ind,2),2); %False negative
FN=0;

for i = 1 : size(tracks2,1)
    index = tracks2(i,3); %Time point
    if ~isempty(find(ind == index,1)) %ind contains the indexes were the cell number has been changed
         j=(find(ind == index,1));
        if cell_num(ind(j)) < cell_number(ind(j)) %If the cell number decreased, we have to remove the false positives
        %Look at the coordinates to decide which one we should remove
        % FP contains the false positive number for the index j
        FP(j) = cell_number(ind(j))- cell_num(ind(j));
        % coor contains the coordinates of all the cells at this time
        % frame
        coor{j} = [coor{j}; tracks2(i,1), tracks2(i,2)];
        end
        
        if cell_num(ind(j)) > cell_number(ind(j)) %False negative
            % FN contains the false negative number for the index j
            FN(j) = cell_num(ind(j)) - cell_number(ind(j));
            %coor2 contains the coordinates of all the cells at this frame
            coor2{j,1} =[tracks2(find(tracks2(:,3)==index),1), tracks2(find(tracks2(:,3)==index),2)];
            indexmin = index-2; %Look before and after to compare the positions
            indexmax = index+2;
            if indexmin <0
                indexmin=index;
            end
            
            if indexmax > size(cell_number,1)
                indexmax=index;
            end
            % Look at the 5 time points around the current time point to give one of their
            % coordinates to the false negative.
            % We look at the neighbor frame which has the right number of
            % cells
             l=find(cell_number(index) == cell_number(indexmin:indexmax)-FN(j));
             if ~isempty(l)
                  Neighbor{j}= l(find(l == 3 + min(abs(l-3)),1))-3;
                 if isempty(Neighbor{j})
                 Neighbor{j} = l( find(l == 3 - min(abs(l-3)),1) )-3; %-2 Second left neighbor, -1 left neighbor, 1 right neighbor, 2 second neighbor
                 end
             end
        if ~isempty(Neighbor{j})
            PosNeigh{j}=find(tracks2(:,3) ==index+Neighbor{j});
        %Look at the coordinates to decide which one we should add
        % Stock the coordinates of the cells in the reference time point
        coor2{j,2} = [ tracks2(PosNeigh{j},1), tracks2(PosNeigh{j},2)];
        end
        end
    end
end

%%
%False negatives

tracks3 = tracks2;

for i=1:size(coor2,1)
    newdist=[];
    index2 = [];
    mini=[];
    if ~isempty(coor2{i})
        for j=1:size(coor2{i,1},1)
            x0 = coor2{i,1}(j,1); %Positions of the cells
            y0 = coor2{i,1}(j,2);
            for k=1:size(coor2{i,2},1)
                
                x = coor2{i,2}(k,1); %Positions of the reference cells
                y = coor2{i,2}(k,2);
                %Compute the distance
                newdist(j,k) = sqrt((x-x0)^2 + (y-y0)^2);
            end
        end
        %We compute the minimum of each column of this matrix, so a cell
        %will match some reference cells (itself and the false negative(s))
        s=[j, k];
        [tf, index]=ismember(min(newdist), newdist);
        [I, J]=ind2sub(s,index);
        
        for j=1:length(J)
            if size(find(j==I),2) >1 %Look at the position which has many matches matches
                GoodPos = find(j==I); %Contains the positions of the false negatives
                %Look at the areas to match which on is which one
                Areas = tracks2(PosNeigh{i}(find(j==I)),4);
                %Look at the current position in the track
                Currentpos = find(tracks3(:,3)==ind(i));
                %AreaFN contains the areas of the false negatives
                AreaFN = tracks3(Currentpos(j),4) ;
                %Find wich cell was not a false negative
                Goodarea = find(min(abs(Areas-AreaFN))== abs(Areas-AreaFN));
                %index2 contains the index of the false negatives
                index2 = GoodPos(find(Areas(Goodarea) ~= Areas));
                
                %We add the lines in track corresponding to the reference
                %cells which complete the false negatives
                toadd = PosNeigh{i}(index2); %Reference position found
                pos = find(tracks3(:,3)==ind(i),1,'last'); %Last position of the time frame which contains the false negative
                tracks3 = [tracks3(1:pos,:); tracks2(toadd,:); tracks3(pos+1:end,:)]; %Reassembly
                tracks3(pos+1:pos+length(index2),3) = ind(i);
            end
        end
        
    end
end
%%
%% False positive
index = [];
miniFinal =[];
tracks4 = tracks3;
index2=[];

for i=1:size(coor,1)
    newdist=[];
    if ~isempty(coor{i})
        for fn=1:FP(i)
            
            for j=1:size(coor{i},1)
                x0 = coor{i}(j,1); %Position of cells
                y0 = coor{i}(j,2);
                for k=1:size(coor{i},1)
                    newdist(j,k) =100000;
                    if k~=j
                        x = coor{i}(k,1);%Position of cells in the same frame
                        y = coor{i}(k,2);
                        newdist(j,k) = sqrt((x-x0)^2 + (y-y0)^2);
                        %Look at the minimum distance between objects
                        
                    end
                end
            end
            %Usually, false positives are part of cells, so we look at the
            %minimum distance between cells
            index= find(min(min(newdist)) == min(newdist));
            m=[]; %#ok<*NASGU>
            l=[];
            m=find(tracks4(:,3) ==ind(i));
            if ~isempty(index)
                l= find(tracks4(m,4) == min(tracks4(m(index),4)),1); %Look at the smallest area
                
                index2 =[index2; m(l)]; %#ok<*AGROW>
                % Replace the x y of the object which is not removed by the mean of the x y of the
                % 2 objects
                newx = sum(tracks4(m(index),1))/2;
                newy = sum(tracks4(m(index),2))/2;
                tracks4(m(index(find(index~=l,1))),1) = newx;
                tracks4(m(index(find(index~=l,1))),2) = newy;
                coor{i}(l,:)=[1000 1000];
            end
        end
    end
end
%Delete the object in track
tracks4(index2 ,:) = [];

for i = 1 : size(tracks4,1)
    INDEX = tracks4(i,3);
    tracks4(i,end) = jump(INDEX);
end

new_tracks = tracks4;

end

Contact us