Ejemplo n.º 1
0
def factor(W):
    """
    This implements rigid factorization as described in
    
    Tomasi, C. & Kanade, T. "Shape and motion from image streams under
    orthography: a factorization method International Journal of Computer
    Vision, 1992
    """
    
    F = W.shape[0]/2
    N = W.shape[1]
    
    # Center W
    T = W.mean(axis=1)
    W = W - T[:, np.newaxis]

    # Factor W
    M_hat, B_hat = factor_matrix(W, J=3)

    # Where we will build the linear system.
    A = np.zeros((3*F, 6))
    b = np.zeros((3*F,))

    for f in range(F):
        
        # Extract the two rows.
        x_f, y_f = M_hat[f*2:f*2+2]
        
        # Both rows must have unit length.
        A[f*3] = util.vc(x_f, x_f)
        b[f*3] = 1.0
        A[f*3+1] = util.vc(y_f,y_f)
        b[f*3+1] = 1.0
        
        # And be orthogonal.
        A[f*3+2] = util.vc(x_f - y_f, x_f + y_f)

    # Recovec vech(Q) and Q
    vech_Q = np.linalg.lstsq(A, b)[0]
    Q = util.from_vech(vech_Q, 3, 3, sym=True)

    # Factor out G recovery matrix
    G, Gt = factor_matrix(Q)
    
    # Upgrade M and B.
    M = np.dot(M_hat, G)
    B = np.linalg.solve(G, B_hat)
    
    # Find actual rotations matrices.
    Rs = np.zeros((F, 3, 3))
    Rs[:,:2] = M.reshape(F,2,3)
    Rs[:,2] = util.normed(np.cross(Rs[:,0], Rs[:,1], axis=-1))

    # And 3D translations.
    Ts = np.zeros((F,3))
    Ts[:,:2] = T.reshape(F,2)
    
    model = BasisShapeModel(Rs, Bs = B[np.newaxis,:,:], Ts = Ts)

    return model
Ejemplo n.º 2
0
def generate_rotation_from_optical_axis(D, safety_checks=False):
    """
    D -- a Fx3 vector of directions.
    
    returns R so that
    Rd = FxN vectors of [0 0 1]
    """

    assert D.ndim == 2 and D.shape[1] == 3

    F = D.shape[0]

    # Space for the rotations.
    R = np.zeros((F, 3, 3))

    # Put the D vectors along the Z axis.
    R[:, 2, :] = normed(D)

    # Make x direction orthogonal in the y=0 plane.
    R[:, 0, 0] = R[:, 2, 2]
    R[:, 0, 2] = -R[:, 2, 0]
    R[:, 0, :] = normed(R[:, 0, :], axis=-1)

    # Make the y direction the cross product.
    # Negation makes this a rotation instead of a reflection.
    R[:, 1, :] = -np.cross(R[:, 0, :], R[:, 2, :], axis=-1)

    if safety_checks:
        for f in range(F):
            if np.linalg.matrix_rank(R[f]) != 3:
                raise Exception("Low rank.")
            if np.linalg.det(R[f]) < 0:
                # Flip one of the rows signs to change this reflection to a rotation matrix.
                R[f, 0, :] *= -1

    return R
Ejemplo n.º 3
0
def generate_rotation_from_optical_axis(D, safety_checks=False):
    """
    D -- a Fx3 vector of directions.
    
    returns R so that
    Rd = FxN vectors of [0 0 1]
    """

    assert D.ndim == 2 and D.shape[1] == 3

    F = D.shape[0]

    # Space for the rotations.
    R = np.zeros((F, 3, 3))

    # Put the D vectors along the Z axis.
    R[:, 2, :] = normed(D)

    # Make x direction orthogonal in the y=0 plane.
    R[:, 0, 0] = R[:, 2, 2]
    R[:, 0, 2] = -R[:, 2, 0]
    R[:, 0, :] = normed(R[:, 0, :], axis=-1)

    # Make the y direction the cross product.
    # Negation makes this a rotation instead of a reflection.
    R[:, 1, :] = -np.cross(R[:, 0, :], R[:, 2, :], axis=-1)

    if safety_checks:
        for f in range(F):
            if np.linalg.matrix_rank(R[f]) != 3:
                raise Exception("Low rank.")
            if np.linalg.det(R[f]) < 0:
                # Flip one of the rows signs to change this reflection to a rotation matrix.
                R[f, 0, :] *= -1

    return R
Ejemplo n.º 4
0
def Rs_from_M_k(M_k):
    """Estimates rotations from a column triple of M."""

    n_frames = M_k.shape[0] / 2

    # Estimate scales of each rotation matrix by averaging norms of two rows.
    scales = .5 * (norm(M_k[0::2], axis=1) + norm(M_k[1::2], axis=1))

    # Rescale to be close to rotation matrices.
    R = M_k.reshape(n_frames, 2, 3) / scales[:, np.newaxis, np.newaxis]
    Rs = []

    # Upgrade to real rotations.
    for f in range(n_frames):
        Rx = R[f, 0]
        Ry = R[f, 1]
        Rz = normed(np.cross(Rx, Ry))
        U, s, Vh = np.linalg.svd(np.asarray([Rx, Ry, Rz]))
        Rs.append(np.dot(U, Vh))

    return np.asarray(Rs)
Ejemplo n.º 5
0
def Rs_from_M_k(M_k):
    """Estimates rotations from a column triple of M."""
    
    n_frames = M_k.shape[0]/2
    
    # Estimate scales of each rotation matrix by averaging norms of two rows.
    scales = .5 * (norm(M_k[0::2], axis=1) + norm(M_k[1::2], axis=1))
    
    # Rescale to be close to rotation matrices.
    R = M_k.reshape(n_frames, 2, 3) / scales[:,np.newaxis,np.newaxis]    
    Rs = []
    
    # Upgrade to real rotations.
    for f in range(n_frames):
        Rx = R[f,0]
        Ry = R[f,1]
        Rz = normed(np.cross(Rx,Ry))
        U,s,Vh = np.linalg.svd(np.asarray([Rx,Ry,Rz]))
        Rs.append(np.dot(U, Vh))
        
    return np.asarray(Rs)