Помогите разобраться

19

Я пытаюсь заставить преобразование Хафа работать в MATLAB, но у меня проблемы. У меня есть действительно плохой способ определения пиков, которые нужно исправить, но до этого мне нужно иметь возможность отменить грубое преобразование для правильного создания линий. Это то, что я получаю прямо сейчас:

введите описание изображения здесь

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

%% load a sample image; convert to grayscale; convert to binary

%create 'x' image (works well)
a = eye(255);
b = flipud(eye(255));
x = a + b;
x(128,128) = 1;

%image = rgb2gray(imread('up.png')) < 255;
%image = rgb2gray(imread('hexagon.png')) < 255;
%image = rgb2gray(imread('traingle.png')) < 255;
%%% these work
%image = x;
%image = a;
image = b;    

%% set up variables for hough transform
theta_sample_frequency = 0.01;                                             
[x, y] = size(image);
rho_limit = norm([x y]);                                                
rho = (-rho_limit:1:rho_limit);
theta = (0:theta_sample_frequency:pi);
num_thetas = numel(theta);
num_rhos = numel(rho);
hough_space = zeros(num_rhos, num_thetas);

%% perform hough transform
for xi = 1:x
    for yj = 1:y
        if image(xi, yj) == 1 
            for theta_index = 1:num_thetas
                th = theta(theta_index);
                r  = xi * cos(th) + yj * sin(th);
                rho_index = round(r + num_rhos/2);                      
                hough_space(rho_index, theta_index) = ...
                     hough_space(rho_index, theta_index) + 1;
            end
        end
    end
end  

%% show hough transform
subplot(1,2,1);
imagesc(theta, rho, hough_space);
title('Hough Transform');
xlabel('Theta (radians)');
ylabel('Rho (pixels)');
colormap('gray');

%% detect peaks in hough transform
r = [];
c = [];
[max_in_col, row_number] = max(hough_space);
[rows, cols] = size(image);
difference = 25;
thresh = max(max(hough_space)) - difference;
for i = 1:size(max_in_col, 2)
   if max_in_col(i) > thresh
       c(end + 1) = i;
       r(end + 1) = row_number(i);
   end
end

%% plot all the detected peaks on hough transform image
hold on;
plot(theta(c), rho(r),'rx');
hold off;


%% plot the detected line superimposed on the original image
subplot(1,2,2)
imagesc(image);
colormap(gray);
hold on;

for i = 1:size(c,2)
    th = theta(c(i));
    rh = rho(r(i));
    m = -(cos(th)/sin(th));
    b = rh/sin(th);
    x = 1:cols;
    plot(x, m*x+b);
    hold on;
end

Связанный: Как сделать De-Houghing из Hough Transform'ed Image?

Оспинатор
источник
Вам удалось решить вашу проблему? я сталкиваюсь с подобной проблемой. спасибо
Эрез Познер
трансформация суфляга с матлабом для детей плюс эллипсы

Ответы:

11

Во-первых, в Matlab есть встроенное преобразование Хафа : не нужно изобретать велосипед.

[H,T,R] = hough(BW,'RhoResolution',0.5,'Theta',-90:0.5:89.5);

Хотя ваше изображение не обязательно требует распознавания краев, вы можете улучшить время обработки и эффективность алгоритма, используя его. Ваш треугольник имеет жирные области белого и черного. В идеале, треугольник должен иметь толщину 1 пиксель и обозначать края треугольника. Используйте Canny Edge Detection

BW = edge(Image,'canny');

-90<θ<900<θ<1800<θ<π90π/2 ).

Существует вероятность того, что вы выберете неправильный пик, потому что существуют соседние пики, которые могут быть больше в матрице аккумулятора. Хотя есть много алгоритмов, один из них я использовал в Hough Transforms в прошлом:

1) Define a region shape (typically its square) 
2) Define an accumulator threshold  
3) Select one pixel in the accumulator matrix
4) If it is a peak (i.e., larger than neighboring values above a threshold)
       a) look at the points within the region shape.
       b) If there is a larger value
              this is not a peak
          Else
              this is a peak
 5) Move to next pixel in accumulator matrix.

Посмотрите на HoughLines для отображения линий преобразования Hough, результаты:

http://www.mathworks.com/help/toolbox/images/ref/houghlines.html

Эффекты от использования Canny Edge Detector

Обнаружение края может потенциально превратить каждую сторону треугольника в две линии.

Целью обнаружения хитрых краев является получение максимально тонких / узких краев с использованием немаксимального подавления

Обнаружение Canny Edge в двух словах (Источник: Цифровая обработка изображений, Gonazalez)

1) Smooth input Image using a Gaussian Filter
2) Compute the Gradient magnitude and angle (Sobel, Perwitt or robert cross filters)
3) Apply Nonmaxima suppression (this is where the thinning happens) 
   a) Figure out which direction the edge is
   b) If the edge's magnitude is smaller than one of its two neighbors in the direction of the edge
          set the edge point to zero
      Else
          leave it alone
4) Use double thresholding and connectivity analysis to detect and link edges
Кибермужчины
источник
Спасибо за ответ. Я делаю это с нуля, чтобы лучше понять. обнаружение четкого края все еще дает 2 треугольника. один для внутреннего края, и наружу для внешнего края. Я узнал эту теорию из Википедии, в которой говорится, что тэта равна 0: pi. Я знаю, что встроенная функция использует -pi / 2: pi / 2, но не должно быть реальной разницы?
оспинатор
Сразу же, диапазон не должен иметь значения. (Можете ли вы сказать разницу между линией, которая была повернута на 180 градусов?) ОДНАКО, это действительно имеет значение, если вы используете грубое преобразование для алгоритмов коррекции изображения. (Это будет означать разницу между изображением вверх и
вниз
Разве обнаружение края не даст 2 строки, где вы хотите найти только 1? То, что находит центр толстой линии, было бы лучше.
эндолит
@endolith Включено небольшое обсуждение определения краев в исходном посте
CyberMen
«Не нужно изобретать велосипед»? Расскажите об этом моему инструктору ;-)
Натан Шверманн
3
    if image(xi, yj) == 1 

должен быть изменен на

    if image(yj, xi) == 1 

для линий, чтобы работать в dehough

Оспинатор
источник
1

Ответ, использующий 3 цикла, является менее оптимальным и может быть улучшен, здесь более интуитивный подход / точка зрения:

Каждая пара действительных точек устанавливает уникальный a & b of y = ax + b. Линия будет иметь много пар с одинаковым значением a & b, поэтому длинная линия будет представлена ​​в виде пика. Это также верно для полярных r & teta координат.

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

  1. Возьмите каждую пару и вычислите ее a & b. (округлено до дискретных значений)
  2. Перейти к определенному месту в массиве и добавить 1.

Длинная линия -> много пар с одинаковыми а, б.
Спорадические точки -> маленький подсчет в определенных клетках -> больше похоже на беспорядок.


Другой способ взглянуть на это с радонской / проективной точки зрения.

  • Линия будет сильно проецироваться на перпендикулярную «линию сбора», поэтому она будет иметь высокий балл.
  • Если угол между линией и «линией сбора» не равен 90 град, или линия сбора не собирает все точки линии, спроецированные в эту «линию сбора», будет более низкий балл.
Илан Синай
источник