Find maximum Euclidean distance of Canny edge output and drawing a line between the points

I am new to Matlab and I am working on a project wherein I want to draw a line between the farthest two edges of an image. I have first used Canny edge detection algorithm to get the edges. Stored the boundaries in a vector. Then, I have calculated the Euclidean distances amongst all the pixels stored inside the vector. The problem I am having is storing the maximum value obtained of this Euclidean distance and plotting a line amongst those two pixels.

Here is an example image:

Code:

im = edge(gray,'canny',0.3);
subplot(2,2,3);imshow(im);title('Canny Output');
figure
imagesc(im)
hold on

[B,L] = bwboundaries(im,'noholes');
for l=1:length(B)-1
    for m=l+1:length(B)-1
        for j=1:length(B{l})
            for k=1:length(B{m})
                a(j,k) = abs(B{l}(j,2) - B{m}(k,2));
                b(j,k) = abs(B{l}(j,1) - B{m}(k,1));
                c(j,k) = sqrt(sum(a(j,k)*a(j,k),b(j,k)*b(j,k)));
                [~,idx] = max(c(j,k));
                [x,y] = ind2sub(size(c),idx);
                p1.l = [B{l}(x,2),B{l}(x,1)];
                p2.m = [B{m}(y,2),B{m}(y,1)];
                plot([p1.l(1),p2.m(1)],[p1.l(2),p2.m(2)],'Color','g','LineWidth',2)
                clear a b c x y idx
            end
        end
    end
end

Answers


This is fairly easy to implement in MATLAB and is also fast (at least for small images). Provided that you have a binary edge image, you need to think of white pixels as points in a 2D space and look for the coordinates that correspond to the largest distance. MATLAB can easily do this using the pdist2 function with some extra parameters. Take a look at the following piece of code:

img = imread( 'image.bmp');
[ y, x] = find( img);
points = [ x y];
[d,idx] = pdist2( points, points, 'euclidean', 'Largest', 1);
idx1 = idx( d==max(d));
[~,idx2] = find(d==max( d));

p={};
for i=1:length(idx1)
   p{end+1} = [ points(idx1(i),1), points(idx1(i),2), points(idx2(i),1), points(idx2(i),2)];
end

First you need to know where are those white pixels so you initiate with a find function to get the coordinates. Then you use pdist2, which (in this case) returns the largest distances in a row matrix d and the corresponding indices in the row matrix i. Then you just need to check where is the maximum value in the largest distances to get the indices of the points with the maximum distance (these points are in a structure of points p). If you need to display the results just use the following piece:

figure; 
imshow( img);
hold on;
for i=1:numel(p)
    line( [ p{i}(1), p{i}(3)], [p{i}(2), p{i}(4)]);
    hdl = get(gca,'Children');
    set( hdl(1),'LineWidth',2);
    set( hdl(1),'color',[1 0 0]);
end

hold off;

You will get this image:


*** an addition that will help keep only unique points:

pp=[];
for i=1:numel(p)
    for j=i+1:numel(p)
        if prod( double( [p{i}(3:4),p{i}(1:2)] == p{j}))
            pp(end+1)=j;
        end
    end
end
j=1;
ppp={};
for i=1:numel(p)-numel(pp)
    if j<=numel(pp) && i~=pp(j)
        ppp{end+1}=p{i};
        j=j+1;
    end
end
p = ppp;


Need Your Help