Все примитивы искомого типа (например, окружности, прямые, треугольники и т.п.) описываются уравнением:
f(x, y, p) = 0
где
x, y — координаты [граничного] пикселя,
p — набор параметров (вектор, обычно вещественный), с изменением которого получаются разные примитивы.
Алгоритм:
1 Строится ассоциативный массив А (“аккумулятор”), размерность которого равна количеству элементов в p. В начале массив полностью состоит из нулей (или просто пуст).
○ Например, для прямой y = kx + b нужно использовать двумерный массив, так как имеются два неизвестных параметра: p1 = k и p2 = b. Два измерения массива А соответствуют различным значениям параметров k и b.
2 Для каждой точки <и её соседей> алгоритм определяет, достаточен ли вес границы в этой точке. Если да, то вычисляются параметры всех возможных примитивов, проходящих через эту точку в заданном направлении (используем направление градиента), и увеличиваются соответствующие этим параметрам значения в ячейках аккумулятора.
3 Среди значений массива А находятся те, которые превосходят некоторый порог. Соответствующие им параметры p определяют искомые примитивы.
Замечания (Босик Босикович)
● С математической точки зрения, множество параметров p может быть бесконечным (например, через одну точку можно провести бесконечно много прямых), поэтому в практической реализации потребуется сделать это множество ограниченным и дискретным.
● Возможно, на третьем шаге перед поиском максимумов придётся сначала сгладить (“размыть”) массив p.
Случай отрезков
Ищем отрезки, которые начинаются в (0,0). Для каждого пикселя изображения смотрим, если значение больше некоторого порога, то он потенциально лежит на отрезке, который заканчивается в (a,b). Увеличиваем все элементы массива А, которые соответствуют прямым, через которые может проходить данный пиксель. В результате те значения (a,b), для которых в матрице A находятся значения, большие некоторого порога, будут характеризовать самые вероятные примитивы.
Какое уравнение лучше использовать для задания прямой?
● y=kx+b — не позволяет описать вертикальную прямую.
● ax+by+c=0 — тут три параметра, много.
● xcosα + ysinα = d — два параметра, нормально. α-угол, d-расстояние. Зная градиент и α, можем найти d.
Проблемы:
● Может быть очень большой массив А
● Эффективность зависит от того, каким образом задано уравнение примитива, т.е. сколько параметров в векторе р.
● Для одного (x,y) находим множество (a,b)
Случай окружности
Окружность задается параметрами (a,b,r): (a, b) — центр, r — радиус.
Находим градиент в граничной точке. Его направление совпадает с направлением r, значит на этой прямой где-то лежит центр окружности. Перебираем все возможные значения радиуса, получаем набор значений (a,b,r) и увеличиваем элементы массива А, расположенные по этим координатам.