7

我正在尝试编写一个脊检测算法,我发现的所有来源似乎都将边缘检测与脊检测混为一谈。现在,我已经实现了 Canny 边缘检测算法,但这不是我想要的:例如,给定图像中的一条线,它会有效地将其转换为双线边缘(因为它会记录两边该行)-我只想让它读取一行。

wikipedia article about ridge detection 有一堆数学,但这对我作为程序员没有帮助(不是我不喜欢数学,但这不是我的领域,我不明白如何翻译他们的微分方程成代码)。是否有一个很好的资源来实际实现这一点?或者,就此而言,是否有一个好的开源实现?

编辑:这是一个简单的例子。我们从一个简单的行开始:

http://img24.imageshack.us/img24/8112/linez.th.png

并运行 Canny 算法得到:

http://img12.imageshack.us/img12/1317/canny.th.png

(你可以看到这里比较粗——如果你点击图片,你会看到它确实是两条相邻的线,中间有一个空白)

另外,我正在用 C++ 编写,但这并不重要。但我想对算法进行编码,而不仅仅是编写SomePackage::findRidges()并完成它。

4

3 回答 3

5

也许您需要考虑清理已有的线条,而不是像 Canny 一样的边缘检测。感觉你应该能够对图像形态学做一些事情,特别是我在考虑骨架化和最终侵蚀点类型的操作。正确使用这些应该从您的图像中删除任何不是“线条”的功能 - 我相信它们是在英特尔的 OpenCV 库中实现的。

您可以从使用 Canny 过滤器生成的双线中恢复单线,使用一个扩张操作,然后是 3 个腐蚀(我在 ImageJ 中尝试过)——这也应该删除任何边缘。

于 2009-02-25T13:24:52.453 回答
2

我打算像伊恩所说的那样清理你的线条,但如果你不想这样做,你也可以考虑做一些霍夫变换的变体。

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);
于 2009-02-26T09:13:34.530 回答
0

如果有人对此仍然感兴趣,这里是脊/谷算法的实现: C++ 源代码。寻找一个名为get_ridges_or_valleys(). 该实现是Linderhed (2009)提出的算法的 3D 版本。有关脊/谷算法,请参见论文的第 8 页。

于 2018-11-26T20:47:06.503 回答