Реализация обнаружения гребня - PullRequest
7 голосов
/ 25 февраля 2009

Я пытаюсь написать алгоритм обнаружения гребня, и все источники, которые я нашел, похоже, связывают обнаружение кромки с обнаружением гребня. Прямо сейчас я реализовал алгоритм обнаружения ребер Канни, но это не то, что мне нужно: например, если на изображении будет одна строка, он будет эффективно преобразовывать его в двойную линию ребер (поскольку он будет записывать обе стороны линии) - я просто хочу, чтобы она прочитала одну строку.

В статье Википедии об обнаружении гребней есть куча математики, но этот вид этого не помогает мне как программисту (не то, чтобы я не любил математику, но это не моя область, и я не понимаю, как перевести их дифференциальные уравнения в код). Есть хороший источник для фактической реализации этого? Или, если на то пошло, есть хорошая реализация с открытым исходным кодом?

Редактировать: вот простой пример. Начнем с простой строки:

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

и запустите алгоритм Канни, чтобы получить:

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

(здесь видно, что он толще - если щелкнуть изображение, вы увидите, что на самом деле это две соседние строки с пробелом между ними)

Кроме того, я пишу на C ++, но это не должно иметь большого значения. Но я хочу закодировать алгоритм , а не просто написать SomePackage::findRidges() и покончить с этим.

Ответы [ 3 ]

5 голосов
/ 25 февраля 2009

Может быть, вам нужно подумать о том, чтобы очистить уже имеющуюся линию, а не об обнаружении краев, подобном Canny. Такое чувство, что вы должны быть в состоянии что-то сделать с морфологией изображения , в частности, я имею в виду операции типа скелетонизации и предельных размытых точек. При правильном использовании они должны удалить из вашего изображения любые функции, которые не являются «линиями» - я считаю, что они реализованы в библиотеке Intel OpenCV.

Вы можете восстановить одну строку из вашей двойной строки, сгенерированной с использованием фильтра Канни, используя одну операцию расширения, за которой следуют 3 эрозии (я опробовал это в ImageJ) - это также должно удалить любые края.

2 голосов
/ 26 февраля 2009

Я собирался предложить очистить ваши строки, как сказал Ян, но если вы не хотите этого делать, вы также можете заняться каким-нибудь вариантом грубого преобразования.

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);
0 голосов
/ 26 ноября 2018

Если кому-то все еще интересно это, вот реализация алгоритма гребней / долин: Исходный код C ++ . Ищите функцию с именем get_ridges_or_valleys(). Эта реализация является трехмерной версией алгоритма, предложенного Linderhed (2009) . См. Стр. 8 для алгоритма гребней / долин.

...