Как реализовать градиентное преобразование Хафа

9

Я пытаюсь использовать преобразование Хафа для обнаружения краев и хотел бы использовать градиентные изображения в качестве основы.

То , что я сделал до сих пор, учитывая изображение Iразмера [M,N]и ее частных производных gx, gy, чтобы вычислить угол градиента в каждом пикселе , как thetas = atan(gy(x,y) ./ gx. Точно так же я вычисляю величину градиента как magnitudes = sqrt(gx.^2+gy.^2).

Для построения преобразования Хафа я использую следующий код MATLAB:

max_rho = ceil(sqrt(M^2 + N^2));
hough = zeros(2*max_rho, 101);
for x=1:M
    for y=1:N
        theta = thetas(x,y);
        rho = x*cos(theta) + y*sin(theta);

        rho_idx = round(rho)+max_rho;
        theta_idx = floor((theta + pi/2) / pi * 100) + 1;
        hough(rho_idx, theta_idx) = hough(rho_idx, theta_idx) + magnitudes(x,y);
    end
end

Результирующее преобразование Хафа выглядит правдоподобно (см. Http://i.stack.imgur.com/hC9mP.png ), но когда я пытаюсь использовать его максимумы в качестве параметров края в исходном изображении, результаты выглядят более или менее случайными. Я сделал что-то не так при построении преобразования Хафа?

ОБНОВЛЕНИЕ : у меня была глупая ошибка в моем коде: rhoбыл вычислен как x*cos(theta)+y*cos(theta)вместо x*cos(theta)+y*sin(theta). То есть я использовал два косинуса вместо косинуса и синуса. Я отредактировал код выше и новое полученное изображение ниже. Это не дало намного лучшие края все же.

@endolith: Чтобы построить ребро, учитывая максимальное значение в hough-матрице в rho_idx, theta_idx, я перевожу индексы в rho,thetaзначения:

theta = (theta_idx -1) / 100 * pi - pi / 2;
rho = rho_idx - max_rho;

Наконец я рисую край как y= (rho - x*cos(theta)) / sin(theta).

Новый результат

Йонас Дуэ Вестерхеден
источник
«когда я пытаюсь использовать его максимумы в качестве параметров края в исходном изображении» Как вы это делаете?
Эндолит
@Jonas Due Vesterheden Просто интересно, это изображение с доплеровской частотой во времени? ...
Спейси
@ Мохаммед: Не то, что я знаю. Исходное изображение имеет какую-то печатную плату. Что вы подразумеваете под "VS"?
Джонас Дуэ Вестерхеден
@JonasDueVesterheden «VS» означает «против». (Время по сравнению с доплеровской частотой ») :-)
Спейси
Вы должны сгладить свою карту жесткости, прежде чем применять к ней немакс.

Ответы:

2

Я немного смущен вашим вопросом. Преобразование Хафа используется для обнаружения линий, а не краев.

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

Если вы хотите обнаружить прямые линии, вам лучше начать с карты краев, а затем использовать houghфункцию панели инструментов Обработка изображений, если у вас есть к ней доступ. Проблема с преобразованием Хафа для градиента состоит в том, что краевые пиксели, образующие прямую линию, могут иметь противоположные ориентации градиента. Например, рассмотрите образец шахматной доски. Край между двумя рядами квадратов меняет ориентацию в зависимости от того, есть ли у вас черный квадрат вверху и белый квадрат внизу, или наоборот.

Что касается вашей реализации, я думаю, что проблема в том, что ячейки в вашей матрице Хо слишком малы. По существу, размер ячейки в измерении rho равен 1, а размер ячейки в измерении тета составляет менее 2 градусов. Это означает, что градиентные ориентации должны очень точно освещаться, чтобы образовать линию, что редко случается на практике. Если вы вычислите rho_idx и theta_idx так, чтобы ячейки были больше, это сделает ваш линейный детектор более терпимым к ошибкам, и вы можете получить более качественные линии.

Дима
источник
1

Я понятия не имею, является ли это проблемой, но atan () дает вам углы от -90 до +90 градусов из-за двусмысленности квадранта. Чтобы получить полный угол наклона градиента (от -180 до 180), вам нужно использовать atan2 ().

Hilmar
источник
Спасибо за предложение! Насколько я понимаю, должно быть достаточно использовать углы от -90 до +90 градусов, поскольку «направления» ребер не имеют значения. Я пытался использовать atan2, но это не помогло.
Йонас Дуэ Вестерхеден