估计给定为世界空间坐标和图像坐标的点位置



我正在尝试使用8个Aruco标记,OpenCV和Python来检测棋盘。标记检测效果很好,但是一旦玩家采取行动,至少一个标记通常会被手臂覆盖。由于仍然可以检测到大多数标记,因此应该可以估计给定其他标记的位置的估计。为了说明我的设置,我链接了一张图片。正确标记点

我第一次预测缺失点的尝试是尝试计算从世界到图像空间的未知过渡矩阵。代表世界空间坐标[1,0,0],[1,50,0],[1,75,0],[1,100,0],[1,0,100],[1,[1,[1,使用0,50],[1,75,100]和[1,100,100]。因此,这些始终以矩阵W的形式知道并表示。标记点的屏幕空间坐标由OpenCV计算,并由矩阵S表示。为了参数,让我们假装未检测到一个标记,需要估算该点。然后,为给定的7点计算从W到S的转换矩阵(即为X求解w * x = s(,并估算了世界空间坐标乘以x的缺失点。问题是x不将x纳入其中透视转换,因此错误地指出了一个估计点。为了说明这一点,在正确检测到所有点的情况下,将第二张图片链接在一起,然后通过投影矩阵X进行投影。 不正确的标记点

python代码的快速片段,该代码显示了X的计算方式并投影了点:

ids = [81,277,939,275,683,677,335,981]
corner_world_coord = {
    683: [1,0,0],
    275: [1,50,0],
    939: [1,75,0],
    81: [1,100,0],
    335: [1,0,100],
    677: [1,50,100],
    277: [1,75,100],
    981: [1,100,100]
}
W = [corner_world_coord[i] for i in ids]
S = [aruco_corners[i] for i in ids]
X, res, _, _ = np.linalg.lstsq(W,S)
estimate = np.zeros(len(ids))
for idx, corner in enumerate(W):
    estimate[idx] = np.dot(corner,X)

x的最小平方错误计算的残差总是等于0。我的问题是,考虑到世界空间和其他多个点的世界空间和屏幕空间坐标,是否有一种方法来计算缺失点的屏幕坐标?

我能够在以下问题下找到解决方案:如何在2D

中绘制透视性校准网格

在这种情况下,从您的图像世界和图像空间中需要4个非共线2D点。IE。从世界坐标中删除其中的,以获得[0,0], [50,0],[75,0],[100,0],[0,100],[50,100],[75,100]和[100,100]。非共线可能不是正确的术语,但是这意味着他们需要创建四边形,并且最多可以允许2点躺在同一条线上。我们称为x1 ... x4的x坐标,y坐标y1 ... y4。我们称为x1p的相应图像空间点的坐标... x4p和y1p ... y4p(p代表prime(。然后在下面的代码中给出了透视图正确过渡矩阵的计算:

def compute_proj_matrix(self, world_points, image_points):
    # compute A * C = B 
    # A is the following 8x8 Matrix:
    # x1   y1     1     0   0    0   -x1*x1'  -y1*x1'
    # 0    0     0    x1   y1   1   -x1*y1'  -y1*y1'
    # x2   y2     1     0   0    0   -x2*x2'  -y2*x2'
    # 0    0     0    x2   y2   1   -x2*y2'  -y2*y2'
    # x3   y3     1     0   0    0   -x3*x3'  -y3*x3'
    # 0    0     0    x3   y3   1   -x3*y3'  -y3*y3'
    # x4   y4     1     0   0    0   -x4*x4'  -y4*x4'
    # 0    0     0    x4   y4   1   -x4*y4'  -y4*y4'
    # B = [x1p,y1p,x2p,y2p,x3p,y3p,x4p,y4p]
    x1,x2,x3,x4 = world_points[:,0]
    y1,y2,y3,y4 = world_points[:,1]
    x1p,x2p,x3p,x4p = image_points[:,0]
    y1p,y2p,y3p,y4p = image_points[:,1]
    A = np.array([
        [x1,y1, 1, 0, 0, 0, -x1*x1p, -y1*x1p],
        [ 0, 0, 0,x1,y1, 1, -x1*y1p, -y1*y1p],
        [x2,y2, 1, 0, 0, 0, -x2*x2p, -y2*x2p],
        [ 0, 0, 0,x2,y2, 1, -x2*y2p, -y2*y2p],
        [x3,y3, 1, 0, 0, 0, -x3*x3p, -y3*x3p],
        [ 0, 0, 0,x3,y3, 1, -x3*y3p, -y3*y3p],
        [x4,y4, 1, 0, 0, 0, -x4*x4p, -y4*x4p],
        [ 0, 0, 0,x4,y4, 1, -x4*y4p, -y4*y4p]])
    B = np.array([x1p,y1p,x2p,y2p,x3p,y3p,x4p,y4p])
    return np.linalg.solve(A,B)

新的映射(在上述情况下,缺少(点由以下方式完成:

def map_point(self, proj_matrix, point):
    x,y = point
    factor = 1.0/(proj_matrix[6] * x + proj_matrix[7] * y + 1.0)
    projected_x = factor * (proj_matrix[0] * x + proj_matrix[1] * y + proj_matrix[2])
    projected_y = factor * (proj_matrix[3] * x + proj_matrix[4] * y + proj_matrix[5])
    return np.array([projected_x,projected_y])

最好在上面链接的问题中最好地检查它的原因和方式,因为坦率地说,我不了解自己,很高兴找到解决方案。

最新更新