Example #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
Example #2
0
def find_G_k(M_hat):

    K = M_hat.shape[1] / 3
    F = M_hat.shape[0] / 2

    # Get the linear basis that vech(Q_k) should reside in.
    U = find_linear_basis_for_vech_Q_k(M_hat)

    # 2D subspace of vech style.
    B = np.asarray([
        from_vech(U[:, i], 3 * K, 3 * K, sym=True).flatten()
        for i in range(U.shape[1])
    ]).T

    # Coefficients correspond to taking trace.
    from cvxopt import matrix, solvers

    # Calculate the cost vector.
    non_diag = np.where(np.eye(3 * K).flatten() != 1)[0]
    c = B.copy()
    c[non_diag, :] = 0
    c = c.sum(axis=0)

    # This matrix should be positive semi-definite.
    G = [matrix(-B)]
    h = [matrix(np.zeros((3 * K, 3 * K)))]

    # We fix the first row of the recovered M_hat to have unit length
    # which avoids the trivial solution.
    A = np.dot(vc(M_hat[0], M_hat[0]), U)[np.newaxis, :].copy()
    A = matrix(A)
    b = matrix([[1.0]])

    # Disable progress reporting in solver.
    solvers.options['show_progress'] = False

    # Solve the sdp using cvxopt
    sol = solvers.sdp(matrix(c), Gs=G, hs=h, A=A, b=b)

    # Extract the solution.
    x = np.asarray(sol['x'])

    # Upgrade to vec(Q_k)
    y = np.dot(B, x)

    # And reshape to Q_k
    Q_k = y.reshape((3 * K, 3 * K))

    # Factor into G_k
    Q_k_U, Q_k_s, Q_k_V = np.linalg.svd(Q_k)
    G_k = Q_k_U[:, :3] * np.sqrt(Q_k_s)[np.newaxis, :3]

    # Squared residual objective function as defined in Dai2012.
    def f(g_k):
        G_k = g_k.reshape(3 * K, 3)
        M_k = np.dot(M_hat, G_k)
        M_kx = M_k[0::2]
        M_ky = M_k[1::2]
        term1 = np.square(1 - (M_kx * M_kx).sum(axis=-1) /
                          (M_ky * M_ky).sum(axis=-1))
        term2 = np.square(2 * (M_ky * M_kx).sum(axis=-1) /
                          (M_ky * M_ky).sum(axis=-1))
        err = np.sum(term1 + term2)
        return err

    # Minimize this function with LBFGS
    from scipy.optimize import fmin_l_bfgs_b
    rc = fmin_l_bfgs_b(f, G_k.flatten(), approx_grad=True)
    G_k = rc[0].reshape(3 * K, 3)

    return G_k
Example #3
0
def find_G_k(M_hat):
    
    K = M_hat.shape[1]/3
    F = M_hat.shape[0]/2

    # Get the linear basis that vech(Q_k) should reside in.
    U = find_linear_basis_for_vech_Q_k(M_hat)

    # 2D subspace of vech style.
    B = np.asarray([from_vech(U[:,i], 3*K, 3*K, sym=True).flatten() for i in range(U.shape[1])]).T
    
    # Coefficients correspond to taking trace.
    from cvxopt import matrix, solvers
    
    # Calculate the cost vector.
    non_diag = np.where(np.eye(3*K).flatten()!=1)[0]
    c = B.copy()
    c[non_diag,:] = 0
    c = c.sum(axis=0)

    # This matrix should be positive semi-definite.    
    G = [matrix(-B)]
    h = [matrix(np.zeros((3*K,3*K)))]

    # We fix the first row of the recovered M_hat to have unit length
    # which avoids the trivial solution.
    A = np.dot(vc(M_hat[0], M_hat[0]), U)[np.newaxis,:].copy()
    A = matrix(A)
    b = matrix([[1.0]])
    
    # Disable progress reporting in solver.
    solvers.options['show_progress'] = False
    
    # Solve the sdp using cvxopt
    sol = solvers.sdp(matrix(c), Gs = G, hs = h, A = A, b = b)
    
    # Extract the solution.
    x = np.asarray(sol['x'])
    
    # Upgrade to vec(Q_k)
    y = np.dot(B, x)

    # And reshape to Q_k
    Q_k = y.reshape((3*K, 3*K))
    
    # Factor into G_k
    Q_k_U, Q_k_s, Q_k_V = np.linalg.svd(Q_k)
    G_k = Q_k_U[:,:3] * np.sqrt(Q_k_s)[np.newaxis,:3]
    
    # Squared residual objective function as defined in Dai2012.
    def f(g_k):
        G_k = g_k.reshape(3*K, 3)
        M_k = np.dot(M_hat, G_k)
        M_kx = M_k[0::2]
        M_ky = M_k[1::2]
        term1 = np.square(1 - (M_kx * M_kx).sum(axis=-1)/(M_ky*M_ky).sum(axis=-1 )) 
        term2 = np.square(2*(M_ky*M_kx).sum(axis=-1)/(M_ky*M_ky).sum(axis=-1))
        err = np.sum(term1 + term2)
        return err

    # Minimize this function with LBFGS
    from scipy.optimize import fmin_l_bfgs_b
    rc = fmin_l_bfgs_b(f, G_k.flatten(), approx_grad=True)        
    G_k = rc[0].reshape(3*K,3)
    
    return G_k