Finding the distance between objects

14 views (last 30 days)
Duncan
Duncan on 5 Aug 2014
Edited: Image Analyst on 9 Apr 2019
I have the above image which I have already labeled using bwlabel(). Now what I want to do is something similar to what was posted in: http://www.mathworks.com/matlabcentral/answers/91046-how-to-find-distance-in-binary-image
For this case I want to calculate the smallest distance between object 1&2, 1&3 and 2&3. But in general I want to make it flexible so I could input any image with any amounts of objects and be able to calculate the distances.
This is my code so far:
Timg = zeros(size(Limg));
Timg(Limg == i)=1 ;
Dist = bwdist(Timg, 'euclidean');
for j~=i
DistanceValues = Dist(lableledImage == j));
min(DistanceValues);
end
It doesn't work as I expected it to. Any help in editing this code or completely changing the concept would be appreciated.
Thanks

Answers (2)

Image Analyst
Image Analyst on 5 Aug 2014
That code is no good.
First you need to get a binary image with the center filled in. I suggest you run around the border of the image and if there are any white pixels closer than 10 pixels or so, connect them. Then call imfill(binaryImage, 'holes') to get three solid branches.
Then call bwdist to get the distance transform on the binary image.
Next call bwmorph(binaryImage, 'skel', inf) to get the skeleton. The skeleton runs all the way out to the border and you don't want that since you'll get distance values of zero so you want to clip the skeleton by a few pixels with the 'spur' option of bwmorph. Think about it and you'll realize why. If not, plot the skeleton over the binary image and then you'll see why.
The distance transform has distances from every point to the border, which is not what we want. We want only those distances along the centerline, the skeleton. So multiply the skeleton by the distance transform to get only the radii. Double it to get the diameters.
Then extract all non-zero pixels and find the min. Then you're done.
An alternative way - kind of a brute force approach - is just to label the image and use the Pythaogrean theorem to find the distance from every pixel of region m to region n. Call find() on each to get a list of coordinates, then use sqrt() to get distances. Use a single for loop. Should be fast, probably faster than the first method, since there are only a few hundred or thousand elements.
Code up one of those methods, and run it by me if you want.
  4 Comments
Image Analyst
Image Analyst on 8 Apr 2019
One way to find the longest spine might be to compute the skeleton and endpoints with bwmorph(). Then compute distance between all identified endpoints with bwdistgeodesic(). See Steve's Image Processing blog
Then find out which pair of endpoints had the longest distance.
Brett Shoelson
Brett Shoelson on 9 Apr 2019
Edited: Image Analyst on 9 Apr 2019
Image Analyst's answer is spot on. Here's a snippet of code that gets you to it. Note that I took a grayscale screen shot of the lightning, and inverted it first. (I called it 'lightning.png'.) If you don't have togglefig(), you can either comment it out, replace it with 'figure', or get it from the File Exchange.
Regards,
Brett
clear;close all;clc;
%%
img = imread('lightning.png');
%imwrite(img,'lightning.png');
togglefig('Original')
imshow(img)
%%
% imageMorphology(img)
%%
SE = strel('Disk',8,4);
lightning = imclose(img, SE);
togglefig('Lightning')
imshow(lightning)
%%
lightning = imbinarize(lightning);
togglefig('Lightning')
imshow(lightning)
%%
% imageMorphology(lightning)
% I prefer 'thin' to 'skel' because it generally yields fewer spurs...
lightning = bwmorph(lightning, 'thin', Inf);
togglefig('Lightning')
imshow(lightning)
%%
endpoints = bwmorph(lightning,'endpoints');
[r,c] = find(endpoints);
hold on
plot(c,r,'r.','markersize',14)
%% USE BWDISTGEODESIC:
maxDist = -inf;
rbest = [];
cbest = [];
for ii = 1:numel(r)
for jj = 1:numel(c)
tmp = bwdistgeodesic(lightning,c(jj),r(ii),'quasi-euclidean');
thisDist = max(max(tmp));
if round(thisDist) >= round(maxDist)
maxDist = thisDist;
rbest = [rbest,r(ii)]; %#ok<*AGROW>
cbest = [cbest,c(jj)];
end
end
end
hold on
plot(cbest,rbest,'go','markersize',18);
title(sprintf('Longest Path: %0.2f',maxDist))

Sign in to comment.


Alaa
Alaa on 4 Mar 2015
And your help will be highly appreciated...

Community Treasure Hunt

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

Start Hunting!