예제 #1
0
def feat_desc(img, x, y):
    N = x.size
    descs = np.zeros((64, N))
    edges = filters.sobel(img)

    for i in range(N):
        x_temp = np.arange(x[i] - 19, x[i] + 21, 1)
        x_i = np.tile(x_temp, (40, 1))
        y_temp = np.arange(y[i] - 19, y[i] + 21, 1)
        y_temp = y_temp.reshape(-1, 1)
        y_i = np.tile(y_temp, (1, 40))
        interp = interp2(edges, x_i, y_i)
        final = np.zeros((320, 5))
        final[0:40, 0:5] = interp[0:40, 0:5]
        final[40:80, 0:5] = interp[0:40, 5:10]
        final[80:120, 0:5] = interp[0:40, 10:15]
        final[120:160, 0:5] = interp[0:40, 15:20]
        final[160:200, 0:5] = interp[0:40, 20:25]
        final[200:240, 0:5] = interp[0:40, 25:30]
        final[240:280, 0:5] = interp[0:40, 30:35]
        final[280:320, 0:5] = interp[0:40, 35:40]
        final = final.reshape((64, 25))
        final_max = np.amax(final, axis=1)
        descs_i = preprocessing.scale(final_max)
        descs[0:64, i:i + 1] = descs_i.reshape((64, 1))
    return descs
예제 #2
0
def estimateFeatureTranslation(startX, startY, Ix, Iy, img1, img2):
    I_gray_1, I_gray_2 = rgb2gray(img1), rgb2gray(img2)
    X_old, Y_old = generatePatch(startX, startY)
    X_old, Y_old = X_old.astype(np.int32), Y_old.astype(np.int32)
    Ix_temp, Iy_temp = Ix[Y_old, X_old], Iy[Y_old, X_old]
    x0, y0 = startX, startY
    min_error = 999999
    error_thresh = 1

    iteration = 5
    for i in range(iteration):
        X_new, Y_new = generatePatch(x0, y0)
        old_coor = np.array((x0, y0)).reshape(-1, 1)
        It_temp = interp2(I_gray_2, X_new, Y_new) - I_gray_1[Y_old, X_old]
        error = np.linalg.norm(It_temp)

        if error < min_error:
            min_error = error
            newX, newY = x0, y0
            if error < error_thresh:
                break

        A = np.hstack((Ix_temp.reshape(-1, 1), Iy_temp.reshape(-1, 1)))
        b = -It_temp.reshape(-1, 1)
        flow_temp = np.linalg.solve(np.dot(A.T, A), np.dot(A.T, b))
        new_coor = old_coor + flow_temp
        x0, y0 = new_coor[0, 0], new_coor[1, 0]

    return newX, newY
def estimateAllTranslation(startXs, startYs, origXs, origYs, img1, img2, bbox,
                           params):
    import numpy as np
    from helpers import rgb2gray
    from helpers import interp2
    from scipy import signal
    from calculateError import calculateError

    # ---------- Part 1: Setup ---------- #

    # Get images computed to grayscale
    # For now I'm going to pad the images symmetrically to get W for edges and corners
    # It will just be important to remember that padding's there when solving for pixel locations
    window = 11
    pad = int((window - 1) / 2)

    # Blur the images to get better optical flow results
    Gx = signal.gaussian(window, 1.4).reshape(1, window)
    Gy = signal.gaussian(window, 1.4).reshape(window, 1)
    gray1 = signal.convolve2d(rgb2gray(img1), Gx, mode="full", boundary="symm")
    gray1 = signal.convolve2d(gray1, Gy, mode="full", boundary="symm")
    gray2 = signal.convolve2d(rgb2gray(img2), Gx, mode="full", boundary="symm")
    gray2 = signal.convolve2d(gray2, Gy, mode="full", boundary="symm")

    # Pull out parameters for looping
    F = len(startXs)

    # Initialize our outputs
    newXs = np.zeros(F, dtype=object)
    newYs = np.zeros(F, dtype=object)

    # Calculate the gradients
    kx = np.array([[1, -1]])
    ky = np.array([[1], [-1]])
    Ix = signal.convolve2d(gray1, kx, mode="same")
    Iy = signal.convolve2d(gray1, ky, mode="same")

    # ---------- Part 2: Caluclate the feature translations ---------- #

    # Use these gradients to find the new locations of the feature points
    # I'm not going to put this into a second function to reduce runtime
    A = np.zeros((window**2, 2))
    b = np.zeros((window**2, 1))

    # Iterate for each bounding box as necessary
    for i in range(F):
        error = np.nan_to_num(np.Inf)
        min_error = error.copy()
        iters = 0

        tempOrigXs = np.copy(origXs[i])
        tempOrigYs = np.copy(origYs[i])

        # Run for a max of 5 iterations or until the average squared distance between ea feat pt value is less than 5k
        while error > 5000 and iters < 5:
            N = len(startXs[i])
            potXs = np.zeros(N)
            potYs = np.zeros(N)

            It = gray2 - gray1
            iters += 1
            for j in range(N):

                # Get our feature location
                fx = startXs[i][j]
                fy = startYs[i][j]

                # Generate a meshgrid for interpolating
                meshx, meshy = np.meshgrid(np.arange(window),
                                           np.arange(window))
                meshx = meshx + fx
                meshy = meshy + fy

                # Build A and b from A*[u; v] = b centered around the feature location
                A[:, 0] = interp2(Ix, meshx, meshy).reshape(
                    window**2
                )  # Ix[fy - pad: fy + pad + 1, fx - pad: fx + pad + 1].reshape(window**2)
                A[:, 1] = interp2(Iy, meshx, meshy).reshape(
                    window**2
                )  # Iy[fy - pad: fy + pad + 1, fx - pad: fx + pad + 1].reshape(window**2)
                b[:, 0] = interp2(It, meshx, meshy).reshape(
                    window**2
                )  # It[fy - pad: fy + pad + 1, fx - pad: fx + pad + 1].reshape(window**2)

                # Solve for [u; v]
                try:
                    translation = np.matmul(
                        np.matmul(np.linalg.inv(np.matmul(A.T, A)), A.T), -b)
                except np.linalg.LinAlgError:
                    translation = np.array([0, 0])

                # Save our result into our output
                potXs[j] = startXs[i][j] + translation[0]
                potYs[j] = startYs[i][j] + translation[1]

            # Calculate the error
            error, gray1, indexer, Ix, Iy, potXs, potYs = calculateError(
                startXs[i], startYs[i], potXs, potYs, np.copy(gray1),
                np.copy(gray2), Ix, Iy, np.copy(bbox[i]), params)

            startXs[i] = np.copy(potXs)
            startYs[i] = np.copy(potYs)
            tempOrigXs = tempOrigXs[indexer]
            tempOrigYs = tempOrigYs[indexer]

            # If we did better this time, save the results
            if error < min_error:
                min_error = error.copy()
                newXs[i] = np.copy(potXs)
                newYs[i] = np.copy(potYs)
                origXs[i] = np.copy(tempOrigXs)
                origYs[i] = np.copy(tempOrigYs)

    return newXs, newYs, origXs, origYs
예제 #4
0
def calculateError(startXs, startYs, newXs, newYs, img1, img2, Ix, Iy, box,
                   params):
    import numpy as np
    from helpers import rgb2gray
    from helpers import interp2
    from scipy import signal
    from scipy.optimize import least_squares
    from helpers import inlier_cost_func
    from helpers import warp_image

    # Extract parameters
    max_dist = params[0]
    k1 = params[1]
    k2 = params[2]
    k3 = params[3]
    k4 = params[4]
    pad = 5

    source = rgb2gray(img1)
    target = rgb2gray(img2)
    source_warped = np.copy(source)

    h, w = source.shape

    # Get the boundaries of bounding box
    xmin = max([np.amin(box[:, 0]) - pad, 0])
    xmax = min([np.amax(box[:, 0]) + pad + 1, w])
    ymin = max([np.amin(box[:, 1]) - pad, 0])
    ymax = min([np.amax(box[:, 1]) + pad + 1, h])

    # Outlier handling
    indexer = np.all(np.stack([
        newXs > xmin + pad, newXs < xmax - pad, newYs > ymin + pad,
        newYs < ymax - pad
    ],
                              axis=0),
                     axis=0)
    distances = np.sqrt(
        np.square(newXs - startXs) + np.square(newYs - startYs))
    avg_dist = np.mean(distances)
    std_dist = np.std(distances)
    if avg_dist != 0:
        indexer = np.logical_and(
            indexer,
            np.logical_and(
                distances < min([k1 * avg_dist + k2 * std_dist, max_dist]),
                distances > k3 * avg_dist - k4 * std_dist))

    # Generate vectors of inliers for calculating the transformation
    ux = startXs[indexer]
    uy = startYs[indexer]
    vx = newXs[indexer]
    vy = newYs[indexer]

    # Form our initial and final feature points in homogeneous coordinates
    N = len(ux)
    u = np.stack([ux, uy, np.ones(N)])
    v = np.stack([vx, vy, np.ones(N)])

    # Calculate the transformation via least squares
    T = least_squares(inlier_cost_func,
                      np.identity(3)[:2].reshape(6),
                      args=(u, v))["x"].reshape(2, 3)
    T = np.concatenate((T, np.array([[0, 0, 1]])))
    newXs = np.matmul(T, u)[0]
    newYs = np.matmul(T, u)[1]

    # Warp img1, Ix and Iy based on calculated transformation
    target_area = target[ymin:ymax, xmin:xmax]
    source_area = source[ymin:ymax, xmin:xmax]

    warped_area = warp_image(source, T, xmin, xmax, ymin, ymax)
    source_warped[ymin:ymax, xmin:xmax] = warped_area

    Ix_area = warp_image(Ix, T, xmin, xmax, ymin, ymax)
    Ix[ymin:ymax, xmin:xmax] = Ix_area

    Iy_area = warp_image(Iy, T, xmin, xmax, ymin, ymax)
    Iy[ymin:ymax, xmin:xmax] = Iy_area

    # Calculate the error per feature point
    interpx = np.array([newXs])
    interpy = np.array([newYs])
    values_this = interp2(source_warped, interpx, interpy).reshape(len(newXs))
    values_next = interp2(target, interpx, interpy).reshape(len(newXs))
    error = np.sum(np.square(values_next - values_this)) / len(newXs)

    return error, source_warped, indexer, Ix, Iy, newXs, newYs
예제 #5
0
def generate_warp(size_H, size_W, Tri, A_Inter_inv_set, A_im_set, image):
    # generate x,y meshgrid
    x, y = np.meshgrid(np.arange(size_W), np.arange(size_H))
    x = x.flatten()
    y = y.flatten()
    # all points in img (size_H*size_W, 2) as x,y system
    empty_points = np.array(list(zip(x, y)))
    # print(empty_points)
    assert empty_points.shape == (size_H * size_W, 2)
    # find the tris where these points live in
    find_simplex_tris = Tri.find_simplex(empty_points)
    # compute alpha, beta, gamma
    all_Inter_inv_A = A_Inter_inv_set[find_simplex_tris]
    all_img_A = A_im_set[find_simplex_tris]

    # aug_empty_points = np.hstack((empty_points,np.ones((empty_points.shape[0], 1))))
    alpha = all_Inter_inv_A[:, 0, 0] * empty_points[:, 0].flatten() + \
        all_Inter_inv_A[:, 0, 1] * empty_points[:, 1].flatten() + \
        all_Inter_inv_A[:, 0, 2] * 1

    beta = all_Inter_inv_A[:, 1, 0] * empty_points[:, 0] + \
        all_Inter_inv_A[:, 1, 1] * empty_points[:, 1] + \
        all_Inter_inv_A[:, 1, 2] * 1

    gamma = all_Inter_inv_A[:, 2, 0] * empty_points[:, 0] + \
        all_Inter_inv_A[:, 2, 1] * empty_points[:, 1] + \
        all_Inter_inv_A[:, 2, 2] * 1

    assert beta.size == empty_points[:, 0].flatten().size
    # print(all_Inter_inv_A[:, 2, 0].shape)
    all_x_coor = all_img_A[:, 0, 0] * alpha + \
        all_img_A[:, 0, 1] * beta + \
        all_img_A[:, 0, 2] * gamma

    all_y_coor = all_img_A[:, 1, 0] * alpha + \
        all_img_A[:, 1, 1] * beta + \
        all_img_A[:, 1, 2] * gamma

    # analytical result
    all_z_coor = np.ones(beta.size)

    all_x_coor_regularized = all_x_coor / all_z_coor
    all_y_coor_regularized = all_y_coor / all_z_coor

    # generate warp img
    generated_pic = np.zeros((size_H, size_W, 3), dtype=np.uint8)

    generated_pic[:, :, 0] = np.reshape(
        interp2(image[:, :, 0], all_x_coor_regularized,
                all_y_coor_regularized), [size_H, size_W])
    generated_pic[:, :, 1] = np.reshape(
        interp2(image[:, :, 1], all_x_coor_regularized,
                all_y_coor_regularized), [size_H, size_W])
    generated_pic[:, :, 2] = np.reshape(
        interp2(image[:, :, 2], all_x_coor_regularized,
                all_y_coor_regularized), [size_H, size_W])

    # LOOP VERSION: SLOW
    #
    #
    # # generate a empty matrix to store the warp img
    # generated_pic = np.zeros((size_H, size_W, 3), dtype=np.uint8)
    #
    # # go through every point's coor in the inter-generated-pic
    # for i in np.arange(size_H):
    #       for j in np.arange(size_W):
    #             # find its belonging triangle,
    #             # find_simplex according to x,y system
    #             fea_index = Tri.find_simplex(np.array([i, j]))
    #             # print(fea_index)
    #             # pull out the A_inter_inv matrix of Tri index
    #             A_Inter_inv = A_Inter_inv_set[fea_index, :, :]
    #
    #             # pull out the coor of the point
    #             b_target = np.array([i, j, 1])
    #
    #             # compute the barycentric coor
    #             barycentric = np.dot(A_Inter_inv, b_target)
    #
    #             # pull out the A_im matrix of the Tir index
    #             b_source = np.dot(A_im_set[fea_index, :, :], barycentric)
    #             assert len(b_source) == 3
    #             print(b_source[2])
    #
    #             b_source = b_source/b_source[2]
    #             b_source_map = np.round(b_source).astype(int)[0:2]
    #
    #             generated_pic[i, j, 0] = image[b_source_map[0], b_source_map[1], 0]
    #             generated_pic[i, j, 1] = image[b_source_map[0], b_source_map[1], 1]
    #             generated_pic[i, j, 2] = image[b_source_map[0], b_source_map[1], 2]

    return generated_pic
예제 #6
0
    x1, y1 = xs1, ys1
    x2, y2 = xs2, ys2

    X_old = np.array(
        [[x1 - 1, x1, x1 + 1], [x1 - 1, x1, x1 + 1], [x1 - 1, x1, x1 + 1]],
        dtype=np.int32)
    Y_old = np.array([[0, 0, 0], [1, 1, 1], [2, 2, 2]], dtype=np.int32)
    ix_temp = ix[Y_old, X_old]
    iy_temp = iy[Y_old, X_old]
    for i in range(5):
        X_new = np.array([[x1 - 1, x1, x1 + 1], [x1 - 1, x1, x1 + 1],
                          [x1 - 1, x1, x1 + 1]])
        Y_new = np.array([[0, 0, 0], [1, 1, 1], [2, 2, 2]])
        old_coor = np.array((x1, y1)).reshape(-1, 1)
        it_temp = interp2(i2, X_new, Y_new) - i1[Y_old, X_old]
        error = np.linalg.norm(it_temp)
        A = np.hstack((ix_temp.reshape(-1, 1), iy_temp.reshape(-1, 1)))
        b = -it_temp.reshape(-1, 1)
        flow_temp = np.linalg.solve(np.dot(A.T, A), np.dot(A.T, b))
        new_coor = old_coor + flow_temp
        x1, y1 = new_coor[0, 0], new_coor[1, 0]
    xe1, ye1 = x1, y1
    print("result point 1:", (xe1, ye1))

    X_old = np.array(
        [[x2 - 1, x2, x2 + 1], [x2 - 1, x2, x2 + 1], [x2 - 1, x2, x2 + 1]],
        dtype=np.int32)
    Y_old = np.array([[0, 0, 0], [1, 1, 1], [2, 2, 2]], dtype=np.int32)
    ix_temp = ix[Y_old, X_old]
    iy_temp = iy[Y_old, X_old]
예제 #7
0
def morph_tri(im1, im2, im1_pts, im2_pts, warp_frac, dissolve_frac):
  # TODO: Your code here
  # Tips: use Delaunay() function to get Delaunay triangulation;
  # Tips: use tri.find_simplex(pts) to find the triangulation index that pts locates in.
  dissolve_frac = 1-dissolve_frac
  warp_frac = 1-warp_frac
  images = []
  if im2.shape != im1.shape:
    im2 = Image.fromarray(im2)
    im2 = im2.resize((im1.shape[1],im1.shape[0]))
    im2 = np.asarray(im2)
  imFF = np.zeros(([len(warp_frac),im1.shape[0],im1.shape[1],3]))
  imgc = 0
  for t in warp_frac:
    im_mpts = (t*im1_pts + (1-t)*im2_pts)
    D = Delaunay(im_mpts)
    x = range(im1.shape[0])
    y = range(im1.shape[1])
    xv, yv = np.meshgrid(x, y)
    r = im1.shape[0]
    c = im1.shape[1]
    co_ords = np.zeros([im1.shape[1],im1.shape[0],3])
    co_ords[:,:,0] = yv
    co_ords[:,:,1] = xv
    co_ords[:,:,2] = np.ones(yv.shape)
    points = co_ords.reshape([1,r*c,3])
    triangles = D.find_simplex(points[:,:,:2])
    act_tri = np.transpose(triangles.reshape(co_ords[:,:,0].shape))
    tri_pt = D.simplices
    A_pt = tri_pt[:,0]
    B_pt = tri_pt[:,1]
    C_pt = tri_pt[:,2]
    A_ptc = im_mpts[A_pt]
    B_ptc = im_mpts[B_pt]
    C_ptc = im_mpts[C_pt]
    A_ptc = np.pad(A_ptc,[(0,0),(0,1)],mode = 'constant')
    A_ptc[:,2] = A_ptc[:,2]+1
    B_ptc = np.pad(B_ptc,[(0,0),(0,1)],mode = 'constant')
    B_ptc[:,2] = B_ptc[:,2]+1
    C_ptc = np.pad(C_ptc,[(0,0),(0,1)],mode = 'constant')
    C_ptc[:,2] = C_ptc[:,2]+1
    A_ptc = np.transpose(A_ptc)
    B_ptc = np.transpose(B_ptc)
    C_ptc = np.transpose(C_ptc)
    D1 = np.transpose(A_ptc.copy())
    E1 = np.transpose(B_ptc.copy())
    F1 = np.transpose(C_ptc.copy())
    D12 = D1.reshape([A_ptc.shape[1],3,1])
    E12 = E1.reshape([B_ptc.shape[1],3,1])
    F12 = F1.reshape([C_ptc.shape[1],3,1])
    tri_mat = np.concatenate((D12,E12,F12),axis=2)
    tri_inv = np.linalg.inv(tri_mat)
    tri_inv_ordered = tri_inv[triangles,:,:]
    tri_inv_ordered = tri_inv_ordered[0,:,:,:]
    points1 = points[0,:,:]
    points1 = points.reshape([points.shape[1],3,1])
    BC = np.matmul(tri_inv_ordered,points1)

    As_ptc = im1_pts[A_pt]
    Bs_ptc = im1_pts[B_pt]
    Cs_ptc = im1_pts[C_pt]
    As_ptc = np.pad(As_ptc,[(0,0),(0,1)],mode = 'constant')
    As_ptc[:,2] = As_ptc[:,2]+1
    Bs_ptc = np.pad(Bs_ptc,[(0,0),(0,1)],mode = 'constant')
    Bs_ptc[:,2] = Bs_ptc[:,2]+1
    Cs_ptc = np.pad(Cs_ptc,[(0,0),(0,1)],mode = 'constant')
    Cs_ptc[:,2] = Cs_ptc[:,2]+1
    As_ptc = np.transpose(As_ptc)
    Bs_ptc = np.transpose(Bs_ptc)
    Cs_ptc = np.transpose(Cs_ptc)
    D1s = np.transpose(As_ptc.copy())
    E1s = np.transpose(Bs_ptc.copy())
    F1s = np.transpose(Cs_ptc.copy())
    D12s = D1s.reshape([As_ptc.shape[1],3,1])
    E12s = E1s.reshape([Bs_ptc.shape[1],3,1])
    F12s = F1s.reshape([Cs_ptc.shape[1],3,1])
    tris_mat = np.concatenate((D12s,E12s,F12s),axis=2)
    tris_mat_ordered = tris_mat[triangles,:,:]
    tris_mat_ordered = tris_mat_ordered[0,:,:,:]
    sxyz = np.matmul(tris_mat_ordered,BC)
    sxy = sxyz[:,:2,0]
    sxy = sxy.reshape([im1.shape[1],im1.shape[0],2])
    x_1 = sxy[:,:,0]
    y_1 = sxy[:,:,1]
    im1R = interp2(im1[:,:,0],x_1,y_1)
    im1G = interp2(im1[:,:,1],x_1,y_1)
    im1B = interp2(im1[:,:,2],x_1,y_1)

    At_ptc = im2_pts[A_pt]
    Bt_ptc = im2_pts[B_pt]
    Ct_ptc = im2_pts[C_pt]
    At_ptc = np.pad(At_ptc,[(0,0),(0,1)],mode = 'constant')
    At_ptc[:,2] = At_ptc[:,2]+1
    Bt_ptc = np.pad(Bt_ptc,[(0,0),(0,1)],mode = 'constant')
    Bt_ptc[:,2] = Bt_ptc[:,2]+1
    Ct_ptc = np.pad(Ct_ptc,[(0,0),(0,1)],mode = 'constant')
    Ct_ptc[:,2] = Ct_ptc[:,2]+1
    At_ptc = np.transpose(At_ptc)
    Bt_ptc = np.transpose(Bt_ptc)
    Ct_ptc = np.transpose(Ct_ptc)
    D1t = np.transpose(At_ptc.copy())
    E1t = np.transpose(Bt_ptc.copy())
    F1t = np.transpose(Ct_ptc.copy())
    D12t = D1t.reshape([At_ptc.shape[1],3,1])
    E12t = E1t.reshape([Bt_ptc.shape[1],3,1])
    F12t = F1t.reshape([Ct_ptc.shape[1],3,1])
    trit_mat = np.concatenate((D12t,E12t,F12t),axis=2)
    trit_mat_ordered = trit_mat[triangles,:,:]
    trit_mat_ordered = trit_mat_ordered[0,:,:,:]
    txyz = np.matmul(trit_mat_ordered,BC)
    txy = txyz[:,:2,0]
    txy = txy.reshape([im1.shape[1],im1.shape[0],2])
    x_2 = txy[:,:,0]
    y_2 = txy[:,:,1]
    im2R = interp2(im2[:,:,0],x_2,y_2)
    im2G = interp2(im2[:,:,1],x_2,y_2)
    im2B = interp2(im2[:,:,2],x_2,y_2)

    imFR = (dissolve_frac[imgc]*im1R + (1-dissolve_frac[imgc])*im2R).T
    imFG = (dissolve_frac[imgc]*im1G + (1-dissolve_frac[imgc])*im2G).T
    imFB = (dissolve_frac[imgc]*im1B + (1-dissolve_frac[imgc])*im2B).T
    imF = im1.copy()
    imF[:,:,0] = imFR
    imF[:,:,1] = imFG
    imF[:,:,2] = imFB
    # plt.imshow(imF)
    # plt.show()
    imFF[imgc,:,:,0] = imFR
    imFF[imgc,:,:,1] = imFG
    imFF[imgc,:,:,2] = imFB
    images.append(imF)
    imgc = imgc +1
  morphed_im = imFF
  io.mimsave('Morph.gif', images, duration = 0.05)
  # print(morphed_im.shape)
  return morphed_im
예제 #8
0
def findStuff(xx, yy, img, pts_avg, pts_orig, tri, tri_arr):
    corr_tri = tri_arr[yy * 300 + xx]
    trig_pts_avg = pts_avg[tri.simplices]
    trig_pts_orig = pts_orig[tri.simplices]

    Ax_avg = trig_pts_avg[corr_tri, 0, 0]
    Bx_avg = trig_pts_avg[corr_tri, 1, 0]
    Cx_avg = trig_pts_avg[corr_tri, 2, 0]
    Ay_avg = trig_pts_avg[corr_tri, 0, 1]
    By_avg = trig_pts_avg[corr_tri, 1, 1]
    Cy_avg = trig_pts_avg[corr_tri, 2, 1]

    Ax_orig = trig_pts_orig[corr_tri, 0, 0]
    Bx_orig = trig_pts_orig[corr_tri, 1, 0]
    Cx_orig = trig_pts_orig[corr_tri, 2, 0]
    Ay_orig = trig_pts_orig[corr_tri, 0, 1]
    By_orig = trig_pts_orig[corr_tri, 1, 1]
    Cy_orig = trig_pts_orig[corr_tri, 2, 1]

    ones = np.zeros((300, 300))
    ones.fill(1)
    ones_horiz = np.zeros((1, 90000))
    ones_horiz.fill(1)

    Ax_avg_flat = Ax_avg.flatten()
    Bx_avg_flat = Bx_avg.flatten()
    Cx_avg_flat = Cx_avg.flatten()
    Ay_avg_flat = Ay_avg.flatten()
    By_avg_flat = By_avg.flatten()
    Cy_avg_flat = Cy_avg.flatten()

    Ax_orig_flat = Ax_orig.flatten()
    Bx_orig_flat = Bx_orig.flatten()
    Cx_orig_flat = Cx_orig.flatten()
    Ay_orig_flat = Ay_orig.flatten()
    By_orig_flat = By_orig.flatten()
    Cy_orig_flat = Cy_orig.flatten()

    # big fat chunk to get Avg into 90000 * 3 * 3 matrix
    tempABCx = np.vstack((Ax_avg_flat, Bx_avg_flat, Cx_avg_flat))
    tempx = tempABCx.T
    tempx = np.vsplit(tempx, 90000)
    tempx = np.hstack(tempx)
    tempx = np.squeeze(tempx, axis=0)
    tempABCy = np.vstack((Ay_avg_flat, By_avg_flat, Cy_avg_flat))
    tempy = tempABCy.T
    tempy = np.vsplit(tempy, 90000)
    tempy = np.hstack(tempy)
    tempy = np.squeeze(tempy, axis=0)
    ones_flat = np.zeros(270000, dtype='float64')
    ones_flat.fill(1)
    temp_avg = np.vstack((tempx, tempy, ones_flat))
    temp_avg = np.hsplit(temp_avg, 90000)
    temp_avg = np.vstack(temp_avg)
    temp_avg = np.vsplit(temp_avg, 90000)

    # big fat chunk to get orig into 90000 * 3 * 3 matrix
    tempABCxo = np.vstack((Ax_orig_flat, Bx_orig_flat, Cx_orig_flat))
    tempxo = tempABCxo.T
    tempxo = np.vsplit(tempxo, 90000)
    tempxo = np.hstack(tempxo)
    tempxo = np.squeeze(tempxo, axis=0)
    tempABCyo = np.vstack((Ay_orig_flat, By_orig_flat, Cy_orig_flat))
    tempyo = tempABCyo.T
    tempyo = np.vsplit(tempyo, 90000)
    tempyo = np.hstack(tempyo)
    tempyo = np.squeeze(tempyo, axis=0)
    temp_o = np.vstack((tempxo, tempyo, ones_flat))
    temp_o = np.hsplit(temp_o, 90000)
    temp_o = np.vstack(temp_o)
    temp_o = np.vsplit(temp_o, 90000)

    xx_flat = xx.flatten()
    yy_flat = yy.flatten()
    ones_flat_2 = np.zeros(90000, dtype='float64')
    ones_flat_2.fill(1)
    xy1_stack = np.vstack((xx_flat, yy_flat, ones_flat_2))
    xy1 = np.hsplit(xy1_stack, 90000)
    xy1 = np.vstack(xy1)
    xy1 = np.vsplit(xy1, 90000)

    solutiontMtx = np.linalg.solve(temp_avg, xy1)

    solution_pts = np.matmul(temp_o, solutiontMtx)
    solution_pts = np.squeeze(solution_pts, axis=2)
    solution_pts = np.hsplit(solution_pts, 3)
    sol_x = solution_pts[0]
    sol_y = solution_pts[1]
    sol_x = sol_x.flatten()
    sol_y = sol_y.flatten()
    sol_x_r = sol_x.reshape((300, 300))
    sol_y_r = sol_y.reshape((300, 300))

    img_r = img[:, :, 0]
    img_g = img[:, :, 1]
    img_b = img[:, :, 2]
    im1_morph_r = interp2(img_r, sol_x_r, sol_y_r)
    im1_morph_g = interp2(img_g, sol_x_r, sol_y_r)
    im1_morph_b = interp2(img_b, sol_x_r, sol_y_r)

    return im1_morph_r, im1_morph_g, im1_morph_b
예제 #9
0
def morph_tri(im1, im2, im1_pts, im2_pts, warp_frac, dissolve_frac):

  # Tips: use Delaunay() function to get Delaunay triangulation;
  # Tips: use tri.find_simplex(pts) to find the triangulation index that pts locates in.

  num_of_frames = warp_frac.shape[0]
  row, col, ch = im1.shape
  # create meshgrid of x,y coordinate
  x, y = np.meshgrid(np.arange(col), np.arange(row))
  y = y.flatten()
  x = x.flatten()
  # create pixel coordinate in (x,y)
  pixel = np.stack((x,y), axis=1)
  # initialize morphing image
  morph_im = np.zeros([num_of_frames, row, col, ch], dtype='uint8')
  warp_src = np.zeros([num_of_frames, row, col, ch], dtype='uint8')
  warp_trg = np.zeros([num_of_frames, row, col, ch], dtype='uint8')

  for i in range(num_of_frames):
    # find interpolated points for Delaunay triangulation
    interp_pts = (1 - warp_frac[i]) * im1_pts + warp_frac[i] * im2_pts
    tri = Delaunay(interp_pts)
    # find the triangulation index that interp_pts locates in
    location = tri.find_simplex(pixel)
    # location = location.reshape(row, col)

    for j in range(np.shape(tri.simplices)[0]):
      # loop through every Delaunay triangles
      coor = pixel[np.where(location == j)]  # pixels that belongs to triangle j
      x = coor[:,0]
      y = coor[:,1]
      pixel_coor = np.row_stack((x, y, np.ones(x.shape[0])))

      # vertices of Delaunay triangles
      vertices = interp_pts[tri.simplices[j]]
      vertices = np.transpose(vertices)
      vertices = np.row_stack((vertices, np.ones([1,3])))
      inv_vertices = np.linalg.inv(vertices)

      # barycentric coordinates for each pixel
      bary_coor = np.dot(inv_vertices, pixel_coor)

      # vertices of Delaunay triangles from source picture
      vertices_src = im1_pts[tri.simplices[j]]
      vertices_src = np.transpose(vertices_src)
      vertices_src = np.row_stack((vertices_src, np.ones([1, 3])))
      source_coor = np.dot(vertices_src, bary_coor)

      # vertices of Delaunay triangles from target picture
      vertices_trg = im2_pts[tri.simplices[j]]
      vertices_trg = np.transpose(vertices_trg)
      vertices_trg = np.row_stack((vertices_trg, np.ones([1, 3])))
      target_coor = np.dot(vertices_trg, bary_coor)

      # interpolate through every pixel in source and target
      for k in range(ch):
        warp_src[i, y, x, k] = interp2(im1[:, :, k], source_coor[0, :], source_coor[1, :])
        warp_trg[i, y, x, k] = interp2(im2[:, :, k], target_coor[0, :], target_coor[1, :])

      morph_im[i, :, :, :] = (1-dissolve_frac[i]) * warp_src[i,:,:,:] + dissolve_frac[i] * warp_trg[i,:,:,:]

  # pixel value should be between [0,255]
  morph_im = np.clip(morph_im, 0, 255)

  return morph_im