I\'m trying to write a ridge detection algorithm, and all of the sources I\'ve found seem to conflate edge detection with ridge detection. Right now, I\'ve implemented the Canny
If anyone is still interested in this, here is an implementation of the ridges/valleys algorithm: C++ source code. Look for a function called get_ridges_or_valleys()
. This implementation is a 3D version of the algorithm proposed by Linderhed (2009). See page 8 of the paper for the ridges/valleys algorithm.
I was going to suggest cleaning up your lines like Ian said, but if you don't want to do that, you might also look into doing some variant of a hough transform.
http://en.wikipedia.org/wiki/Hough_transform
You should be able to get the actual equation for the line from this, so you can make it as thin or as thick as you like. The only tricky part is figuring out where the line ends.
Here's the code I wrote for a hough transform a few years ago, written in MATLAB. I'm not sure how well it works anymore, but it should give you a general idea. It will find all the lines (not segments) in an image
im = imread('cube.tif');
[bin1,bin2,bin3] = canny(im);
%% define constants
binary = bin1;
distStep = 10; % in pixels
angStep = 6; % in degrees
thresh = 50;
%% vote
maxDist = sqrt((size(binary,1))^2+(size(binary,2))^2);
angLoop = 0:angStep*pi/180:pi;
origin = size(binary)/2;
accum = zeros(ceil(maxDist/distStep)+1,ceil(360/angStep)+1);
for y=1:size(binary,2)
for x=1:size(binary,1)
if binary(x,y)
for t = angLoop
dx = x-origin(1);
dy = y-origin(2);
r = x*cos(t)+y*sin(t);
if r < 0
r = -r;
t = t + pi;
end
ri = round(r/distStep)+1;
ti = round(t*180/pi/angStep)+1;
accum(ri,ti) = accum(ri,ti)+1;
end
end
end
end
imagesc(accum);
%% find local maxima in accumulator
accumThresh = accum - thresh;
accumThresh(logical(accumThresh<0)) = 0;
accumMax = imregionalmax(accumThresh);
imagesc(accumMax);
%% calculate radius & angle of lines
dist = [];
ang = [];
for t=1:size(accumMax,2)
for r=1:size(accumMax,1)
if accumMax(r,t)
ang = [ang;(t-1)*angStep/180*pi];
dist = [dist;(r-1)*distStep];
end
end
end
scatter(ang,dist);
Maybe you need to think in terms of cleaning up the line you already have, rather than a Canny-like edge detection. It feels like you should be able to do something with image morphology, in particular I'm thinking of the skeletonize and ultimate eroded points type operations. Used appropriately these should remove from your image any features which are not 'lines' - I believe they're implemented in Intel's OpenCV library.
You can recover a single line from your double line generated using the Canny filter using one dilate operation followed by 3 erodes (I tried it out in ImageJ) - this should also remove any edges.