Over on dsp.stackexchange.com someone asked a question about segmenting a roughly round object from an x-ray:

My solution was to use shortest path. It is very powerful. These are the steps:

Bandpass filter

We are interested in finding the edges of the oval sections. The first step is to make a bandpass filter, in this case a difference of Gaussians, to isolate the smaller features.

H1 = fspecial('gaussian',[60,60],5);
H2 = fspecial('gaussian',[60,60],2);
H = H2-H1;

Edge filter

Use the Hilbert transform to make two edge filters, one in the x and one in the y direction.

Hedge = imag(hilbert(H));

Filtered images

Filter the image with the edge filters. Square each of the edge filter responses, add them together, then take the square root. The result is the magnitude of the edges.

Iodd = sqrt(imfilter(I,Hedge).^2 + imfilter(I,Hedge.').^2);

Shortest Path

Shortest phase looks for the path of lowest energy (but not negative), so invert the edge values. We use the *log* of the edge values here as that makes strong and weak edges a little closer together in value. Using the log is not mandatory, you just need to get some kind of energy image that is a good measure.

G = log(Iodd);
G = max(G(:)) - G;

Perform shortest path. I won’t explain this fully as it would require an entire paper.

[ path, energy, lastIndex, pathImage ] = ...
circularShortestPath(G, 0.1, [300,300], [100,400], [400,720]);

hold on;
hold off;

hold on;
hold off;


Use the path to segment the image

J = zeros(size(I));
mask = roipoly(J,path(:,1),path(:,2));
segmentedI = I .* mask;
imagesc(segmentedI); title('segmented image'); colormap gray(256);


Changing the centre point of the shortest path you can segment other things as well:

[ path, energy, lastIndex, pathImage ] = ...
circularShortestPath(G, 0.1, [114,394], [10,400], [400,720]);

Code available: