Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/api/close-line-algo #33

Merged
merged 15 commits into from
May 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 1 addition & 18 deletions api/algorithms/algorithm_AverageSmallestAndLargest.m
Original file line number Diff line number Diff line change
Expand Up @@ -18,33 +18,16 @@
% averageSeg (matrix [height, width]):
% The average segmentation.
%
% THROWS:
% TDSFT:algorithms:
% if the input is empty.
%
% DESCRIPTION:
% Get the average segmentation between the smallest and the largest.
% Can be passed as input the smallest and the largest segmentation or an array of
% segmentations from which the smallest and the largest are obtained.
% The average segmentation is obtained by taking the 1-pixel line in the middle of
% the area between the two segmentations.
function averageSeg = algorithm_AverageSmallestAndLargest(varargin)
disp('Getting the average segmentation between the smallest and the largest...');

if nargin == 1
segmentations = varargin{1};

% Check if the input is empty, if it is the case throw an exception
if isempty(segmentations)
throw(MException('TDSFT:algorithms', 'Segmentations array empty'));
end

% If there is only one segmentation, return it
if length(segmentations) == 1
averageSeg = segmentations{1};
return;
end

try
smallest = algorithm_Smallest(segmentations);
largest = algorithm_Largest(segmentations);
Expand All @@ -58,7 +41,7 @@
throw(MException('TDSFT:algorithms', 'Wrong number of parameters'));
end

% Overlap the two smallest and the largest segmentations
% Overlap the smallest and the largest segmentations
averageSeg = smallest + largest;

% Fill the holes and get the area between the two segmentations
Expand Down
19 changes: 5 additions & 14 deletions api/algorithms/algorithm_AverageTargetFromInput.m
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
% PARAMETERS:
% segmentations (Cell array: [1, raters], Cells: matrix [height, width]):
% array containing the segmentations to fuse.
% startSegmentation (int):
% target (int):
% the index of the segmentation to be used as main segmentation.
%
% OUTPUT:
Expand All @@ -14,8 +14,6 @@
%
% THROWS:
% TDSFT:algorithms:
% the segmentations array is empty.
% TDSFT:algorithms:
% the start segmentation index is greater than the number of segmentations.
%
% DESCRIPTION:
Expand All @@ -24,20 +22,13 @@
% with value 1 in the other segmentations. Then it is computed the average pixel:
% - if the segmentations are 2, the average pixel is the middle point between the two pixels;
% - if the segmentations are more than 2, the average pixel is the centroid of the pixels.
function averageSeg = algorithm_AverageTargetFromInput(segmentations, startSegmentation)
s = strcat("Getting average segmentation targetting the segmentation ", num2str(startSegmentation{1}), "...");
disp(s);

% Check if the input is empty, if it is the case throw an exception
if isempty(segmentations)
throw(MException('TDSFT:algorithms', 'Segmentations array empty'));
end

function averageSeg = algorithm_AverageTargetFromInput(segmentations, target)
try
if startSegmentation{1} > length(segmentations) || startSegmentation{1} < 1
% Check if the target segmentation is in the range.
if target > length(segmentations) || target < 1
throw(MException('TDSFT:algorithms', 'Wrong start segmentation index'));
end
averageSeg = getAverageSegmentation(segmentations, startSegmentation{1});
averageSeg = getAverageSegmentation(segmentations, target);
catch ME
rethrow(ME);
end
Expand Down
9 changes: 1 addition & 8 deletions api/algorithms/algorithm_AverageTargetLargest.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
%
% OUTPUT:
% averageSeg (matrix [height, width]):
% The average segmentation.
% the average segmentation.
%
% DESCRIPTION:
% The average segmentation is computed by averaging the segmentations as follows:
Expand All @@ -17,13 +17,6 @@
% - if the segmentations are 2, the average pixel is the middle point between the two pixels;
% - if the segmentations are more than 2, the average pixel is the centroid of the pixels.
function averageSeg = algorithm_AverageTargetLargest(segmentations)
disp('Getting average segmentation targetting the largest...');

% Check if the input is empty, if it is the case throw an exception
if isempty(segmentations)
throw(MException('TDSFT:algorithms', 'Segmentations array empty'));
end

try
largest = algorithm_Largest(segmentations);
averageSeg = getAverageSegmentation(segmentations, largest);
Expand Down
11 changes: 2 additions & 9 deletions api/algorithms/algorithm_AverageTargetSmallest.m
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,9 @@
% - if the segmentations are 2, the average pixel is the middle point between the two pixels;
% - if the segmentations are more than 2, the average pixel is the centroid of the pixels.
function averageSeg = algorithm_AverageTargetSmallest(segmentations)
disp('Getting average segmentation targetting the smallest......');

% Check if the input is empty, if it is the case throw an exception
if isempty(segmentations)
throw(MException('TDSFT:algorithms', 'Segmentations array empty'));
end

try
largest = algorithm_Smallest(segmentations);
averageSeg = getAverageSegmentation(segmentations, largest);
smallest = algorithm_Smallest(segmentations);
averageSeg = getAverageSegmentation(segmentations, smallest);
catch ME
rethrow(ME);
end
Expand Down
40 changes: 8 additions & 32 deletions api/algorithms/algorithm_Largest.m
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,10 @@
% NAME: TDSFT (version 1.0)
%
% PARAMETERS:
% The function accepts two different input parameters:
% 1) segmentations (Cell array: [1, raters], Cells: matrix [height, width]):
% array containing the segmentations to fuse.
%
% 2) segmentations (Matrix [height, width]):
% the segmentations are already overlapped in a matrix.
% (The algorithm need NO dense segmentations, so to overlap the segmentations no fill holes is needed).
%
% THROWS:
% TDSFT:algorithms:
% throwed if the input is empty.
% segmentations (Cell array: [1, raters], Cells: matrix [height, width] || Matrix [height, width]):
% - array: array containing the segmentations to fuse;
% - matrix: the segmentations are already overlapped in a matrix.
% (The algorithm need NO dense segmentations, so to overlap the segmentations no fill holes is needed)
%
% OUTPUT:
% largestSegmentation (Matrix [height, width]):
Expand All @@ -22,30 +15,13 @@
% DESCRIPTION:
% Fuse all the segmentations together overlapping them and getting the largest possible segmentation.
% The largest segmentation is the smallest segmentation possible which contains each input segmentation.
% To obtain it the segmentations are overlapped and then is returned the perimeter of the area covered by them.
% To obtain it the segmentations are overlapped and then is returned the perimeter of the total area covered by them.
function largestSegmentation = algorithm_Largest(segmentations)
disp('Getting the largest...');

if iscell(segmentations)

% Check if the input is empty
if isempty(segmentations)
throw(MException('TDSFT:algorithms', 'Segmentations array empty'));
end

% If there is only one segmentation, return it
if length(segmentations) == 1
largestSegmentation = segmentations{1};
return;
end

try
overlap = overlapSegmentations(segmentations);
catch ME
rethrow(ME);
end
overlap = overlapSegmentations(segmentations);
else
overlap = segmentations;
end
largestSegmentation = getLargestSegmentation(overlap);

[~, largestSegmentation] = getLargestArea(overlap);
end
65 changes: 19 additions & 46 deletions api/algorithms/algorithm_Middle.m
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@
%
% THROWS:
% TDSFT:algorithms:
% throwed if the input is empty.
% TDSFT:algorithms:
% throwed if the number of segmentations is even and the algorithm is not specified.
% TDSFT:algorithms:
% throwed if the algorithm choosed if the number of segmentations is even is not available.
Expand All @@ -29,81 +27,56 @@
% Discard outliers until the middle segmentation is reached. To do that iterate over the segmentations and
% discard the largest and the smallest segmentation at each iteration.
% If the number of segmentations is even specify a method for the last two segmentations left.
% The available methods are:
% - 'LargestSegmentation': use the largest segmentation.
% - 'SmallestSegmentation': use the smallest segmentation.
% - 'AverageSmallestAndLargest': use the average between the smallest and the largest segmentation.
function middleSegmentation = algorithm_Middle(segmentations, algorithm)
disp('Getting the middle...');

% check if the input is empty
if isempty(segmentations)
throw(MException('TDSFT:algorithms', 'Segmentations array empty'));
end

% check if the number of segmentations is even and the algorithm is specified
% Check if the number of segmentations is even and the algorithm is specified
if mod(length(segmentations), 2) == 0 && nargin < 2
throw(MException('TDSFT:algorithms', 'If the number of segmentations is even, the algorithm must be specified'));
end

% if there is only one segmentation, return it
if length(segmentations) == 1
middleSegmentation = segmentations{1};
return;
end

try
overlap = overlapSegmentations(segmentations);
catch ME
rethrow(ME);
end
overlap = overlapSegmentations(segmentations);

nSeg = length(segmentations); % number of segmentations
totIt = floor( (nSeg - 1) / 2 ); % total number of iterations

% preallocate the filled segmentations array
filledSegmentations = cell(1, length(segmentations));

% Get the filled segmentations needed to get the smallest segmentation
for i=1:length(segmentations)
filledSegmentations{i} = imfill(segmentations{i}, 'holes');
end

try
overlapFilled = overlapSegmentations(filledSegmentations);
catch ME
rethrow(ME);
end
% Fill segmentations and overlap.
filledSegmentations = getFilledSegmentations(segmentations);
overlapFilled = overlapSegmentations(filledSegmentations);

% At each iteration discard the largest and the smallest segmentation
for i=1:totIt
largest = uint8( getLargestSegmentation(overlap) );
smallest = uint8( getSmallestSegmentation(overlapFilled, nSeg) );
largest = uint8( algorithm_Largest(overlap) );
smallest = uint8( algorithm_Smallest(overlapFilled, nSeg) );

overlap = overlap - largest;
overlap = overlap - smallest;

filledLargest = imfill(largest, 'holes');
filledSmallest = imfill(smallest, 'holes');
filledLargest = imfill(largest, "holes");
filledSmallest = imfill(smallest, "holes");
overlapFilled = overlapFilled - filledLargest;
overlapFilled = overlapFilled - filledSmallest;

nSeg = nSeg - 2;
end

% compute result
% If the number of segmentations is even, use the specified algorithm for the last two segmentations left.
if isequal(nSeg, 2)
% if the number of segmentations is even, use the specified algorithm for the last two segmentations left
algorithm = fromSpacedToFullName(algorithm);
algorithm = fromSpacedToFullNameAlgorithm(algorithm);
if strcmp(algorithm, 'algorithm_Largest')
middleSegmentation = getLargestSegmentation(overlap);
middleSegmentation = algorithm_Largest(overlap);
elseif strcmp(algorithm, 'algorithm_Smallest')
middleSegmentation = getSmallestSegmentation(overlapFilled, nSeg);
middleSegmentation = algorithm_Smallest(overlapFilled, nSeg);
elseif strcmp(algorithm, 'algorithm_AverageSmallestAndLargest')
smallest = getSmallestSegmentation(overlapFilled, nSeg);
largest = getLargestSegmentation(overlap);
smallest = algorithm_Smallest(overlapFilled, nSeg);
largest = algorithm_Largest(overlap);
middleSegmentation = algorithm_AverageSmallestAndLargest(smallest, largest);
else
throw(MException('TDSFT:algorithms', 'Algorithm not available'));
end
else
% if the number of segmentations is odd, return the segmentation left
middleSegmentation = imbinarize(overlap);
end

Expand Down
34 changes: 7 additions & 27 deletions api/algorithms/algorithm_STAPLE.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@
% gtSegmentation (Matrix [height, width]):
% the ground truth segmentation computed with STAPLE algorithm.
%
% THROWS:
% staple:emptyInput (Exception):
% throwed if the input is empty.
%
% DESCRIPTION:
% Use STAPLE algorithm to get the ground truth segmentation.
%
Expand All @@ -23,37 +19,21 @@
% an algorithm for the validation of image segmentation."
% Medical Imaging, IEEE Transactions on 23.7 (2004): 903-921.
function gtSegmentation = algorithm_STAPLE(segmentations)
disp('Executing STAPLE...');

% check if the input is empty
if isempty(segmentations)
throw(MException('TDSFT:algorithms', 'Segmentations array empty'));
end

% if there is only one segmentation, return it
if length(segmentations) == 1
gtSegmentation = segmentations{1};
return;
end
% Convert to the right format for STAPLE.
% (See STAPLE file for more details)

% convert to the right format for STAPLE
% See STAPLE file for more details

% get segmentations dimensions
[height, width] = size(segmentations{1});
% Get segmentations dimensions.
imageDims = size(segmentations{1});
nSeg = length(segmentations);

% preallocate the array
stapleParam = zeros(height*width, nSeg);
% Preallocate the array.
stapleParam = zeros(imageDims(1) * imageDims(2), nSeg);
for i=1:length(segmentations)
seg = segmentations{i};
stapleParam(:, i) = seg(:);
end
[W, ~, ~] = STAPLE(stapleParam);

% get segmentations dimensions
imageDims = size(segmentations{1});

% reshape to get the ground truth segmentation
% Reshape to get the ground truth segmentation.
gtSegmentation = reshape((W >= .5), imageDims);
end
Loading