Кластеризация линий на основе начальной и конечной точек без знания количества кластеров - PullRequest
2 голосов
/ 05 октября 2019

Я использую преобразование Хафа для обнаружения линий на футбольном поле. Ниже приведен пример обнаруженных строк (всего 61 строк ):

enter image description here

Все строки являются выходными данными cv2.HoughLinesP -функция и представлена ​​в виде numpy-array в следующем формате:

 [x1, y1, x2, y2]

Есть 3 группы строк, которые я хочу классифицировать;goal_line, goal_area_line и penalty_area_line. Четвертая строка, видимая на изображении, является строкой, вызванной рекламными щитами, и я хочу игнорировать эту. Я борюсь с выбором количества кластеров, k . Это связано с тем, что когда мяч перемещается от средней линии к зоне ворот, мы сначала видим только 1 линию, а именно penalty_area_line. Когда мяч перемещается дальше влево, камера, вероятно, последует, и мы увидим больше линий. Я использую следующее для вычисления градиента и пересечения каждой линии:

def gradient_intercept(x1, y1, x2, y2):
   dx = x2 - x1
   dy = y2 - y1
   radius = math.atan2(-dy, dx)
   radius %= 2 * math.pi
   gradient = -math.degrees(radius)
   if gradient <= -180:
     gradient = gradient + 180
   gradient = gradient + 90
   intercept = y1 - gradient * x1

   return gradient, intercept

Затем я создаю 2d-массив для всех линий и использую его для вычисления матрицы расстояний.

import numpy as np
import scipy.spatial as ss     

def distance_matrix(lines):
   xy = np.empty((0, 2), int)

   try:
      for line in lines:
         for x1, y1, x2, y2 in line:
            gradient, intercept = gradient_intercept(x1, y1, x2, y2)
            xy = np.append(xy, [[0, gradient]], axis=0)
   except Exception as e:
      print(str(e))

   if len(xy) > 2:
      distance_matrix = ss.distance_matrix(xy, xy)

Функция выдает следующий вывод:

[[0.        6.10702413 5.12577724 ... 1.11858265 0.02889456 2.02399679]
[6.10702413 0.         0.98124689 ... 7.22560678 6.07812957 4.08302733]
[5.12577724 0.98124689 0.         ... 6.24435989 5.09688267 3.10178044]
...
[1.11858265 7.22560678 6.24435989 ... 0.         1.14747721 3.14257944]
[0.02889456 6.07812957 5.09688267 ... 1.14747721 0.         1.99510223]
[2.02399679 4.08302733 3.10178044 ... 3.14257944 1.99510223 0.        ]]

Далее мне нужно сгруппировать строки вместе на основе их перехвата. Я предполагаю, что (в случае 4 видимых кластеров)

  intercept_billboards > intercept_goal_line > intercept_goal_area_line > intercept_penalty_area_line

Поиск через SO Я считаю, что DBSCAN подходит для моего случая

from sklearn.cluster import DBSCAN
db = DBSCAN(eps=0.2,min_samples=2)  # minimum of two lines in order to be considered a cluster
db.fit_predict(distance_matrix)
labels = db.labels_
n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)

Осматривая n_clusters_ я иногда вижу значения 5 или 6. Вопрос : Что именно eps? Какой это масштаб? Что может быть подходящим значением в моем случае? Второй вопрос Является ли моя методология (перехватывает -> distance_matrix) правильной?

Заранее спасибо

...