Точечная проекция с использованием перекрестных соотношений после определенного порога становится совершенно неправильной - PullRequest
0 голосов
/ 28 января 2019

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

Это основано на статье Быстрая регистрация 2D-модели для изображения с использованием точек схода для анализа спортивного видео , и я использую эту функцию проекции, учитываяна странице 3. Я также пытался рассчитать результат, используя разные методы (а именно на основе пересечений), но результат тот же:

enter image description here

Должна быть нижняя линия поля, но она должна выйти далеко вправо.

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

def Projection(vanpointH, vanpointV, pointmatch2, pointmatch1):
"""

:param vanpointH:
:param vanpointV:
:param pointmatch1:
:param pointmatch2:
:returns function that takes a single modelpoint as input:
"""
X1 = pointmatch1[1]
point1field = pointmatch1[0]
X2 = pointmatch2[1]
point2field = pointmatch2[0]
point1VP = linecalc.calcLineEquation([[point1field[0], point1field[1], vanpointH[0], vanpointH[1], 1]])
point1VP2 = linecalc.calcLineEquation([[point1field[0], point1field[1], vanpointV[0], vanpointV[1], 1]])
point2VP = linecalc.calcLineEquation([[point2field[0], point2field[1], vanpointV[0], vanpointV[1], 1]])
point2VP2 = linecalc.calcLineEquation([[point2field[0], point2field[1], vanpointH[0], vanpointH[1], 1]])
inters = linecalc.calcIntersections([point1VP, point2VP])[0]
inters2 = linecalc.calcIntersections([point1VP2, point2VP2])[0]

def lambdaFcnX(X, inters):
    # This fcn provides the solution of where the point to be projected is, according to the matching,
    # on the line connecting point1 and vanpointH. Based only on that the cross ratio is the same as in the model field
    return (((X[0] - X1[0]) * (inters[1] - point1field[1])) / ((X2[0] - X1[0]) * (inters[1] - vanpointH[1])))

def lambdaFcnX2(X, inters):
    # This fcn provides the solution of where the point to be projected is, according to the matching,
    # on the line connecting point2 and vanpointH, Based only on that the cross ratio is the same as in the model field
    return (((X[0] - X1[0]) * (point2field[1] - inters[1])) / ((X2[0] - X1[0]) * (point2field[1] - vanpointH[1])))

def lambdaFcnY(X, v1, v2):
    # return (((X[1] - X1[1]) * (np.subtract(v2,v1))) / ((X2[1] - X1[1]) * (np.subtract(v2, vanpointV))))
    return (((X[1] - X1[1]) * (v2[0] - v1[0])) / ((X2[1] - X1[1]) * (v2[0] - vanpointV[0])))

def projection(Point):
    lambdaPointx = lambdaFcnX(Point, inters)
    lambdaPointx2 = lambdaFcnX2(Point, inters2)

    v1 = (np.multiply(-(lambdaPointx / (1 - lambdaPointx)), vanpointH) + np.multiply((1 / (1 - lambdaPointx)),
                                                                                     point1field))

    v2 = (np.multiply(-(lambdaPointx2 / (1 - lambdaPointx2)), vanpointH) + np.multiply((1 / (1 - lambdaPointx2)),
                                                                                       inters2))

    lambdaPointy = lambdaFcnY(Point, v1, v2)

    point = np.multiply(-(lambdaPointy / (1 - lambdaPointy)), vanpointV) + np.multiply((1 / (1 - lambdaPointy)), v1)
    return point

return projection

match1 = ((650,390,1),(2478,615,1))
match2 = ((740,795,1),(2114,1284,1))

vanpoint1 = [-2.07526585e+03, -5.07454315e+02,  1.00000000e+00]
vanpoint2 = [ 5.53599881e+03, -2.08240612e+02,  1.00000000e+00]

model = Projection(vanpoint2,vanpoint1,match2,match1)
model((110,1597))

Предположим, что точки схода

vanpoint1 = [-2.07526585e+03, -5.07454315e+02,  1.00000000e+00]
vanpoint2 = [ 5.53599881e+03, -2.08240612e+02,  1.00000000e+00]

и два совпадения:

match1 = ((650,390,1),(2478,615,1))
match2 = ((740,795,1),(2114,1284,1))

Они работают почти для всех точек, как показано на рисунке.Левая нижняя точка, однако, полностью отключена и получает координаты изображения [ 4.36108177e+04, -1.13418258e+04] Это происходит при понижении с (312,1597);для (312,1597) результат равен [-2.34989787e+08, 6.87155603e+07], где он и должен быть.

Почему он смещается до 4000?Возможно, было бы целесообразно, если бы я рассчитал матрицу камеры, а затем точка была за камерой.Но так как то, что я делаю, на самом деле похоже на оценку гомографии (2D-картирование), я не могу понять это геометрически.Тем не менее, мои знания об этом определенно ограничены.

Редактировать: возможно, это связано с топологией проективной плоскости и что она не ориентируема (охватывает)?Мое знание топологии не то, что должно быть ...

1 Ответ

0 голосов
/ 31 января 2019

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

Геометрически я понял следующее при использовании эквивалентного подхода, где v1 и v2рассчитываются на основе различных точек схода, а я проектирую на основе пересечения линий, соединяющих точки с точками схода.Здесь в какой-то момент эти линии становятся параллельными, и после этого пересечение фактически полностью лежит на другой стороне.И это имеет смысл;Мне потребовалось некоторое время, чтобы понять, что это так.

В приведенном выше коде последнее перекрестное соотношение, называемое lambdapointy, переходит в 1, а после этого выше.Здесь происходит то же самое, но это было проще всего визуализировать на основе пересечений.

Также знаете, как ее решить;это на тот случай, если кто-то еще попробует такой код.

...