finding the distance between points of boundaries

Hi all,
I need help to find the distance between boundaries . I have attached my original microscopy image and the code I wrote to get the more clear boudaries of desired regions of that image . After that my problem is to find the distance between right most points of innner(green) and outer(Red) boundaries . Actually, I have to find the the distance between A and B points indicated in the resulting png.
It would be great if you share some ideas about writing codes for this measurement.
Thank you

 Risposta accettata

Babu, to process many images, see the code samples in the FAQ:
To find the distance on the right between the two circles, try this.
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;
%--------------------------------------------------------------------------------------------------------
% READ IN IMAGE
folder = pwd;
baseFileName = 'originalimage.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
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);
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.
subplot(2, 2, 1);
imshow(grayImage, []);
title('Original Grayscale Image', 'FontSize', fontSize, 'Interpreter', 'None');
impixelinfo;
hFig = gcf;
hFig.WindowState = 'maximized'; % May not work in earlier versions of MATLAB.
drawnow;
% Display histogram
subplot(2, 2, 2);
imhist(grayImage);
grid on;
title('Histogram of gray image', 'FontSize', fontSize);
%--------------------------------------------------------------------------------------------------------
% SEGMENTATION OF IMAGE
% Get a binary image
brightMask = imbinarize(grayImage);
% Take the 2 biggest blobs
brightMask = bwareafilt(brightMask, 1, 4);
% Get rid of the small dots in the star by doing a hole fill.
% binaryImage = imfill(binaryImage, 'holes');
subplot(2, 2, 3);
imshow(brightMask, []);
impixelinfo;
title('Initial Binary Image', 'FontSize', fontSize, 'Interpreter', 'None');
impixelinfo;
% Need to get rid of little black specks in blob.
props = regionprops(brightMask, 'Area');
brightArea = props.Area
minAllowableArea = brightArea * 0.9
brightMask = ~bwareafilt(~brightMask, 2);
% Blur it a bit to smooth it out.
windowSize = 17;
kernel = ones(windowSize, windowSize) / windowSize ^ 2;
brightMask = imfilter(brightMask, kernel) > 0.5;
subplot(2, 2, 4);
imshow(brightMask, []);
impixelinfo;
title('Final Binary Image', 'FontSize', fontSize, 'Interpreter', 'None');
impixelinfo;
% Get boundaries and plot them, just for fun.
boundaries = bwboundaries(brightMask);
subplot(2, 2, 1);
hold on;
for k = 1 : length(boundaries)
thisBoundary = boundaries{k};
x = thisBoundary(:, 2);
y = thisBoundary(:, 1);
plot(x, y, 'r-', 'LineWidth', 2);
end
%--------------------------------------------------------------------------------------------------------
% FIND DISTANCE BETWEEN CIRCLES ON THE RIGHT HAND SIDE.
% Find the right-most point.
[r, c] = find(brightMask);
[lastColumn, outerIndex] = max(c)
xRight = c(outerIndex)
yRight = r(outerIndex)
innerBoundary = boundaries{2};
x = innerBoundary(:, 2);
y = innerBoundary(:, 1);
% Find the closest point on the inner boundary to that point.
distances = sqrt((x - xRight).^2 + (y - yRight).^2);
[minDistance, innerIndex] = min(distances)
xInner = innerBoundary(innerIndex, 2);
yInner = innerBoundary(innerIndex, 1);
% Draw a line between them
line([xInner, xRight], [yInner, yRight], 'Color', 'r', 'LineWidth', 2);
subplot(2, 2, 4);
line([xInner, xRight], [yInner, yRight], 'Color', 'r', 'LineWidth', 2);
caption = sprintf('Final Mask. Distance = %.1f', minDistance);
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');

25 Commenti

Babu Sankhi
Babu Sankhi il 27 Lug 2020
Modificato: Babu Sankhi il 27 Lug 2020
Thank you Analyst I really appreciate your help; it works very well for my image .
In addition to that I am sorry I have still one additional follow up question;
1) How can I find the (x,y) co-ordinates of the centre of inner-boundary only?
Thank you
Babu: did you overlook these lines:
innerBoundary = boundaries{2};
x = innerBoundary(:, 2);
y = innerBoundary(:, 1);
Then to get the center, just take the mean of x and y.
Babu Sankhi
Babu Sankhi il 27 Lug 2020
Modificato: Babu Sankhi il 27 Lug 2020
Thank you analyst I got the center;
But these (accepted) codes work only for the previous image I sent you not for other png images (like as I attached below). I tried by changing the parameters to get rightmost boundary distances but It gave me crazy result. Can you help me which part of code should be modified to get right most distances between two big blob ( same as before) for such type of images?
This image is intensity inverted as compared to the last one. Which way is it supposed to be? Can't you have it be consistent?
Babu Sankhi
Babu Sankhi il 27 Lug 2020
Modificato: Babu Sankhi il 27 Lug 2020
Yes I agree, But we are supposed to do both ways. Sorry No I cant.( I think new2.png has same intensity profile as last but still does not work).Please let me know if you have any idea for it.
Thank you
Extract the first row and get the mean value. If it's above or below a certain value, then invert it. You may also need to play around with the window size for blurring if your thin surround gets too thin (too close to the edge of the image).
I am sorry, I am not quiet sure about it, I find the mean of row then what do you mean by certain value. Rows have allmost same values at all. Can you please help me?
folder = pwd;
baseFileName = 'new1.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))
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);
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
row1 = grayImage(1,:)
findmean=mean(row1)
[row,col] = find(row1)
findmofindicesrow=mean(row);
findmocolumn= mean(col)
How about if the mean of the first 3 rows is brighter than the mean of the image, invert it? This is because I was expecting the surround to be darker than the donut. If it's not, we need to invert it before we proceed with the algorithm.
meanOf3Rows = mean2(grayImage(1:3, :));
if meanOf3Rows > mean2(grayImage)
% Polarity is the opposite of what the algorithm was designed for, so invert it.
grayImage = 255 - grayImage;
end
Babu Sankhi
Babu Sankhi il 28 Lug 2020
Modificato: Babu Sankhi il 28 Lug 2020
Thank you analyst it worked for intesity inverted image (like muu.png) now.
But still it does not work for the images like new1 and new2.png images ,as attached above. Can you please look at those images and give me some additional ideas about doing for those images too?
Are those the original images? Why do they look so dramatically different? These would need a completely different algorithm - one based on binary images instead of gray scale images. Is that how they start out? Or did they start out like the others and you did something to them for some reason?
Thank you analyst ,
I wanted all of them ( my images) to be gray scale image and tried to save my 100 images
by using (imwrite) code given below; they look dramatically different. Do you have any idea to save all of them by making gray scale that would be nice?
for n=101:200
I1 =medfilt2(double(testI(:,:,n)-testI(:,:,117)));%actual
%image at 7.5mT
II1 =medfilt2(testI(:,:,48)-testI(:,:,117));% substraction
%of backgroaund
III1=(I1-II1)% gives the image with the reference image at the center
filename=sprintf('PMA44asmexpanat-13pt9mT%02d.png', n);%saves all files
imwrite(III1,filename)
end
I know the code below displays the gray scale image. But I want all of them to be saved at once by using code . Any help will really be appreciated.
figure(6);
imagesc(medfilt2(double(testI(:,:,108)-testI(:,:,117))),;colormap gray
I don't know what you want. imwrite() does save all the images, not at once, but one at a time to individual files. If you want all files saved at once then you will have to use save() after the loop to either save one big 3D array with all 100 images in it or a 1-D cell array with images in each cell.
Sorry, no. I don't know what imprint is. You can save them with imwrite() and it you give it a gray scale image, it will save it exactly how it it. If you pass it a color image, it will save it as a color image. Note, it's possible for a color image to look gray scale if all the color channels are identical.
thank you,
Its solved.
I am sorry I got another problem. I want to apply above algorithm for 100 same intensity images and also want to save all distinct plots in one file/folder and corresponding right most distances/edge (between boundaries) another text file. So that text file should contain rightmost distances in one column and other column contain the corresponding numbers (eg.serial number).
Can you please help me in this regard?
Babu Sankhi
Babu Sankhi il 2 Ago 2020
Modificato: Babu Sankhi il 2 Ago 2020
Hi Analyst,
I used for loop to save all the right edge(miDistances). But the problem is that I have to change the windowSize for each image to get the accurate value (as I have different imges with surround getting too thin to too wide) . It means I dont get accurate values for all images by using same algorithm. For 500 images each time changing windowSize is crazy. Can't we develope the algorithm so that it works for all (same intesity but different sizes surroundings) images without changing windowSize?
Thank you
Probably. But it looks like you cropped those out of a larger image. Maybe you need to adjust your cropping algorithm. Why even crop at all? Why not just use the original size image and just mask out one donut at a time from it? Not as a smaller image but as a blob in the original, full-sized image.
Where we used cropping algorithm? I am really sorry I could not undersand your answer.
Hi,
I tried to save my (sub)plots as displayed in accepted answer of this question at the begining, by using code;
pngFileName = sprintf('plot_subject_%d.png', i);
fullFileNam = fullfile(folder, pngFileName);
% Then save it
export_fig(fullFileNam);
It always gives the error like this;
Undefined function 'export_fig' for input arguments of type 'char'.
Can you please help me to fix the error and hence save the figures?
thank you
I thought I remember seeing one of your images once that was larger and had several donuts in it, not one small image with one donut.
For export fig, you can use exportgraphics() which is built in to r2020a, or see this link.
Babu Sankhi
Babu Sankhi il 4 Ago 2020
Modificato: Babu Sankhi il 4 Ago 2020
Thank you,
But still both problems remain unresolved.
I used exportgraphics it displays the error like ;
Undefined function 'exportgraphics' for input arguments of type 'matlab.ui.Figure'.
It would be great if anyone can help me more?
thank you
So you have not, for some reason, added your release to the right hand side of this page, or when you posted this. It's helpful if you completely read and fill out the form when initially posting. Eveidently you don't have r2020a.
Did you set a path to export_fig?
oh sorry, I have R2019aor b not R2020a.
Yes I tried several ways. I think I set the path by assigning the folder and figures are supposed be saved there. But it still gives the same error. Can you please help me more?
Thank you
For i=1:100
My code is here for everything to get the figures
pngFileName = sprintf('plot_subject_%d.png', i);
fullFileNam = fullfile('F:\2020\microscope\setup\figur', pngFileName);
% Then save it
export_fig(fullFileNam);
%addpath('F:\2020\microscope\setup\figur', '-end')
end
What does this say if you put it right before that call to export_fig
which -all export_fig
It gives the error;
'export_fig(fullFileNam)' not found. when I use this;
For i=1:100
My code is here for everything to get the figures
pngFileName = sprintf('plot_subject_%d.png', i);
fullFileNam = fullfile('F:\2020\microscope\setup\figur', pngFileName);
% Then save it
which -all export_fig(fullFileNam);
%addpath('F:\2020\microscope\setup\figur', '-end')
end
But
I don't get any error when I use this. However no figures are saved. Can you please help me more?
all export_fig(fullFileNam);

Accedi per commentare.

Più risposte (1)

If you have the Statistics Toolbox, you can pdist2
D = pdist2(Red,Green)

7 Commenti

Babu Sankhi
Babu Sankhi il 26 Lug 2020
Modificato: Babu Sankhi il 26 Lug 2020
Thank you Matt,
I am sorry I am not quite clear about your answer. Do you mean I have to find the coordinates of red and green boundary by using toolbox then use pdist2 function to measure distance? if not, How can I define the variable red and green as I have several other unwanted greens too?
Thank you for your great help
That's no problem, but first we need to answer what distance(s) do you want? Do you want
  1. all distances (thousands of them) from every green point to every red point - all possible combinations (if so why?)
  2. or do you want the smallest distance that indicates how close the inner boundary comes to the outer boundary at its closest point?
Which is it?
Babu Sankhi
Babu Sankhi il 26 Lug 2020
Modificato: Babu Sankhi il 26 Lug 2020
No I do not need all distances and smallest distance too. I only need how much difference/distance in between them along right direction/edge (+x direction). For example if you see the resulting image attached above; eg. the coordinates of A(point on green boundary)is (102,0) & B( point on red boundary) is (178,0).So that their difference is 76 pixel along right direction , right? That is what I want to do. I have several other different images like this so I want to have some efficient code for the measurement. Thank you analyst for your great help
Matt J
Matt J il 26 Lug 2020
Modificato: Matt J il 26 Lug 2020
Do you mean I have to find the coordinates of red and green boundary by using toolbox
Yes, and from your posted attachments, you have clearly done that already. Since you only care about the horizontal coordinates, you can modify my initial solution to,
minDistance = pdist2(red(:,1), green(:,1),'cityblock','Smallest',1);
Babu Sankhi
Babu Sankhi il 26 Lug 2020
Modificato: Babu Sankhi il 26 Lug 2020
Thank you Matt
But I have thousands of images to do that so using tool box for each is quiet time consuming/and allmost impossible. So I am looking for the code that will help me to get these coordinates and their difference along right direction/edge only.
How can I define red and green for using this?
xred = boundary1(:,2);
xgreen = boundary2(:,2);
distance = max(xred) - max(xgreen);
But I have thousands of images to do that so using tool box for each is quiet time consuming/and allmost impossible.
The boundarycalculation.m routine that you attached takes about 0.02 sec on my machine once you remove all of the plotting commands. That should allow you to do thousands of images in about a minute or so - doesn't seem so bad to me.
Using the alternative version below, I was able to cut the time by about half. The imclose operations that I commented out may or may not be helpful in removing noise, and in any case don't add much overhead:
tic;
BW=bwareafilt(imbinarize (II),1);
%BW=imclose(BW,ones(3));
BWhole=bwareafilt(imfill(BW,'holes')-BW>0,1);
%BWhole=imclose(BWhole,ones(3));
[~,J]=find(BW);
[~,Jhole]=find(BW);
distance=max(J)-max(Jhole);
toc
%Elapsed time is 0.009772 seconds.

Accedi per commentare.

Community Treasure Hunt

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

Start Hunting!

Translated by