Finding the minimum distance between two objects, for multiple images.

I am attaching an input as well as an output image(distance between two bones) for your review, I am also attaching the code that helped me find the distance between the bones.
I have a folder for 200 individuals, each individual having approximately 150 such bones samples.
I want to apply this algorithm for every individual having 150 bone samples(each varying in sizes and distances).
For every individual, I want to find the average minimum distance by taking an average of these 150 bone samples and store the result in a vector. I want to do the same for all 200 individuals.
  • How can I iterate through these images (200*150 images) and load them to apply this algorithm on each one of them.
  • How can I find the average distance that I obtain after finding the distance from 150 bone samples and store the result in a vector and do the same for 200 individuals?
Please help me understand this.
Thank you.
%===============================================================================
% Read in a standard MATLAB color demo image.
folder = 'D:\MathWorks_MATLAB_R2020a_v9.8.0.1323502\MathWorks_MATLAB_R2020a_v9.8.0.1323502'; %'C:\Users\Lakshya\Documents\Temporary';
baseFileName = '9002116_060_pred.png';
% Get the full filename, with path prepended.
fullFileName = fullfile(folder, baseFileName);
if ~exist(fullFileName, 'file')
% Didn't find it there. Check the search path for it.
fullFileName = baseFileName; % No path this time.
if ~exist(fullFileName, 'file')
% Still didn't find it. Alert user.
errorMessage = sprintf('Error: %s does not exist.', fullFileName);
uiwait(warndlg(errorMessage));
return;
end
end
grayImage = imread(fullFileName);
% Get the dimensions of the image. numberOfColorBands should be = 3.
[rows, columns, numberOfColorBands] = size(grayImage);
% Display the original image.
subplot(2, 2, 1);
imshow(grayImage);
axis on;
title('Original Gray Scale Image');
% Enlarge figure to full screen.
set(gcf, 'units','normalized','outerposition',[0 0 1 1]);
% Binarize the image
binaryImage = imbinarize(grayImage);
% Display the image.
subplot(2, 2, 2);
imshow(binaryImage);
title('Binary Image');
% Fill the outline to make it solid so we don't get boundaries
% on both the inside of the shape and the outside of the shape.
binaryImage = imfill(binaryImage, 'holes');
% Display the image.
subplot(2, 2, 3);
imshow(binaryImage);
% bwboundaries() returns a cell array, where each cell contains the row/column coordinates for an object in the image.
% Plot the borders of all the coins on the original grayscale image using the coordinates returned by bwboundaries.
hold on;
boundaries = bwboundaries(binaryImage);
numberOfBoundaries = size(boundaries, 1);
for k = 1 : numberOfBoundaries
thisBoundary = boundaries{k};
plot(thisBoundary(:,2), thisBoundary(:,1), 'r', 'LineWidth', 3);
end
title('Filled Binary Image with Boundaries');
hold off;
% Define object boundaries
numberOfBoundaries = size(boundaries, 1)
boundary1 = boundaries{1};
boundary2 = boundaries{2};
boundary1x = boundary1(:, 2);
boundary1y = boundary1(:, 1);
x1=1;
y1=1;
x2=1;
y2=1;
overallMinDistance = inf; % Initialize.
index1 = 1;
index2 = 1;
for k = 1 : length(boundary2)
boundary2x = boundary2(k, 2);
boundary2y = boundary2(k, 1);
% For this blob, compute distances from boundaries to edge.
allDistances = sqrt((boundary1x - boundary2x).^2 + (boundary1y - boundary2y).^2);
% Find closest point, min distance.
[minDistance(k), indexOfMin] = min(allDistances);
if minDistance(k) < overallMinDistance
overallMinDistance = minDistance(k);
x1 = boundary1x(indexOfMin);
y1 = boundary1y(indexOfMin);
x2 = boundary2x;
y2 = boundary2y;
index2 = k;
index1 = indexOfMin;
end
end
% Report to command window.
fprintf('Min Distance from sqrt() method = %f at index %d of boundary 1 and index %d of boundary 2.\n', ...
overallMinDistance, index1, index2);
hFig = figure;
h1 = subplot(1, 2, 1);
imshow(binaryImage);
axis on;
title('Closest Distance from sqrt()');
h2 = subplot(1, 2, 2);
imshow(binaryImage);
axis on;
title('Closest Distances from pdist2()');
hFig.WindowState = 'maximized';
hold on;
% Draw a line between point 1 and 2
line(h1, [x1, x2], [y1, y2], 'Color', 'y', 'LineWidth', 3);
%======================================================================================
% For comparison, use pdist2()
allDistances2 = pdist2(boundary1, boundary2);
minDistance2 = min(allDistances2(:));
% Find all points that have that min distance - there may be several that have it.
[r, c] = find(allDistances2 == minDistance2)
boundary1x = boundary1(:, 2);
boundary1y = boundary1(:, 1);
boundary2x = boundary2(:, 2);
boundary2y = boundary2(:, 1);
for k = 1 : length(r)
% Report to command window.
index1 = r(k);
index2 = c(k);
fprintf('Min Distance from pdist2() method = %f at index %d of boundary 1 and index %d of boundary 2.\n', ...
minDistance2, index1, index2);
xLine = [boundary1x(index1), boundary2x(index2)];
yLine = [boundary1y(index1), boundary2y(index2)];
line(h2, xLine, yLine, 'Color', 'm', 'LineWidth', 1.5);
end

5 Comments

You have a function you want to apply to a certain number of images for each case.
bones = 150; % Number of images you have for each person
people = 200; % Number of people you have
% Preallocate array for each person's minimum distance
personal_min_dist = zeros(people,1);
% Preallocate array for each bone's minimum distance
% This assumes that you have the exact same number of
% images for each person. If not, this array may need
% to change size inside the loop
bones_min_dist = zeros(bones,1)
for person = 1:people
% Get the set of images for each person
personal_bones_data = bones_data(person)
% Your actual setup here will depend on how your data is stored
for image = 1:bones
% Get minimum distance for each image using ImageAnalyst's function
bones_min_dist(image) = analysis_function(personal_bones_data(image))
end
% Get bone distance as mean of all distances for a person
personal_bone_dist(person) = mean(bones_min_dist);
end
Thank you @Clayton Gotberg This is very helpful. I am still trying to work this out. I shall get back to you here once I do.
I am trying to find out the minimum distance between two bones, and apply that minimum distance to multiple images. I tried to jot three pieces together: 1. That loads multiple images from the location of my folder, 2. A procedure that finds the minimum distance between two bones for 1 sample(image), 3. Took a sample set out of the whole dataset, and apply the minimum distance from the previous step to all the samples(images). I keep getting the error: Index exceeds the number of array elements (1). I tried to fix the code in multiple ways, but I couldn't find an appropriate solution, I dont know where am I going wrong with the code. Please help me debug this code and run it for multiple images. I am attaching the code sample and a sample dataset along with it for you to review. Thank you. @Clayton Gotberg
function test10
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
myFolder = 'D:\MathWorks_MATLAB_R2020a_v9.8.0.1323502\MathWorks_MATLAB_R2020a_v9.8.0.1323502\pq';
% Check to make sure that folder actually exists. Warn user if it doesn't.
if ~isfolder(myFolder)
errorMessage = sprintf('Error: The following folder does not exist:\n%s\nPlease specify a new folder.', myFolder);
uiwait(warndlg(errorMessage));
myFolder = uigetdir(); % Ask for a new one.
if myFolder == 0
% User clicked Cancel
return;
end
end
% Get a list of all files in the folder with the desired file name pattern.
filePattern = fullfile(myFolder, '*.png'); % Change to whatever pattern you need.
theFiles = dir(filePattern);
for k = 1 : length(theFiles)
baseFileName = theFiles(k).name;
fullFileName = fullfile(theFiles(k).folder, baseFileName);
fprintf(1, 'Now reading %s\n', fullFileName);
% Now do whatever you want with this file name,
% such as reading it in as an image array with imread()
imageArray = imread(fullFileName);
%imshow(imageArray); % Display image.
%drawnow; % Force display to update immediately.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Get the dimensions of the image. numberOfColorBands should be = 3.
[rows, columns, numberOfColorBands] = size(imageArray);
% Display the original image.
subplot(2, 2, 1);
imshow(imageArray);
axis on;
title('Original Gray Scale Image');
% Enlarge figure to full screen.
set(gcf, 'units','normalized','outerposition',[0 0 1 1]);
% Binarize the image
binaryImage = imbinarize(imageArray);
% Display the image.
subplot(2, 2, 2);
imshow(binaryImage);
title('Binary Image');
% Fill the outline to make it solid so we don't get boundaries
% on both the inside of the shape and the outside of the shape.
binaryImage = imfill(binaryImage, 'holes');
% Display the image.
subplot(2, 2, 3);
imshow(binaryImage);
% bwboundaries() returns a cell array, where each cell contains the row/column coordinates for an object in the image.
% Plot the borders of all the coins on the original grayscale image using the coordinates returned by bwboundaries.
hold on;
boundaries = bwboundaries(binaryImage);
numberOfBoundaries = size(boundaries, 1);
for k = 1 : numberOfBoundaries
thisBoundary = boundaries{k};
plot(thisBoundary(:,2), thisBoundary(:,1), 'r', 'LineWidth', 3);
end
title('Filled Binary Image with Boundaries');
hold off;
% Define object boundaries
numberOfBoundaries = size(boundaries, 1)
boundary1 = boundaries{1};
boundary2 = boundaries{2};
boundary1x = boundary1(:, 2);
boundary1y = boundary1(:, 1);
x1=1;
y1=1;
x2=1;
y2=1;
overallMinDistance = inf; % Initialize.
index1 = 1;
index2 = 1;
for k = 1 : length(boundary2)
boundary2x = boundary2(k, 2);
boundary2y = boundary2(k, 1);
% For this blob, compute distances from boundaries to edge.
allDistances = sqrt((boundary1x - boundary2x).^2 + (boundary1y - boundary2y).^2);
% Find closest point, min distance.
[minDistance(k), indexOfMin] = min(allDistances);
if minDistance(k) < overallMinDistance
overallMinDistance = minDistance(k);
x1 = boundary1x(indexOfMin);
y1 = boundary1y(indexOfMin);
x2 = boundary2x;
y2 = boundary2y;
index2 = k;
index1 = indexOfMin;
end
end
% Report to command window.
fprintf('Min Distance from sqrt() method = %f at index %d of boundary 1 and index %d of boundary 2.\n', ...
overallMinDistance, index1, index2);
hFig = figure;
h1 = subplot(1, 2, 1);
imshow(binaryImage);
axis on;
title('Closest Distance from sqrt()');
h2 = subplot(1, 2, 2);
imshow(binaryImage);
axis on;
title('Closest Distances from pdist2()');
hFig.WindowState = 'maximized';
hold on;
% Draw a line between point 1 and 2
line(h1, [x1, x2], [y1, y2], 'Color', 'y', 'LineWidth', 3);
%======================================================================================
% For comparison, use pdist2()
allDistances2 = pdist2(boundary1, boundary2);
minDistance2 = min(allDistances2(:));
% Find all points that have that min distance - there may be several that have it.
[r, c] = find(allDistances2 == minDistance2)
boundary1x = boundary1(:, 2);
boundary1y = boundary1(:, 1);
boundary2x = boundary2(:, 2);
boundary2y = boundary2(:, 1);
for k = 1 : length(r)
% Report to command window.
index1 = r(k);
index2 = c(k);
fprintf('Min Distance from pdist2() method = %f at index %d of boundary 1 and index %d of boundary 2.\n', ...
minDistance2, index1, index2);
xLine = [boundary1x(index1), boundary2x(index2)];
yLine = [boundary1y(index1), boundary2y(index2)];
line(h2, xLine, yLine, 'Color', 'm', 'LineWidth', 1.5);
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bones = 84; % Number of images you have for each person
people = 5; % Number of people you have
% Preallocate array for each person's minimum distance
personal_min_dist = zeros(people,1);
% Preallocate array for each bone's minimum distance
% This assumes that you have the exact same number of
% images for each person. If not, this array may need
% to change size inside the loop
bones_min_dist = zeros(bones,1)
for person = 1:people
% Get the set of images for each person
personal_bones_data = imageArray(person)
% Your actual setup here will depend on how your data is stored
for image = 1:bones
% Get minimum distance for each image using ImageAnalyst's function
bones_min_dist(image) = minDistance2(personal_bones_data(image))
end
% Get bone distance as mean of all distances for a person
personal_bone_dist(person) = mean(bones_min_dist);
end
end
I don't even know what "apply the minimum distance from the previous step to all the samples(images)." means.
Each image will have its own minimum distance, which you can find. But what does it mean to APPLY the distance from one image to a different image??? How do you apply a distance?
Dataset: There are a total of 420 images, where 84 images belong to 1 case, and I have created a dataset for 5 such cases.
What I mean is, the way the distance between the two bones in one image was found, I need to find the distance between the two bones for all these images(420 images). Lastly, I need to compute the mean of distances per case for the 84 images in that case which determines an average distance for that 1 case, and put the average value of those 84 images in a vector. I need to do the same for 5 such cases and have 5 average values put in 5 vector.

Sign in to comment.

Answers (0)

Asked:

on 26 Apr 2021

Commented:

on 29 Apr 2021

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!