Form Index Image Processing
1 view (last 30 days)
Show older comments
Hello Guys,
I am struggling to get the Form Index from a bw image. The form index (FI) isdescribed as the sum of the changes in radius: and it is represented by the attached model. where R is the radius of the particle in different directions, and θ is the directional angle. In Equation 1, the form index of a circle is zero, because there are no changes in radii. I would apreciate if there is someone that can help me with it

0 Comments
Accepted Answer
Image Analyst
on 22 Nov 2022
Try this:
% Demo by Image Analyst
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 = 22;
markerSize = 40;
%--------------------------------------------------------------------------------------------------------
% READ IN IMAGE
folder = [];
baseFileName = 'eight.tif';
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
grayImage = imread(fullFileName);
% 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)
%--------------------------------------------------------------------------------------------------------
% Display the image.
subplot(2, 2, 1);
imshow(grayImage);
impixelinfo;
axis('on', 'image');
title('Original Gray Scale Image', 'FontSize', fontSize, 'Interpreter', 'None');
if numberOfColorChannels > 1
% It's not really gray scale like we expected - it's color.
fprintf('It is not really gray scale like we expected - it is color\n');
% Extract the blue channel.
grayImage = grayImage(:, :, 3);
end
% Update 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)
% Maximize window.
g = gcf;
g.WindowState = 'maximized';
drawnow;
%--------------------------------------------------------------------------------------------------------
% Show the histogram
subplot(2, 2, 2);
imhist(grayImage);
title('Histogram of Original Image', 'FontSize', fontSize, 'Interpreter', 'None');
grid on;
%--------------------------------------------------------------------------------------------------------
% Interactively and visually set a threshold on a gray scale image.
% https://www.mathworks.com/matlabcentral/fileexchange/29372-thresholding-an-image?s_tid=srchtitle
lowThreshold = 0;
highThreshold = 200;
% [lowThreshold, highThreshold] = threshold(lowThreshold, highThreshold, grayImage)
%--------------------------------------------------------------------------------------------------------
% Create a mask
mask = grayImage >= lowThreshold & grayImage <= highThreshold;
% Fill blobs
mask = imfill(mask,"holes");
% Take blobs only 1000 pixels or larger in area
mask = bwareaopen(mask, 1000);
subplot(2, 2, 3);
imshow(mask, []);
impixelinfo;
axis('on', 'image');
title('Mask', 'FontSize', fontSize, 'Interpreter', 'None');
%--------------------------------------------------------------------------------------------------------
% Measure blob sizes
props = regionprops(mask, 'Area', 'Centroid');
allAreas = [sort([props.Area], 'descend')]
subplot(2, 2, 4);
histogram(allAreas);
title('Histogram of blob areas', 'FontSize', fontSize, 'Interpreter', 'None');
grid on;
% Plot the borders of all the blobs in the overlay above the original grayscale image
% using the coordinates returned by bwboundaries().
% bwboundaries() returns a cell array, where each cell contains the row/column coordinates for an object in the image.
imshow(grayImage); % Optional : show the original image again. Or you can leave the binary image showing if you want.
% Here is where we actually get the boundaries for each blob.
boundaries = bwboundaries(mask);
% boundaries is a cell array - one cell for each blob.
% In each cell is an N-by-2 list of coordinates in a (row, column) format. Note: NOT (x,y).
% Column 1 is rows, or y. Column 2 is columns, or x.
numberOfBoundaries = size(boundaries, 1); % Count the boundaries so we can use it in our for loop
% Here is where we actually plot the boundaries of each blob in the overlay.
hold on; % Don't let boundaries blow away the displayed image.
for k = 1 : numberOfBoundaries
thisBoundary = boundaries{k}; % Get boundary for this specific blob.
x = thisBoundary(:,2); % Column 2 is the columns, which is x.
y = thisBoundary(:,1); % Column 1 is the rows, which is y.
plot(x, y, 'r-', 'LineWidth', 2); % Plot boundary in red.
% Compute the Form Index
xCenter = props(k).Centroid(1);
yCenter = props(k).Centroid(2);
% Get all the radii as we move around the boundary.
radii = sqrt((x - xCenter).^2 + (y - yCenter).^2);
% Get the sum of differences to get the Form Index
FI(k) = sum(abs(diff(radii)));
end
FI % Show in command window.
hold off;
caption = sprintf('%d Outlines, from bwboundaries()', numberOfBoundaries);
fontSize = 15;
title(caption, 'FontSize', fontSize);
axis('on', 'image'); % Make sure image is not artificially stretched because of screen's aspect ratio.
4 Comments
Image Analyst
on 22 Nov 2022
Look, here is one with irregularly shaped blobs, some smooth and convex and some not. I compute the FI both taking abs and without taking abs.
% Demo by Image Analyst
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 = 22;
markerSize = 40;
%--------------------------------------------------------------------------------------------------------
% READ IN IMAGE
folder = [];
baseFileName = 'toyobjects.png';
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
grayImage = imread(fullFileName);
% 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)
%--------------------------------------------------------------------------------------------------------
% Display the image.
subplot(2, 2, 1);
imshow(grayImage);
impixelinfo;
axis('on', 'image');
title('Original Gray Scale Image', 'FontSize', fontSize, 'Interpreter', 'None');
if numberOfColorChannels > 1
% It's not really gray scale like we expected - it's color.
fprintf('It is not really gray scale like we expected - it is color\n');
% Extract the blue channel.
grayImage = grayImage(:, :, 3);
end
% Update 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)
% Maximize window.
g = gcf;
g.WindowState = 'maximized';
drawnow;
%--------------------------------------------------------------------------------------------------------
% Show the histogram
subplot(2, 2, 2);
imhist(grayImage);
title('Histogram of Original Image', 'FontSize', fontSize, 'Interpreter', 'None');
grid on;
%--------------------------------------------------------------------------------------------------------
% Interactively and visually set a threshold on a gray scale image.
% https://www.mathworks.com/matlabcentral/fileexchange/29372-thresholding-an-image?s_tid=srchtitle
lowThreshold = 0;
highThreshold = 200;
% [lowThreshold, highThreshold] = threshold(lowThreshold, highThreshold, grayImage)
%--------------------------------------------------------------------------------------------------------
% Create a mask
% mask = grayImage >= lowThreshold & grayImage <= highThreshold;
mask = grayImage ~= 127;
% Fill blobs
mask = imfill(mask,"holes");
% Take blobs only 1000 pixels or larger in area
mask = bwareaopen(mask, 1000);
subplot(2, 2, 3);
imshow(mask, []);
impixelinfo;
axis('on', 'image');
title('Mask', 'FontSize', fontSize, 'Interpreter', 'None');
%--------------------------------------------------------------------------------------------------------
% Measure blob sizes
props = regionprops(mask, 'Area', 'Centroid');
allAreas = [sort([props.Area], 'descend')]
subplot(2, 2, 4);
histogram(allAreas);
title('Histogram of blob areas', 'FontSize', fontSize, 'Interpreter', 'None');
grid on;
% Plot the borders of all the blobs in the overlay above the original grayscale image
% using the coordinates returned by bwboundaries().
% bwboundaries() returns a cell array, where each cell contains the row/column coordinates for an object in the image.
imshow(grayImage); % Optional : show the original image again. Or you can leave the binary image showing if you want.
% Here is where we actually get the boundaries for each blob.
boundaries = bwboundaries(mask);
% boundaries is a cell array - one cell for each blob.
% In each cell is an N-by-2 list of coordinates in a (row, column) format. Note: NOT (x,y).
% Column 1 is rows, or y. Column 2 is columns, or x.
numberOfBoundaries = size(boundaries, 1); % Count the boundaries so we can use it in our for loop
% Here is where we actually plot the boundaries of each blob in the overlay.
hold on; % Don't let boundaries blow away the displayed image.
for k = 1 : numberOfBoundaries
thisBoundary = boundaries{k}; % Get boundary for this specific blob.
x = thisBoundary(:,2); % Column 2 is the columns, which is x.
y = thisBoundary(:,1); % Column 1 is the rows, which is y.
plot(x, y, 'r-', 'LineWidth', 2); % Plot boundary in red.
% Compute the Form Index
xCenter = props(k).Centroid(1);
yCenter = props(k).Centroid(2);
% Get all the radii as we move around the boundary.
radii = sqrt((x - xCenter).^2 + (y - yCenter).^2);
% Get the sum of differences to get the Form Index
FI(k) = sum(diff(radii));
FIabs(k) = sum(abs(diff(radii)));
end
FI % Show in command window.
FIabs
hold off;
caption = sprintf('%d Outlines, from bwboundaries()', numberOfBoundaries);
fontSize = 15;
title(caption, 'FontSize', fontSize);
axis('on', 'image'); % Make sure image is not artificially stretched because of screen's aspect ratio.

You see the FI without taking the abs are all zero as expected:
FI =
0 0 0 0
FIabs =
149.325027041666 218.54116484628 245.790271754549 84.1212568797374
More Answers (0)
See Also
Categories
Find more on Lighting, Transparency, and Shading in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!