我正在尝试编写脊检测算法,我发现的所有信号源似乎都将边缘检测与脊检测混为一谈。现在,我已经实现了Canny边缘检测算法,但它不是我想要的:例如,给定图像中的单行,它将有效地将其转换为双行边缘(因为它将记录这两行的侧面 - 我只想让它读取一行。
关于岭检测的wikipedia article有一堆数学,但这种方式对我作为一个程序员没有帮助(不是说我不喜欢数学,但这不是我的领域,我不喜欢不懂如何将微分方程转化为代码。实际实现这个有一个很好的来源吗?或者,就此而言,是否有一个很好的开源实现?
编辑:这是一个简单的例子。我们从简单的一行开始:
http://img24.imageshack.us/img24/8112/linez.th.png
并运行Canny算法得到:
http://img12.imageshack.us/img12/1317/canny.th.png
(你可以看到它在这里更厚 - 如果你点击图像,你会发现它实际上是两条相邻的线条,中间有一个空白)
另外,我是用C ++编写的,但这并不重要。但我想编写算法,而不只是编写SomePackage::findRidges()
并完成它。
答案 0 :(得分:5)
也许您需要考虑清理已有的线路,而不是类似Canny的边缘检测。感觉你应该能够用image morphology做一些事情,特别是我正在考虑骨架化和最终侵蚀点类型的操作。如果使用得当,这些应该从您的图像中删除任何非“线条”的功能 - 我相信它们是在英特尔的OpenCV库中实现的。
您可以使用Canny过滤器使用一个扩张操作生成的双线恢复单行,然后进行3次侵蚀(我在ImageJ中尝试过) - 这也应该删除任何边缘。
答案 1 :(得分:2)
我打算像Ian所说的那样建议清理你的行,但如果你不想这样做,你也可以考虑做一些hough变换的变种。
http://en.wikipedia.org/wiki/Hough_transform
您应该能够从中获得该线的实际等式,因此您可以根据需要将其设置为细线或粗线。唯一棘手的部分是确定线的终点。
这是我几年前用MATLAB编写的用于霍夫变换的代码。我不确定它的效果如何,但它应该给你一个大致的想法。它会找到图像中的所有行(而不是段)
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);
答案 2 :(得分:0)
如果仍然有人对此感兴趣,这里是ridges / valleys算法的一种实现:C++ source code。寻找一个名为get_ridges_or_valleys()
的函数。此实现是Linderhed (2009)提出的算法的3D版本。有关脊/谷算法,请参见论文的第8页。