Я пытаюсь для проекта компьютерного зрения определить трансформацию проекции, происходящую в изображении футбола.Я определяю точки схода, получаю совпадения в 2 точки и вычисляю проекцию от точек поля модели до точек изображения на основе перекрестных отношений.Это работает очень хорошо почти для всех точек, но для точек (которые находятся за камерой) проекция идет совершенно неправильно.Знаете ли вы, почему и как я могу это исправить?
Это основано на статье Быстрая регистрация 2D-модели для изображения с использованием точек схода для анализа спортивного видео , и я использую эту функцию проекции, учитываяна странице 3. Я также пытался рассчитать результат, используя разные методы (а именно на основе пересечений), но результат тот же:
Должна быть нижняя линия поля, но она должна выйти далеко вправо.
Я также попытался использовать десятичную дробь, чтобы увидеть, была ли это отрицательная ошибка переполнения, но это не имело бы большого смысла для меня, так как тот же результат был обнаружен на 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-картирование), я не могу понять это геометрически.Тем не менее, мои знания об этом определенно ограничены.
Редактировать: возможно, это связано с топологией проективной плоскости и что она не ориентируема (охватывает)?Мое знание топологии не то, что должно быть ...