MATLAB: Finding tortuosity of parasite

curvedistanceImage Processing Toolboxlongest spinetortuosity

Any demo to measure the tortuosity of this parasite?
tried using bwmorph to get the skeleton and then find the endpoints. But then the skeleton i can get from image above is something like the below:

Best Answer

Use bwskel() to get the longest spine. Then use bwmorph() to get the endpoints of the spine. Then use find() and sqrt() to get the straight line distance between the endpoints, then divide the two.
% This demo computes the tortuosity of a snake-like shape by dividing the actual longest spine distance by the straight line distance between the endpoints.
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 15;
%--------------------------------------------------------------------------------------------------------

% READ IN IMAGE
folder = pwd;
baseFileName = 'worm.png';
% Get the full filename, with path prepended.
fullFileName = fullfile(folder, baseFileName);
% Check if file exists.
if ~exist(fullFileName, 'file')
% The file doesn't exist -- didn't find it there in that folder.
% Check the entire search path (other folders) for the file by stripping off the folder.
fullFileNameOnSearchPath = baseFileName; % No path this time.
if ~exist(fullFileNameOnSearchPath, 'file')
% Still didn't find it. Alert user.
errorMessage = sprintf('Error: %s does not exist in the search path folders.', fullFileName);
uiwait(warndlg(errorMessage));
return;
end
end
% Read in the image from disk. If storedColorMap is not empty, it's an indexed image with a stored colormap.
[grayImage, storedColorMap] = imread(fullFileName);
if ~isempty(storedColorMap)
grayImage = ind2rgb(grayImage, storedColorMap);
end
% Get the dimensions of the image.
% numberOfColorChannels should be = 1 for a gray scale image, and 3 for an RGB color image.
[rows, columns, numberOfColorChannels] = size(grayImage);
if numberOfColorChannels > 1
% It's not really gray scale like we expected - it's color.
% Use weighted sum of ALL channels to create a gray scale image.
grayImage = rgb2gray(grayImage);
% ALTERNATE METHOD: Convert it to gray scale by taking only the green channel,
% which in a typical snapshot will be the least noisy channel.
% grayImage = grayImage(:, :, 2); % Take green channel.
end
% Display the image.
hFig = figure;
subplot(1, 2, 1);
imshow(grayImage, []);
title('Original Grayscale Image', 'FontSize', fontSize, 'Interpreter', 'None');
impixelinfo;
hFig.WindowState = 'maximized'; % May not work in earlier versions of MATLAB.
drawnow;
%--------------------------------------------------------------------------------------------------------
% SEGMENTATION
% Binarize the image
binaryImage = imbinarize(grayImage);
% Take the largest blob only.
binaryImage = bwareafilt(binaryImage, 1);
% Fill holes, if any.
binaryImage = imfill(binaryImage, 'holes');
% Display the binary image.
subplot(1, 2, 1);
imshow(binaryImage, []);
title('Binary Image', 'FontSize', fontSize, 'Interpreter', 'None');
axis('on', 'image');
% Now skeletonize
skelImage = bwskel(binaryImage); % First guess. Will have short spurs.
% First get the area of the skeleton and take half of it to be the longest spine length.
% This will get rid of all spurs.
MinBranchLength = round(sum(skelImage(:))/2)
% Now take the skeleton again using that min branch length we just computed.
skelImage = bwskel(binaryImage, 'MinBranchLength', MinBranchLength);
% Display the skeleton image.
subplot(1, 2, 2);
imshow(skelImage, []);
title('Skeleton Image', 'FontSize', fontSize, 'Interpreter', 'None');
axis('on', 'image');
% Find the endpoints
endpointImage = bwmorph(skelImage, 'endpoints');
[rows, columns] = find(endpointImage)
% Draw a red line between them.
hold on;
plot(columns, rows, 'r-', 'LineWidth', 2);
% Find the spine length.
% (Would be more accurate to find the spine length by traversing it.)
spineLength = sum(skelImage(:))
% Compute the straight line distance.
straightLineDistance = sqrt((columns(2) - columns(1))^2 + (rows(2) - rows(1))^2)
% Compute the tortuosity
tortuosity = spineLength / straightLineDistance
caption = sprintf('Skeleton Image. Tortuosity = %f', tortuosity);
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');