0

我正在尝试一个计算机视觉项目来确定足球图像中发生的投影变换。我检测消失点,获得 2 个点匹配,并根据交叉比率计算从模型场点到图像点的投影。这对几乎所有点都非常有效,但对于点(位于相机后面),投影完全错误。你知道为什么以及如何解决这个问题吗?

它基于文章Fast 2D model-to-image registration using vanishing points for sports video analysis,我使用第 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 映射),所以我无法理解这一点。但是,我对此的了解肯定是有限的。

编辑:这可能与投影平面的拓扑结构以及它不可定向(环绕)有关吗?我的拓扑学知识不应该是……

4

1 回答 1

0

好的,想通了。这对其他人可能没有太大意义,但对我来说确实如此(如果有人遇到同样的问题......)

在几何上,我在使用等效方法时实现了以下几点,其中 v1 和 v2 是根据不同的消失点计算的,我根据连接点与消失点的线的交点进行投影。在某些时候,这些线变得平行,然后交叉点实际上完全位于另一侧。这是有道理的;我花了一段时间才意识到它确实如此。

在上面的代码中,最后一个交叉比率,称为 lambdapointy,变为 1 和上面的之后。这里发生了同样的事情,但最容易根据交叉点进行可视化。

也知道怎么解决;这是以防万一其他人尝试这样的代码。

于 2019-01-31T08:45:01.563 回答