Esempio n. 1
0
def analogy(img_A, img_BP, config):
    start_time_0 = time.time()

    weights = config['weights']
    sizes = config['sizes']
    rangee = config['rangee']
    params = config['params']
    lr = config['lr']
    if config['use_cuda']:
        device = torch.device('cuda:0')
    else:
        raise NotImplementedError('cpu mode is not supported yet')

    # preparing data
    img_A_tensor = torch.FloatTensor(img_A.transpose(2, 0, 1))
    img_BP_tensor = torch.FloatTensor(img_BP.transpose(2, 0, 1))
    img_A_tensor, img_BP_tensor = img_A_tensor.to(device), img_BP_tensor.to(
        device)

    img_A_tensor = img_A_tensor.unsqueeze(0)
    img_BP_tensor = img_BP_tensor.unsqueeze(0)

    # compute 5 feature maps
    model = VGG19(device=device)
    data_A, data_A_size = model.get_features(img_tensor=img_A_tensor.clone(),
                                             layers=params['layers'])
    data_AP = copy.deepcopy(data_A)
    data_BP, data_B_size = model.get_features(img_tensor=img_BP_tensor.clone(),
                                              layers=params['layers'])
    data_B = copy.deepcopy(data_BP)
    print("Features extracted!")

    for curr_layer in range(5):
        print("\n### current stage: %d - start ###" % (5 - curr_layer))
        start_time_1 = time.time()

        if curr_layer == 0:
            ann_AB = init_nnf(data_A_size[curr_layer][2:],
                              data_B_size[curr_layer][2:])
            ann_BA = init_nnf(data_B_size[curr_layer][2:],
                              data_A_size[curr_layer][2:])
        else:
            ann_AB = upSample_nnf(ann_AB, data_A_size[curr_layer][2:])
            ann_BA = upSample_nnf(ann_BA, data_B_size[curr_layer][2:])

        # blend feature
        Ndata_A, response_A = normalize(data_A[curr_layer])
        Ndata_BP, response_BP = normalize(data_BP[curr_layer])

        data_AP[curr_layer] = blend(response_A, data_A[curr_layer],
                                    data_AP[curr_layer], weights[curr_layer])
        data_B[curr_layer] = blend(response_BP, data_BP[curr_layer],
                                   data_B[curr_layer], weights[curr_layer])

        Ndata_AP, _ = normalize(data_AP[curr_layer])
        Ndata_B, _ = normalize(data_B[curr_layer])

        # NNF search
        print("- NNF search for ann_AB")
        start_time_2 = time.time()
        ann_AB, _ = propagate(ann_AB, ts2np(Ndata_A), ts2np(Ndata_AP),
                              ts2np(Ndata_B), ts2np(Ndata_BP),
                              sizes[curr_layer], params['iter'],
                              rangee[curr_layer])
        print("\tElapse: " +
              str(datetime.timedelta(seconds=time.time() - start_time_2))[:-7])

        print("- NNF search for ann_BA")
        start_time_2 = time.time()
        ann_BA, _ = propagate(ann_BA, ts2np(Ndata_BP), ts2np(Ndata_B),
                              ts2np(Ndata_AP), ts2np(Ndata_A),
                              sizes[curr_layer], params['iter'],
                              rangee[curr_layer])
        print("\tElapse: " +
              str(datetime.timedelta(seconds=time.time() - start_time_2))[:-7])

        if curr_layer >= 4:
            print("### current stage: %d - end | " % (5 - curr_layer) +
                  "Elapse: " +
                  str(datetime.timedelta(seconds=time.time() -
                                         start_time_1))[:-7] + ' ###')
            break

        # using backpropagation to approximate feature
        next_layer = curr_layer + 2

        ann_AB_upnnf2 = upSample_nnf(ann_AB, data_A_size[next_layer][2:])
        ann_BA_upnnf2 = upSample_nnf(ann_BA, data_B_size[next_layer][2:])

        data_AP_np = avg_vote(ann_AB_upnnf2, ts2np(data_BP[next_layer]),
                              sizes[next_layer], data_A_size[next_layer][2:],
                              data_B_size[next_layer][2:])
        data_B_np = avg_vote(ann_BA_upnnf2, ts2np(data_A[next_layer]),
                             sizes[next_layer], data_B_size[next_layer][2:],
                             data_A_size[next_layer][2:])

        data_AP[next_layer] = np2ts(data_AP_np, device)
        data_B[next_layer] = np2ts(data_B_np, device)

        target_BP_np = avg_vote(ann_AB, ts2np(data_BP[curr_layer]),
                                sizes[curr_layer], data_A_size[curr_layer][2:],
                                data_B_size[curr_layer][2:])
        target_A_np = avg_vote(ann_BA, ts2np(data_A[curr_layer]),
                               sizes[curr_layer], data_B_size[curr_layer][2:],
                               data_A_size[curr_layer][2:])

        target_BP = np2ts(target_BP_np, device)
        target_A = np2ts(target_A_np, device)

        print('- deconvolution for feat A\'')
        start_time_2 = time.time()
        data_AP[curr_layer + 1] = model.get_deconvoluted_feat(
            target_BP,
            curr_layer,
            data_AP[next_layer],
            lr=lr[curr_layer],
            iters=400,
            display=False)
        print("\tElapse: " +
              str(datetime.timedelta(seconds=time.time() - start_time_2))[:-7])

        print('- deconvolution for feat B')
        start_time_2 = time.time()
        data_B[curr_layer + 1] = model.get_deconvoluted_feat(
            target_A,
            curr_layer,
            data_B[next_layer],
            lr=lr[curr_layer],
            iters=400,
            display=False)
        print("\tElapse: " +
              str(datetime.timedelta(seconds=time.time() - start_time_2))[:-7])

        # in case of data type inconsistency
        if data_B[curr_layer + 1].type() == torch.cuda.DoubleTensor:
            data_B[curr_layer + 1] = data_B[curr_layer + 1].type(
                torch.cuda.FloatTensor)
            data_AP[curr_layer + 1] = data_AP[curr_layer + 1].type(
                torch.cuda.FloatTensor)

        print("### current stage: %d - end | " % (5 - curr_layer) +
              "Elapse: " +
              str(datetime.timedelta(seconds=time.time() -
                                     start_time_1))[:-7] + ' ###')

    print('\n- reconstruct images A\' and B')
    img_AP = reconstruct_avg(ann_AB, img_BP, sizes[curr_layer],
                             data_A_size[curr_layer][2:],
                             data_B_size[curr_layer][2:])
    img_B = reconstruct_avg(ann_BA, img_A, sizes[curr_layer],
                            data_A_size[curr_layer][2:],
                            data_B_size[curr_layer][2:])

    img_AP = np.clip(img_AP, 0, 255)
    img_B = np.clip(img_B, 0, 255)

    return img_AP, img_B, str(
        datetime.timedelta(seconds=time.time() - start_time_0))[:-7]
Esempio n. 2
0
def analogy(img_A, img_BP, config):
    weights = config['weights']
    sizes = config['sizes']
    rangee = config['rangee']
    use_cuda = config['use_cuda']
    params = config['params']
    lr = config['lr']
    # assert use_cuda==True, "cpu version is not implemented yet. You can modify VGG19.py to make it support CPU if you like."

    # preparing data
    img_A_tensor = torch.FloatTensor(img_A.transpose(2, 0, 1))
    img_BP_tensor = torch.FloatTensor(img_BP.transpose(2, 0, 1))
    if use_cuda:
        img_A_tensor, img_BP_tensor = img_A_tensor.cuda(), img_BP_tensor.cuda()

    img_A_tensor = img_A_tensor.unsqueeze(0)
    img_BP_tensor = img_BP_tensor.unsqueeze(0)

    # compute 5 feature maps
    model = VGG19(use_cuda=use_cuda)
    data_A, data_A_size = model.get_features(
        img_tensor=img_A_tensor.clone(), layers=params['layers'])
    data_AP = copy.deepcopy(data_A)
    data_BP, data_B_size = model.get_features(
        img_tensor=img_BP_tensor.clone(), layers=params['layers'])
    data_B = copy.deepcopy(data_BP)

    for curr_layer in range(5):

        if curr_layer == 0:
            ann_AB = init_nnf(
                data_A_size[curr_layer][2:], data_B_size[curr_layer][2:])
            ann_BA = init_nnf(
                data_B_size[curr_layer][2:], data_A_size[curr_layer][2:])
        else:
            ann_AB = upSample_nnf(ann_AB, data_A_size[curr_layer][2:])
            ann_BA = upSample_nnf(ann_BA, data_B_size[curr_layer][2:])

        # blend feature
        Ndata_A, response_A = normalize(data_A[curr_layer])
        Ndata_BP, response_BP = normalize(data_BP[curr_layer])

        data_AP[curr_layer] = blend(
            response_A, data_A[curr_layer], data_AP[curr_layer], weights[curr_layer])
        data_B[curr_layer] = blend(
            response_BP, data_BP[curr_layer], data_B[curr_layer], weights[curr_layer])

        Ndata_AP, _ = normalize(data_AP[curr_layer])
        Ndata_B, _ = normalize(data_B[curr_layer])

        # NNF search
        ann_AB, _ = propagate(ann_AB, ts2np(Ndata_A), ts2np(Ndata_AP), ts2np(Ndata_B), ts2np(Ndata_BP), sizes[curr_layer],
                              params['iter'], rangee[curr_layer])
        ann_BA, _ = propagate(ann_BA, ts2np(Ndata_BP), ts2np(Ndata_B), ts2np(Ndata_AP), ts2np(Ndata_A), sizes[curr_layer],
                              params['iter'], rangee[curr_layer])

        if curr_layer >= 4:
            break

        # using backpropagation to approximate feature
        next_layer = curr_layer + 2

        ann_AB_upnnf2 = upSample_nnf(ann_AB, data_A_size[next_layer][2:])
        ann_BA_upnnf2 = upSample_nnf(ann_BA, data_B_size[next_layer][2:])

        data_AP_np = avg_vote(ann_AB_upnnf2, ts2np(data_BP[next_layer]), sizes[next_layer], data_A_size[next_layer][2:],
                              data_B_size[next_layer][2:])
        data_B_np = avg_vote(ann_BA_upnnf2, ts2np(data_A[next_layer]), sizes[next_layer], data_B_size[next_layer][2:],
                             data_A_size[next_layer][2:])

        data_AP[next_layer] = np2ts(data_AP_np)
        data_B[next_layer] = np2ts(data_B_np)

        target_BP_np = avg_vote(ann_AB, ts2np(data_BP[curr_layer]), sizes[curr_layer], data_A_size[curr_layer][2:],
                                data_B_size[curr_layer][2:])
        target_A_np = avg_vote(ann_BA, ts2np(data_A[curr_layer]), sizes[curr_layer], data_B_size[curr_layer][2:],
                               data_A_size[curr_layer][2:])

        target_BP = np2ts(target_BP_np)
        target_A = np2ts(target_A_np)

        data_AP[curr_layer+1] = model.get_deconvoluted_feat(target_BP, curr_layer, data_AP[next_layer], lr=lr[curr_layer],
                                                            iters=400, display=False)
        data_B[curr_layer+1] = model.get_deconvoluted_feat(target_A, curr_layer, data_B[next_layer], lr=lr[curr_layer],
                                                           iters=400, display=False)

        if type(data_B[curr_layer + 1]) == torch.DoubleTensor:
            data_B[curr_layer + 1] = data_B[curr_layer +
                                            1].type(torch.FloatTensor)
            data_AP[curr_layer + 1] = data_AP[curr_layer +
                                              1].type(torch.FloatTensor)
        elif type(data_B[curr_layer + 1]) == torch.cuda.DoubleTensor:
            data_B[curr_layer + 1] = data_B[curr_layer +
                                            1].type(torch.cuda.FloatTensor)
            data_AP[curr_layer + 1] = data_AP[curr_layer +
                                              1].type(torch.cuda.FloatTensor)

    img_AP = reconstruct_avg(
        ann_AB, img_BP, sizes[curr_layer], data_A_size[curr_layer][2:], data_B_size[curr_layer][2:])
    img_B = reconstruct_avg(
        ann_BA, img_A, sizes[curr_layer], data_A_size[curr_layer][2:], data_B_size[curr_layer][2:])

    img_AP = np.clip(img_AP/255.0, 0, 1)[:, :, ::-1]
    img_B = np.clip(img_B/255.0, 0, 1)[:, :, ::-1]

    return img_AP, img_B
def deep_image_analogy(A, BP, config):
    alphas = config['alpha']
    nnf_patch_size = config['nnf_patch_size']
    radii = config['radii']
    params = config['params']
    lr = config['lr']

    # preparing data
    img_A_tensor = torch.FloatTensor(A.transpose(2, 0, 1)).cuda()
    img_BP_tensor = torch.FloatTensor(BP.transpose(2, 0, 1)).cuda()
    # fake a batch dimension
    img_A_tensor = img_A_tensor.unsqueeze(0)
    img_BP_tensor = img_BP_tensor.unsqueeze(0)

    # 4.1 Preprocessing Step
    model = VGG19()
    F_A, F_A_size = model.get_features(img_tensor=img_A_tensor.clone(),
                                       layers=params['layers'])
    F_BP, F_B_size = model.get_features(img_tensor=img_BP_tensor.clone(),
                                        layers=params['layers'])

    # Init AP&B 's feature maps with F_A&F_BP
    F_AP = copy.deepcopy(F_A)
    F_B = copy.deepcopy(F_BP)

    #Note that the feature_maps now is in the order of [5,4,3,2,1,input]
    for curr_layer in range(5):

        #ANN init step, coarsest layer is initialized randomly,
        #Other layers is initialized using upsample technique described in the paper
        if curr_layer == 0:
            ann_AB = init_nnf(F_A_size[curr_layer][2:],
                              F_B_size[curr_layer][2:])
            ann_BA = init_nnf(F_B_size[curr_layer][2:],
                              F_A_size[curr_layer][2:])
        else:
            ann_AB = upSample_nnf(ann_AB, F_A_size[curr_layer][2:])
            ann_BA = upSample_nnf(ann_BA, F_B_size[curr_layer][2:])

        # According to Equotion(2), we need to normalize F_A and F_BP
        # response denotes the M in Equotion(6)
        F_A_BAR, response_A = normalize(F_A[curr_layer])
        F_BP_BAR, response_BP = normalize(F_BP[curr_layer])

        # F_AP&F_B is reconstructed according to Equotion(4)
        # Note that we reuse the varibale F_AP here,
        # it denotes the RBprime as is stated in the  Equotion(4) which is calculated
        # at the end of the previous iteration
        F_AP[curr_layer] = blend(response_A, F_A[curr_layer], F_AP[curr_layer],
                                 alphas[curr_layer])
        F_B[curr_layer] = blend(response_BP, F_BP[curr_layer], F_B[curr_layer],
                                alphas[curr_layer])

        # Normalize F_AP&F_B as well
        F_AP_BAR, _ = normalize(F_AP[curr_layer])
        F_B_BAR, _ = normalize(F_B[curr_layer])

        # Run PatchMatch algorithm to get mapping AB and BA
        ann_AB, _ = propagate(ann_AB, ts2np(F_A_BAR), ts2np(F_AP_BAR),
                              ts2np(F_B_BAR), ts2np(F_BP_BAR),
                              nnf_patch_size[curr_layer], params['iter'],
                              radii[curr_layer])
        ann_BA, _ = propagate(ann_BA, ts2np(F_BP_BAR), ts2np(F_B_BAR),
                              ts2np(F_AP_BAR), ts2np(F_A_BAR),
                              nnf_patch_size[curr_layer], params['iter'],
                              radii[curr_layer])

        if curr_layer >= 4:
            break

        # The code below is used to initialize the F_AP&F_B in the next layer,
        # it generates the R_B' and R_A as is stated in Equotion(4)
        # R_B' is stored in F_AP, R_A is stored in F_B

        # using backpropagation to approximate feature

        # About why we add 2 here:
        # https://github.com/msracver/Deep-Image-Analogy/issues/30
        next_layer = curr_layer + 2
        ann_AB_upnnf2 = upSample_nnf(ann_AB, F_A_size[next_layer][2:])
        ann_BA_upnnf2 = upSample_nnf(ann_BA, F_B_size[next_layer][2:])
        F_AP_np = avg_vote(ann_AB_upnnf2, ts2np(F_BP[next_layer]),
                           nnf_patch_size[next_layer],
                           F_A_size[next_layer][2:], F_B_size[next_layer][2:])
        F_B_np = avg_vote(ann_BA_upnnf2, ts2np(F_A[next_layer]),
                          nnf_patch_size[next_layer], F_B_size[next_layer][2:],
                          F_A_size[next_layer][2:])

        # Initialize  R_B' and R_A
        F_AP[next_layer] = np2ts(F_AP_np)
        F_B[next_layer] = np2ts(F_B_np)

        # Warp F_BP using ann_AB, Warp F_A using ann_BA
        target_BP_np = avg_vote(ann_AB, ts2np(F_BP[curr_layer]),
                                nnf_patch_size[curr_layer],
                                F_A_size[curr_layer][2:],
                                F_B_size[curr_layer][2:])
        target_A_np = avg_vote(ann_BA, ts2np(F_A[curr_layer]),
                               nnf_patch_size[curr_layer],
                               F_B_size[curr_layer][2:],
                               F_A_size[curr_layer][2:])

        target_BP = np2ts(target_BP_np)
        target_A = np2ts(target_A_np)

        #LBFGS algorithm to approximate R_B' and R_A
        F_AP[curr_layer + 1] = model.get_deconvoluted_feat(
            target_BP,
            curr_layer,
            F_AP[next_layer],
            lr=lr[curr_layer],
            blob_layers=params['layers'])
        F_B[curr_layer + 1] = model.get_deconvoluted_feat(
            target_A,
            curr_layer,
            F_B[next_layer],
            lr=lr[curr_layer],
            blob_layers=params['layers'])

        if type(F_B[curr_layer + 1]) == torch.DoubleTensor:
            F_B[curr_layer + 1] = F_B[curr_layer + 1].type(torch.FloatTensor)
            F_AP[curr_layer + 1] = F_AP[curr_layer + 1].type(torch.FloatTensor)
        elif type(F_B[curr_layer + 1]) == torch.cuda.DoubleTensor:
            F_B[curr_layer + 1] = F_B[curr_layer + 1].type(
                torch.cuda.FloatTensor)
            F_AP[curr_layer + 1] = F_AP[curr_layer + 1].type(
                torch.cuda.FloatTensor)

    # Obtain the output according to 4.5
    img_AP = reconstruct_avg(ann_AB, BP, nnf_patch_size[curr_layer],
                             F_A_size[curr_layer][2:],
                             F_B_size[curr_layer][2:])
    img_B = reconstruct_avg(ann_BA, A, nnf_patch_size[curr_layer],
                            F_A_size[curr_layer][2:], F_B_size[curr_layer][2:])

    img_AP = np.clip(img_AP / 255.0, 0, 1)[:, :, ::-1]
    img_B = np.clip(img_B / 255.0, 0, 1)[:, :, ::-1]
    return img_AP, img_B