Skip to content

Commit

Permalink
Merge pull request #33 from UniBoDS4H/feat/api/close-line-algo
Browse files Browse the repository at this point in the history
Feature/api/close-line-algo
  • Loading branch information
drudilorenzo authored May 14, 2023
2 parents cb45f7f + a85a360 commit bb8764f
Show file tree
Hide file tree
Showing 46 changed files with 613 additions and 455 deletions.
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

0 comments on commit bb8764f

Please sign in to comment.