Example #1
0
def testBIWI(model,modelin=args.model,outfile=args.out,feature_transform=args.feat_trans):
    if modelin != "":
        model.load_state_dict(torch.load(modelin))
    model.eval()

    # load 3dmm data
    data3dmm = dataloader.SyntheticLoader()
    mu_lm = torch.from_numpy(data3dmm.mu_lm).float()
    lm_eigenvec = torch.from_numpy(data3dmm.lm_eigenvec).float()
    shape = mu_lm
    shape[:,2] = shape[:,2] * -1

    loader = dataloader.BIWILoader()
    seterror_3d = []
    seterror_rel3d = []
    seterror_relf = []
    seterror_2d = []
    for sub in range(len(loader)):
        batch = loader[sub]

        x_cam_gt = batch['x_cam_gt']
        x_w_gt = batch['x_w_gt']
        f_gt = batch['f_gt']
        x_img = batch['x_img']
        x_img_gt = batch['x_img_gt']
        M = x_img_gt.shape[0]

        one  = torch.ones(M,1,68)
        x_img_one = torch.cat([x_img,one],dim=1)

        # run the model
        out, trans, transfeat = model(x_img_one)
        alphas = out[:,:199].mean(0)
        f = torch.relu(out[:,199]).mean()
        K = torch.zeros((3,3)).float()
        K[0,0] = f;
        K[1,1] = f;
        K[2,2] = 1;
        K[0,2] = 320;
        K[1,2] = 240;
        Xc,R,T = util.EPnP(x_img,shape,K)

        # apply 3DMM model from predicted parameters
        reproj_errors2 = util.getReprojError2(x_img,shape,R,T,K)
        reproj_errors3 = util.getReprojError3(x_cam_gt,shape,R,T)
        rel_errors = util.getRelReprojError3(x_cam_gt,shape,R,T)

        reproj_error = reproj_errors2.mean()
        reconstruction_error = reproj_errors3.mean()
        rel_error = rel_errors.mean()
        f_error = torch.abs(f_gt - f) / f_gt

        seterror_2d.append(reproj_error.cpu().data.item())
        seterror_3d.append(reconstruction_error.cpu().data.item())
        seterror_rel3d.append(rel_error.cpu().data.item())
        seterror_relf.append(f_error.cpu().data.item())

        print(f"fgt: {f_gt.mean().item():.3f}  | f_error_rel: {f_error.item():.4f}  | rmse: {reconstruction_error.item():.4f}  | rel rmse: {rel_error.item():.4f}    | 2d error: {reproj_error.item():.4f}")
        #end for

    matdata = {}
    matdata['seterror_2d'] = np.array(seterror_2d)
    matdata['seterror_3d'] = np.array(seterror_3d)
    matdata['seterror_rel3d'] = np.array(seterror_rel3d)
    matdata['seterror_relf'] = np.array(seterror_relf)
    scipy.io.savemat(outfile,matdata)

    print(f"MEAN seterror_2d: {np.mean(seterror_2d)}")
    print(f"MEAN seterror_3d: {np.mean(seterror_3d)}")
    print(f"MEAN seterror_rel3d: {np.mean(seterror_rel3d)}")
    print(f"MEAN seterror_relf: {np.mean(seterror_relf)}")
Example #2
0
def test(model, modelin=args.model,outfile=args.out,feature_transform=args.feat_trans):

    # define model, dataloader, 3dmm eigenvectors, optimization method
    if modelin != "":
        model.load_state_dict(torch.load(modelin))
    model.eval()

    # mean shape and eigenvectors for 3dmm
    M = 100
    data3dmm = dataloader.SyntheticLoader()
    mu_lm = torch.from_numpy(data3dmm.mu_lm).float()
    lm_eigenvec = torch.from_numpy(data3dmm.lm_eigenvec).float()
    shape = mu_lm

    # sample from f testing set
    allerror_2d = []
    allerror_3d = []
    allerror_rel3d = []
    allerror_relf = []
    all_f = []
    all_depth = []

    seterror_3d = []
    seterror_rel3d = []
    seterror_relf = []
    seterror_2d = []
    f_vals = [i*100 for i in range(4,21)]
    for f_test in f_vals:
        # create dataloader
        data = dataloader.TestLoader(f_test)

        error_2d = []
        error_3d = []
        error_rel3d = []
        error_relf = []
        M = 100;
        N = 68;
        batch_size = 1;

        for k in range(len(data)):
            batch = data[k]
            x_cam_gt = batch['x_cam_gt']
            x_w_gt = batch['x_w_gt']
            f_gt = batch['f_gt']
            x_img = batch['x_img'].unsqueeze(0)
            x_img_gt = batch['x_img_gt']
            T_gt = batch['T_gt']
            sequence = batch['x_img'].reshape((M,N,2)).permute(0,2,1)

            all_depth.append(np.mean(T_gt[:,2]))
            all_f.append(f_gt.numpy()[0])

            one = torch.ones(batch_size,M*N,1)
            x_img_one = torch.cat([x_img,one],dim=2)

            # run the model
            out,_,_ = model(x_img_one.permute(0,2,1))
            betas = out[:,:199]
            fout = torch.relu(out[:,199])
            if torch.any(fout < 1): fout = fout+1

            # apply 3DMM model from predicted parameters
            alpha_matrix = torch.diag(betas.squeeze())
            shape_cov = torch.mm(lm_eigenvec,alpha_matrix)
            s = shape_cov.sum(1).view(68,3)
            #shape = (mu_lm + s)
            #shape = mu_lm
            #shape[:,2] = shape[:,2]*-1

            # run epnp using predicted shape and intrinsics
            K = torch.zeros((3,3))
            K[0,0] = fout;
            K[1,1] = fout;
            K[2,2] = 1;
            K[0,2] = 0;
            K[1,2] = 0;
            Xc,R,T = util.EPnP(sequence,shape,K)

            # get errors
            reproj_errors2 = util.getReprojError2(sequence,shape,R,T,K)
            reproj_errors3 = util.getReprojError3(x_cam_gt,shape,R,T)
            rel_errors = util.getRelReprojError3(x_cam_gt,shape,R,T)

            reproj_error = reproj_errors2.mean()
            reconstruction_error = reproj_errors3.mean()
            rel_error = rel_errors.mean()
            f_error = torch.abs(f_gt - fout) / f_gt

            allerror_3d.append(reproj_error.data.numpy())
            allerror_2d.append(reconstruction_error.data.numpy())
            allerror_rel3d.append(rel_error.data.numpy())

            error_2d.append(reproj_error.cpu().data.item())
            error_3d.append(reconstruction_error.cpu().data.item())
            error_rel3d.append(rel_error.cpu().data.item())
            error_relf.append(f_error.cpu().data.item())

            print(f"f/sequence: {f_test}/{k}  | f/fgt: {fout[0].item():.3f}/{f_gt.item():.3f} |  f_error_rel: {f_error.item():.4f}  | rmse: {reconstruction_error.item():.4f}  | rel rmse: {rel_error.item():.4f}    | 2d error: {reproj_error.item():.4f}")
            #end for

        avg_2d = np.mean(error_2d)
        avg_rel3d = np.mean(error_rel3d)
        avg_3d = np.mean(error_3d)
        avg_relf = np.mean(error_relf)

        seterror_2d.append(avg_2d)
        seterror_3d.append(avg_3d)
        seterror_rel3d.append(avg_rel3d)
        seterror_relf.append(avg_relf)
        #end for

    all_f = np.stack(all_f).flatten()
    all_d = np.stack(all_depth).flatten()
    allerror_2d = np.stack(allerror_2d).flatten()
    allerror_3d = np.stack(allerror_3d).flatten()
    allerror_rel3d = np.stack(allerror_rel3d).flatten()

    matdata = {}
    matdata['fvals'] = np.array(f_vals)
    matdata['all_f'] = np.array(all_f)
    matdata['all_d'] = np.array(all_depth)
    matdata['error_2d'] = allerror_2d
    matdata['error_3d'] = allerror_3d
    matdata['error_rel3d'] = allerror_rel3d
    matdata['seterror_2d'] = np.array(seterror_2d)
    matdata['seterror_3d'] = np.array(seterror_3d)
    matdata['seterror_rel3d'] = np.array(seterror_rel3d)
    matdata['seterror_relf'] = np.array(seterror_relf)
    scipy.io.savemat(outfile,matdata)

    print(f"MEAN seterror_2d: {np.mean(seterror_2d)}")
    print(f"MEAN seterror_3d: {np.mean(seterror_3d)}")
    print(f"MEAN seterror_rel3d: {np.mean(seterror_rel3d)}")
    print(f"MEAN seterror_relf: {np.mean(seterror_relf)}")
def test(modelin=args.model,outfile=args.out,feature_transform=args.feat_trans):

    # define model, dataloader, 3dmm eigenvectors, optimization method
    #if modelin != "":
    #    model.load_state_dict(torch.load(modelin))
    #model.eval()
    #model.cuda()

    # mean shape and eigenvectors for 3dmm
    M = 100
    N = 68
    data3dmm = dataloader.SyntheticLoader()
    mu_lm = torch.from_numpy(data3dmm.mu_lm).float()
    mu_lm[:,2] = mu_lm[:,2]*-1
    lm_eigenvec = torch.from_numpy(data3dmm.lm_eigenvec).float()
    #optimizer = torch.optim.Adam(model.parameters(),lr=1e-2)

    # sample from f testing set
    allerror_2d = []
    allerror_3d = []
    allerror_rel3d = []
    allerror_relf = []
    all_f = []
    all_depth = []

    seterror_3d = []
    seterror_rel3d = []
    seterror_relf = []
    seterror_2d = []
    f_vals = [400 + i*100 for i in range(4)]

    # set random seed for reproducibility of test set
    np.random.seed(0)
    for f_test in f_vals:
        f_test = 1400
        # create dataloader
        loader = dataloader.TestLoader(f_test)

        error_2d = []
        error_3d = []
        error_rel3d = []
        error_relf = []
        M = 100;
        N = 68;
        batch_size = 1;

        for j, data in enumerate(loader):
            # create a model and optimizer for it
            theta1 = (1.1*torch.randn(4)).requires_grad()
            optimizer = torch.optim.SGD({theta},lr=0.00001)

            model2 = Model1(k=199,feature_transform=False)
            model2.apply(util.init_weights)
            model = Model1(k=1, feature_transform=False)
            model.apply(util.init_weights)
            optimizer = torch.optim.Adam(list(model.parameters()) + list(model2.parameters()),lr=1)

            # load the data
            x_cam_gt = data['x_cam_gt']
            shape_gt = data['x_w_gt']
            fgt = data['f_gt']
            x_img = data['x_img']
            x_img_gt = data['x_img_gt']
            T_gt = data['T_gt']
            all_depth.append(np.mean(T_gt[:,2]))
            all_f.append(fgt.numpy()[0])

            ptsI = x_img.reshape((M,N,2)).permute(0,2,1)
            x2d = x_img.view((M,N,2))
            x_img_pts = x_img.reshape((M,N,2)).permute(0,2,1)
            one = torch.ones(M*N,1)
            x_img_one = torch.cat([x_img,one],dim=1)
            x = x_img_one.permute(1,0)

            ini_pose = torch.zeros((M,6))
            ini_pose[:,5] = 99
            pre_loss = 99
            for iter in itertools.count():
                optimizer.zero_grad()

                # shape prediction
                betas,_,_ = model2(x.unsqueeze(0))
                shape = torch.sum(betas * lm_eigenvec,1)
                shape = shape.reshape(68,3) + mu_lm
                #shape = shape_gt

                # RMSE between GT and predicted shape
                rmse = torch.norm(shape_gt - shape,dim=1).mean().detach()

                # focal length prediction
                f,_,_ = model(x.unsqueeze(0))
                f = f + 300
                K = torch.zeros((3,3)).float()
                K[0,0] = f
                K[1,1] = f
                K[2,2] = 1

                # differentiable PnP pose estimation
                pose = bpnp(x2d,shape,K,ini_pose)
                pred = BPnP.batch_project(pose,shape,K)

                # loss
                #loss = torch.mean(torch.abs(pred - x2d))
                loss = torch.mean(torch.norm(pred - x2d,dim=2))

                loss.backward()
                optimizer.step()
                print(f"iter: {iter} | error: {loss.item():.3f} | f/fgt: {f.item():.1f}/{fgt[0].item():.1f} | rmse: {rmse.item():.2f}")
                if iter == 200: break
                ini_pose = pose.detach()

            # get errors
            km,c_w,scaled_betas, alphas = util.EPnP(ptsI,shape,K)
            Xc, R, T, mask = util.optimizeGN(km,c_w,scaled_betas,alphas,shape,ptsI,K)

            # get errors
            reproj_errors2 = util.getReprojError2(ptsI,shape,R,T,K)
            reproj_errors3 = util.getReprojError3(x_cam_gt,shape,R,T)
            rel_errors =  util.getRelReprojError3(x_cam_gt,shape,R,T)

            reproj_error = reproj_errors2.mean()
            reconstruction_error = reproj_errors3.mean()
            rel_error = rel_errors.mean()
            f_error = torch.abs(fgt - f) / fgt

            allerror_3d.append(reproj_error.data.numpy())
            allerror_2d.append(reconstruction_error.data.numpy())
            allerror_rel3d.append(rel_error.data.numpy())

            error_2d.append(reproj_error.cpu().data.item())
            error_3d.append(reconstruction_error.cpu().data.item())
            error_rel3d.append(rel_error.cpu().data.item())
            error_relf.append(f_error.cpu().data.item())

            print(f"f/sequence: {f_test}/{j}  | f/fgt: {f[0].item():.3f}/{fgt.item():.3f} |  f_error_rel: {f_error.item():.4f}  | rmse: {reconstruction_error.item():.4f}  | rel rmse: {rel_error.item():.4f}    | 2d error: {reproj_error.item():.4f}")
            #end for

        avg_2d = np.mean(error_2d)
        avg_rel3d = np.mean(error_rel3d)
        avg_3d = np.mean(error_3d)
        avg_relf = np.mean(error_relf)

        seterror_2d.append(avg_2d)
        seterror_3d.append(avg_3d)
        seterror_rel3d.append(avg_rel3d)
        seterror_relf.append(avg_relf)
        #end for
        break

    all_f = np.stack(all_f).flatten()
    all_d = np.stack(all_depth).flatten()
    allerror_2d = np.stack(allerror_2d).flatten()
    allerror_3d = np.stack(allerror_3d).flatten()
    allerror_rel3d = np.stack(allerror_rel3d).flatten()

    matdata = {}
    matdata['fvals'] = np.array(f_vals)
    matdata['all_f'] = np.array(all_f)
    matdata['all_d'] = np.array(all_depth)
    matdata['error_2d'] = allerror_2d
    matdata['error_3d'] = allerror_3d
    matdata['error_rel3d'] = allerror_rel3d
    matdata['seterror_2d'] = np.array(seterror_2d)
    matdata['seterror_3d'] = np.array(seterror_3d)
    matdata['seterror_rel3d'] = np.array(seterror_rel3d)
    matdata['seterror_relf'] = np.array(seterror_relf)
    scipy.io.savemat(outfile,matdata)

    print(f"MEAN seterror_2d: {np.mean(seterror_2d)}")
    print(f"MEAN seterror_3d: {np.mean(seterror_3d)}")
    print(f"MEAN seterror_rel3d: {np.mean(seterror_rel3d)}")
    print(f"MEAN seterror_relf: {np.mean(seterror_relf)}")
Example #4
0
def train(modelin=args.model, modelout=args.out):
    # define logger
    #torch.manual_seed(6)
    #if log:
    #    logger = Logger(logname)
    # define model, dataloader, 3dmm eigenvectors, optimization method
    torch.manual_seed(2)
    calib_net = Model1(k=1, feature_transform=False)
    sfm_net = Model1(k=199, feature_transform=False)
    #if modelin != "":
    #    model.load_state_dict(torch.load(modelin))
    opt1 = torch.optim.Adam(calib_net.parameters(), lr=1e-1)
    opt2 = torch.optim.Adam(sfm_net.parameters(), lr=1e-1)

    # dataloader
    #data = dataloader.Data()
    #loader = data.batchloader
    #loader = dataloader.BIWILoader()
    loader = dataloader.SyntheticLoader()

    # mean shape and eigenvectors for 3dmm
    mu_lm = torch.from_numpy(loader.mu_lm).float()
    #mu_lm[:,2] = mu_lm[:,2] * -1
    shape = mu_lm
    lm_eigenvec = torch.from_numpy(loader.lm_eigenvec).float()

    # main training loop
    for epoch in itertools.count():
        for j, data in enumerate(loader):

            M = loader.M
            N = loader.N

            # get the input and gt values
            x_cam_gt = data['x_cam_gt']
            shape_gt = data['x_w_gt']
            fgt = data['f_gt']
            x_img = data['x_img']
            x_img_gt = data['x_img_gt']

            x_img_pts = x_img.reshape((M, N, 2)).permute(0, 2, 1)
            one = torch.ones(M * N, 1)
            x_img_one = torch.cat([x_img, one], dim=1)
            x_cam_pt = x_cam_gt.permute(0, 2, 1).reshape(M * N, 3)
            x = x_img_one.permute(1, 0)

            # get initial values for betas and alphas of EPNP
            ptsI = x_img.reshape((M, N, 2)).permute(0, 2, 1)

            fvals = []
            errors = []
            for outerloop in itertools.count():

                # calibration
                shape = shape.detach()
                for iter in itertools.count():
                    opt1.zero_grad()

                    # focal length prediction
                    f, _, _ = calib_net(x.unsqueeze(0))
                    f = f + 300
                    K = torch.zeros((3, 3)).float()
                    K[0, 0] = f
                    K[1, 1] = f
                    K[2, 2] = 1

                    # RMSE between GT and predicted shape
                    rmse = torch.norm(shape_gt - shape, dim=1).mean().detach()

                    # error f
                    error_f = torch.mean(torch.abs(f - fgt))

                    # differentiable PnP pose estimation
                    km, c_w, scaled_betas, alphas = util.EPnP(ptsI, shape, K)
                    Xc, R, T, mask = util.optimizeGN(km, c_w, scaled_betas,
                                                     alphas, shape, ptsI, K)
                    error2d = util.getReprojError2(ptsI,
                                                   shape,
                                                   R,
                                                   T,
                                                   K,
                                                   show=False,
                                                   loss='l1')
                    loss = error2d.mean() + error_f
                    if iter > 20 and prev_loss < loss:
                        break
                    else:
                        prev_loss = loss
                    loss.backward()
                    opt1.step()
                    print(
                        f"iter: {iter} | error: {loss.item():.3f} | f/fgt: {f.item():.1f}/{fgt[0].item():.1f} | rmse: {rmse.item():.2f}"
                    )

                # sfm
                f = f.detach()
                for iter in itertools.count():
                    opt2.zero_grad()

                    # shape prediction
                    betas, _, _ = sfm_net(x.unsqueeze(0))
                    shape = torch.sum(betas * lm_eigenvec, 1)
                    shape = shape.reshape(68, 3) + mu_lm
                    K = torch.zeros((3, 3)).float()
                    K[0, 0] = f
                    K[1, 1] = f
                    K[2, 2] = 1

                    # RMSE between GT and predicted shape
                    rmse = torch.norm(shape_gt - shape, dim=1).mean().detach()

                    # differentiable PnP pose estimation
                    km, c_w, scaled_betas, alphas = util.EPnP(ptsI, shape, K)
                    Xc, R, T, mask = util.optimizeGN(km, c_w, scaled_betas,
                                                     alphas, shape, ptsI, K)
                    error2d = util.getReprojError2(ptsI,
                                                   shape,
                                                   R,
                                                   T,
                                                   K,
                                                   show=False,
                                                   loss='l2')
                    loss = error2d.mean()
                    if iter > 20 and prev_loss < loss:
                        break
                    else:
                        prev_loss = loss
                    loss.backward()
                    opt2.step()
                    print(
                        f"iter: {iter} | error: {loss.item():.3f} | f/fgt: {f.item():.1f}/{fgt[0].item():.1f} | rmse: {rmse.item():.2f}"
                    )

                if outerloop == 2: break

            # get errors
            reproj_errors2 = util.getReprojError2(ptsI, shape, R, T, K)
            reproj_errors3 = util.getReprojError3(x_cam_gt, shape, R, T)
            rel_errors = util.getRelReprojError3(x_cam_gt, shape, R, T)

            reproj_error = reproj_errors2.mean()
            reconstruction_error = reproj_errors3.mean()
            rel_error = rel_errors.mean()
            f_error = torch.abs(fgt - f) / fgt

            print(
                f"f/fgt: {f[0].item():.3f}/{fgt.item():.3f} |  f_error_rel: {f_error.item():.4f}  | rmse: {reconstruction_error.item():.4f}  | rel rmse: {rel_error.item():.4f}    | 2d error: {reproj_error.item():.4f}"
            )
            #end for

        torch.save(sfm_net.state_dict(),
                   os.path.join('model', 'sfm_' + modelout))
        torch.save(calib_net.state_dict(),
                   os.path.join('model', 'calib_' + modelout))
def test(modelin=args.model,
         outfile=args.out,
         feature_transform=args.feat_trans):

    # define model, dataloader, 3dmm eigenvectors, optimization method
    #if modelin != "":
    #    model.load_state_dict(torch.load(modelin))
    #model.eval()
    #model.cuda()

    # mean shape and eigenvectors for 3dmm
    M = 100
    N = 68
    data3dmm = dataloader.SyntheticLoader()
    mu_lm = torch.from_numpy(data3dmm.mu_lm).float()
    mu_lm[:, 2] = mu_lm[:, 2] * -1
    shape = mu_lm.detach()
    lm_eigenvec = torch.from_numpy(data3dmm.lm_eigenvec).float()
    #optimizer = torch.optim.Adam(model.parameters(),lr=1e-2)

    # sample from f testing set
    allerror_2d = []
    allerror_3d = []
    allerror_rel3d = []
    allerror_relf = []
    all_f = []
    all_depth = []

    seterror_3d = []
    seterror_rel3d = []
    seterror_relf = []
    seterror_2d = []
    f_vals = [i * 100 for i in range(4, 21)]
    for f_test in f_vals:
        f_test = 1400
        # create dataloader
        loader = dataloader.TestLoader(f_test)

        error_2d = []
        error_3d = []
        error_rel3d = []
        error_relf = []
        M = 100
        N = 68
        batch_size = 1

        for j, data in enumerate(loader):
            # create a model and optimizer for it
            model = Model2(k=1, feature_transform=False)
            model.apply(util.init_weights)
            optimizer = torch.optim.Adam(model.parameters(), lr=1e-1)

            M = loader.M
            N = loader.N

            # load the data
            T_gt = data['T_gt']
            x_cam_gt = data['x_cam_gt']
            x_w_gt = data['x_w_gt']
            fgt = data['f_gt']
            x_img = data['x_img']
            x_img_gt = data['x_img_gt']

            x_img_pts = x_img.reshape((M, N, 2)).permute(0, 2, 1)
            one = torch.ones(M * N, 1)
            x_img_one = torch.cat([x_img, one], dim=1)
            x_cam_pt = x_cam_gt.permute(0, 2, 1).reshape(M * N, 3)

            all_depth.append(np.mean(T_gt[:, 2]))
            all_f.append(fgt.numpy()[0])

            # create the input
            b = 10
            x = x_img_one.reshape(M, N,
                                  3).reshape(b, M // b, N,
                                             3).reshape(b, M // b * N, 3)
            x = x.permute(0, 2, 1)
            ptsI = x_img.reshape((M, N, 2)).permute(0, 2, 1)

            # optimize using EPNP+GN
            fvals = []
            errors = []
            for iter in itertools.count():
                optimizer.zero_grad()

                f, _, _ = model(x)
                #f = f + 1000
                f = torch.nn.functional.leaky_relu(f) + 300
                K = torch.zeros((b, 3, 3)).float()
                K[:, 0, 0] = f.squeeze()
                K[:, 1, 1] = f.squeeze()
                K[:, 2, 2] = 1

                # differentiable pose estimation
                losses = []
                for i in range(b):
                    j = i + 1
                    km, c_w, scaled_betas, alphas = util.EPnP(
                        ptsI[i:j * b], shape, K[i])
                    Xc, R, T, _ = util.optimizeGN(km, c_w, scaled_betas,
                                                  alphas, shape, ptsI[i:j * b],
                                                  K[i])
                    error2d = util.getReprojError2(ptsI[i:j * b], shape, R, T,
                                                   K[i]).mean()
                    losses.append(error2d)
                loss = torch.stack(losses).mean()
                loss.backward()
                optimizer.step()
                print(
                    f"iter: {iter} | error: {loss.item():.3f} | f/fgt: {f.mean().item():.1f}/{fgt[0].item():.1f}"
                )
                if iter == 100: break

            # get overall poses
            f = f.mean()
            K = torch.zeros((3, 3)).float()
            K[0, 0] = f
            K[1, 1] = f
            K[2, 2] = 1
            km, c_w, scaled_betas, alphas = util.EPnP(ptsI, shape, K)
            Xc, R, T, _ = util.optimizeGN(km, c_w, scaled_betas, alphas, shape,
                                          ptsI, K)

            # get errors
            reproj_errors2 = util.getReprojError2(ptsI, shape, R, T, K)
            reproj_errors3 = util.getReprojError3(x_cam_gt, shape, R, T)
            rel_errors = util.getRelReprojError3(x_cam_gt, shape, R, T)

            reproj_error = reproj_errors2.mean()
            reconstruction_error = reproj_errors3.mean()
            rel_error = rel_errors.mean()
            f_error = torch.abs(fgt - f) / fgt

            allerror_3d.append(reproj_error.data.numpy())
            allerror_2d.append(reconstruction_error.data.numpy())
            allerror_rel3d.append(rel_error.data.numpy())

            error_2d.append(reproj_error.cpu().data.item())
            error_3d.append(reconstruction_error.cpu().data.item())
            error_rel3d.append(rel_error.cpu().data.item())
            error_relf.append(f_error.cpu().data.item())

            print(
                f"f/sequence: {f_test}/{j}  | f/fgt: {f.item():.3f}/{fgt.item():.3f} |  f_error_rel: {f_error.item():.4f}  | rmse: {reconstruction_error.item():.4f}  | rel rmse: {rel_error.item():.4f}    | 2d error: {reproj_error.item():.4f}"
            )
            #end for

        avg_2d = np.mean(error_2d)
        avg_rel3d = np.mean(error_rel3d)
        avg_3d = np.mean(error_3d)
        avg_relf = np.mean(error_relf)

        seterror_2d.append(avg_2d)
        seterror_3d.append(avg_3d)
        seterror_rel3d.append(avg_rel3d)
        seterror_relf.append(avg_relf)
        #end for
        break

    all_f = np.stack(all_f).flatten()
    all_d = np.stack(all_depth).flatten()
    allerror_2d = np.stack(allerror_2d).flatten()
    allerror_3d = np.stack(allerror_3d).flatten()
    allerror_rel3d = np.stack(allerror_rel3d).flatten()

    matdata = {}
    matdata['fvals'] = np.array(f_vals)
    matdata['all_f'] = np.array(all_f)
    matdata['all_d'] = np.array(all_depth)
    matdata['error_2d'] = allerror_2d
    matdata['error_3d'] = allerror_3d
    matdata['error_rel3d'] = allerror_rel3d
    matdata['seterror_2d'] = np.array(seterror_2d)
    matdata['seterror_3d'] = np.array(seterror_3d)
    matdata['seterror_rel3d'] = np.array(seterror_rel3d)
    matdata['seterror_relf'] = np.array(seterror_relf)
    scipy.io.savemat(outfile, matdata)

    print(f"MEAN seterror_2d: {np.mean(seterror_2d)}")
    print(f"MEAN seterror_3d: {np.mean(seterror_3d)}")
    print(f"MEAN seterror_rel3d: {np.mean(seterror_rel3d)}")
    print(f"MEAN seterror_relf: {np.mean(seterror_relf)}")
Example #6
0
def test(modelin=args.model,
         outfile=args.out,
         feature_transform=args.feat_trans):

    # define model, dataloader, 3dmm eigenvectors, optimization method
    #if modelin != "":
    #    model.load_state_dict(torch.load(modelin))
    #model.eval()
    #model.cuda()

    # mean shape and eigenvectors for 3dmm
    M = 100
    N = 68
    data3dmm = dataloader.SyntheticLoader()
    mu_lm = torch.from_numpy(data3dmm.mu_lm).float()
    mu_lm[:, 2] = mu_lm[:, 2] * -1
    shape = mu_lm.detach()
    lm_eigenvec = torch.from_numpy(data3dmm.lm_eigenvec).float()
    #optimizer = torch.optim.Adam(model.parameters(),lr=1e-2)

    # sample from f testing set
    allerror_2d = []
    allerror_3d = []
    allerror_rel3d = []
    allerror_relf = []
    all_f = []
    all_depth = []

    seterror_3d = []
    seterror_rel3d = []
    seterror_relf = []
    seterror_2d = []
    f_vals = [i * 100 for i in range(4, 21)]
    np.random.seed(0)
    for f_test in f_vals:
        f_test = 1200
        # create dataloader
        loader = dataloader.TestLoader(f_test)

        error_2d = []
        error_3d = []
        error_rel3d = []
        error_relf = []
        M = 100
        N = 68
        batch_size = 1

        for j, data in enumerate(loader):
            # create a model and optimizer for it
            #model2 = Model1(k=199,feature_transform=False)
            #model2.apply(util.init_weights)
            model = Model1(k=1, feature_transform=False)
            model.apply(util.init_weights)
            optimizer = torch.optim.Adam(model.parameters(), lr=2e-1)

            #data = loader[67]
            x_cam_gt = data['x_cam_gt']
            shape = data['x_w_gt']
            fgt = data['f_gt']
            x_img = data['x_img']
            x_img_gt = data['x_img_gt']
            T_gt = data['T_gt']
            all_depth.append(np.mean(T_gt[:, 2]))
            all_f.append(fgt.numpy()[0])

            x_img_pts = x_img.reshape((M, N, 2)).permute(0, 2, 1)
            one = torch.ones(M * N, 1)
            x_img_one = torch.cat([x_img, one], dim=1)
            x_cam_pt = x_cam_gt.permute(0, 2, 1).reshape(M * N, 3)
            x = x_img_one.permute(1, 0)

            ptsI = x_img.reshape((M, N, 2)).permute(0, 2, 1)

            for iter in itertools.count():
                optimizer.zero_grad()

                #betas,_,_ = model2(x.unsqueeze(0))
                #shape = torch.sum(betas * lm_eigenvec,1)
                #shape = shape.reshape(68,3) + mu_lm

                f, _, _ = model(x.unsqueeze(0))
                #f = f + 300
                #f = (torch.nn.functional.tanh(f)+1)*850 + 300
                f = f + 300
                #f = torch.nn.functional.sigmoid(f)
                K = torch.zeros((3, 3)).float()
                K[0, 0] = f
                K[1, 1] = f
                K[2, 2] = 1

                # differentiable pose estimation
                km, c_w, scaled_betas, alphas = util.EPnP(ptsI, shape, K)
                Xc, R, T, mask = util.optimizeGN(km, c_w, scaled_betas, alphas,
                                                 shape, ptsI, K)
                error2d = util.getReprojError2(ptsI,
                                               shape,
                                               R,
                                               T,
                                               K,
                                               show=False,
                                               loss='l1')
                loss = error2d.mean()
                loss.backward()
                if torch.any(model.fc2.weight.grad != model.fc2.weight.grad):
                    print("oh oh something broke")
                    break
                optimizer.step()
                print(
                    f"iter: {iter} | error: {loss.item():.3f} | f/fgt: {f.item():.1f}/{fgt[0].item():.1f}"
                )
                if iter == 200: break

            # get errors
            reproj_errors2 = util.getReprojError2(ptsI, shape, R, T, K)
            reproj_errors3 = util.getReprojError3(x_cam_gt, shape, R, T)
            rel_errors = util.getRelReprojError3(x_cam_gt, shape, R, T)

            reproj_error = reproj_errors2.mean()
            reconstruction_error = reproj_errors3.mean()
            rel_error = rel_errors.mean()
            f_error = torch.abs(fgt - f) / fgt

            allerror_3d.append(reproj_error.data.numpy())
            allerror_2d.append(reconstruction_error.data.numpy())
            allerror_rel3d.append(rel_error.data.numpy())

            error_2d.append(reproj_error.cpu().data.item())
            error_3d.append(reconstruction_error.cpu().data.item())
            error_rel3d.append(rel_error.cpu().data.item())
            error_relf.append(f_error.cpu().data.item())

            print(
                f"f/sequence: {f_test}/{j}  | f/fgt: {f[0].item():.3f}/{fgt.item():.3f} |  f_error_rel: {f_error.item():.4f}  | rmse: {reconstruction_error.item():.4f}  | rel rmse: {rel_error.item():.4f}    | 2d error: {reproj_error.item():.4f}"
            )
            #end for

        avg_2d = np.mean(error_2d)
        avg_rel3d = np.mean(error_rel3d)
        avg_3d = np.mean(error_3d)
        avg_relf = np.mean(error_relf)

        seterror_2d.append(avg_2d)
        seterror_3d.append(avg_3d)
        seterror_rel3d.append(avg_rel3d)
        seterror_relf.append(avg_relf)
        #end for
        break

    all_f = np.stack(all_f).flatten()
    all_d = np.stack(all_depth).flatten()
    allerror_2d = np.stack(allerror_2d).flatten()
    allerror_3d = np.stack(allerror_3d).flatten()
    allerror_rel3d = np.stack(allerror_rel3d).flatten()

    matdata = {}
    matdata['fvals'] = np.array(f_vals)
    matdata['all_f'] = np.array(all_f)
    matdata['all_d'] = np.array(all_depth)
    matdata['error_2d'] = allerror_2d
    matdata['error_3d'] = allerror_3d
    matdata['error_rel3d'] = allerror_rel3d
    matdata['seterror_2d'] = np.array(seterror_2d)
    matdata['seterror_3d'] = np.array(seterror_3d)
    matdata['seterror_rel3d'] = np.array(seterror_rel3d)
    matdata['seterror_relf'] = np.array(seterror_relf)
    scipy.io.savemat(outfile, matdata)

    print(f"MEAN seterror_2d: {np.mean(seterror_2d)}")
    print(f"MEAN seterror_3d: {np.mean(seterror_3d)}")
    print(f"MEAN seterror_rel3d: {np.mean(seterror_rel3d)}")
    print(f"MEAN seterror_relf: {np.mean(seterror_relf)}")
Example #7
0
def testBIWI(model,modelin=args.model,outfile=args.out,feature_transform=args.feat_trans):
    if modelin != "":
        model.load_state_dict(torch.load(modelin))
    model.cuda()

    # load 3dmm data
    data3dmm = dataloader.SyntheticLoader()
    mu_lm = torch.from_numpy(data3dmm.mu_lm).float().cuda()
    lm_eigenvec = torch.from_numpy(data3dmm.lm_eigenvec).float().cuda()

    loader = dataloader.BIWILoader()
    seterror_3d = []
    seterror_rel3d = []
    seterror_relf = []
    seterror_2d = []
    for sub in range(len(loader)):
        batch = loader[sub]


        x_cam_gt = batch['x_cam_gt'].cuda()
        x_w_gt = batch['x_w_gt'].cuda()
        f_gt = batch['f_gt'].cuda()
        x_img = batch['x_img'].cuda()
        x_img_gt = batch['x_img_gt'].cuda()
        M = x_img_gt.shape[0]

        one  = torch.ones(M,1,68).cuda()
        x_img_one = torch.cat([x_img,one],dim=1)

        # run the model
        out, trans, transfeat = model(x_img_one)
        alphas = out[:,:199].mean(0)
        f = torch.relu(out[:,199]).mean()
        K = torch.zeros((3,3)).float().cuda()
        K[0,0] = f;
        K[1,1] = f;
        K[2,2] = 1;
        K[0,2] = 320;
        K[1,2] = 240;

        # apply 3DMM model from predicted parameters
        alpha_matrix = torch.diag(alphas)
        shape_cov = torch.mm(lm_eigenvec,alpha_matrix)
        s = shape_cov.sum(1).view(68,3)
        shape = (mu_lm + s)
        shae[:,2] = shape[:,2]*-1

        # run epnp algorithm
        # get control points
        c_w = util.getControlPoints(shape)

        # solve alphas
        alphas = util.solveAlphas(shape,c_w)

        # setup M
        px = 320;
        py = 240;

        Matrix = util.setupM(alphas,x_img.permute(0,2,1),px,py,f)

        # get eigenvectors of M for each view
        u,d,v = torch.svd(Matrix)

        #solve N=1
        c_c_n1 = v[:,:,-1].reshape((M,4,3)).permute(0,2,1)
        _ , x_c_n1, _ = util.scaleControlPoints(c_c_n1,c_w[:3,:],alphas,shape)
        Rn1,Tn1 = util.getExtrinsics(x_c_n1,shape)
        reproj_error2_n1 = util.getReprojError2(x_img,shape,Rn1,Tn1,K)
        reproj_error3_n1 = util.getReprojError3(x_cam_gt,shape,Rn1,Tn1)
        rel_error_n1 = util.getRelReprojError3(x_cam_gt,shape,Rn1,Tn1)

        # solve N=2
        # get distance contraints
        d12,d13,d14,d23,d24,d34 = util.getDistances(c_w)
        distances = torch.stack([d12,d13,d14,d23,d24,d34])**2
        beta_n2 = util.getBetaN2(v[:,:,-2:],distances)
        c_c_n2 = util.getControlPointsN2(v[:,:,-2:],beta_n2)
        _,x_c_n2,_ = util.scaleControlPoints(c_c_n2,c_w[:3,:],alphas,shape)
        Rn2,Tn2 = util.getExtrinsics(x_c_n2,shape)
        reproj_error2_n2 = util.getReprojError2(x_img,shape,Rn2,Tn2,K)
        reproj_error3_n2 = util.getReprojError3(x_cam_gt,shape,Rn2,Tn2)
        rel_error_n2 = util.getRelReprojError3(x_cam_gt,shape,Rn1,Tn1)

        mask = reproj_error2_n1 < reproj_error2_n2


        reproj_errors = torch.cat((reproj_error2_n1[mask],reproj_error2_n2[~mask]))
        rmse_errors = torch.cat((reproj_error3_n1[mask],reproj_error3_n2[~mask]))
        rel_errors = torch.cat((rel_error_n2[~mask],rel_error_n1[mask]))

        # errors
        reproj_error = torch.mean(reproj_errors)
        reconstruction_error = torch.mean(rmse_errors)
        rel_error = torch.mean(rel_errors)
        f_error = torch.abs(f_gt - f) / f_gt

        seterror_2d.append(reproj_error.cpu().data.item())
        seterror_3d.append(reconstruction_error.cpu().data.item())
        seterror_rel3d.append(rel_error.cpu().data.item())
        seterror_relf.append(f_error.cpu().data.item())

        print(f"fgt: {f_gt.mean().item():.3f}  | f_error_rel: {f_error.item():.4f}  | rmse: {reconstruction_error.item():.4f}  | rel rmse: {rel_error.item():.4f}    | 2d error: {reproj_error.item():.4f}")
        #end for

    matdata = {}
    matdata['seterror_2d'] = np.array(seterror_2d)
    matdata['seterror_3d'] = np.array(seterror_3d)
    matdata['seterror_rel3d'] = np.array(seterror_rel3d)
    matdata['seterror_relf'] = np.array(seterror_relf)
    scipy.io.savemat(outfile,matdata)

    print(f"MEAN seterror_2d: {np.mean(seterror_2d)}")
    print(f"MEAN seterror_3d: {np.mean(seterror_3d)}")
    print(f"MEAN seterror_rel3d: {np.mean(seterror_rel3d)}")
    print(f"MEAN seterror_relf: {np.mean(seterror_relf)}")
Example #8
0
def test(model, modelin=args.model,outfile=args.out,feature_transform=args.feat_trans):

    # define model, dataloader, 3dmm eigenvectors, optimization method
    if modelin != "":
        model.load_state_dict(torch.load(modelin))
    model.cuda()

    # mean shape and eigenvectors for 3dmm
    M = 100
    data3dmm = dataloader.SyntheticLoader()
    mu_lm = torch.from_numpy(data3dmm.mu_lm).float().cuda()
    lm_eigenvec = torch.from_numpy(data3dmm.lm_eigenvec).float().cuda()

    # sample from f testing set
    allerror_2d = []
    allerror_3d = []
    allerror_rel3d = []
    allerror_relf = []
    allerror_f = []
    allerror_d = []

    seterror_3d = []
    seterror_rel3d = []
    seterror_relf = []
    seterror_2d = []
    f_vals = [i*100 for i in range(4,21)]
    for f_test in f_vals:
        # create dataloader
        data = dataloader.TestLoader(f_test)

        error_2d = []
        error_3d = []
        error_rel3d = []
        error_relf = []

        for k in range(len(data)):
            batch = data[k]
            x_cam_gt = batch['x_cam_gt'].cuda()
            x_w_gt = batch['x_w_gt'].cuda()
            f_gt = batch['f_gt'].cuda()
            x_img = batch['x_img'].cuda()
            x_img_gt = batch['x_img_gt'].cuda()
            T_gt = batch['T_gt']

            allerror_d.append(T_gt[:,2])

            one  = torch.ones(M,1,68).cuda()
            x_img_one = torch.cat([x_img,one],dim=1)

            # run the model
            out, trans, transfeat = model(x_img_one)
            alphas = out[:,:199].mean(0)
            f = torch.relu(out[:,199]).mean()
            K = torch.zeros((3,3)).float().cuda()

            for f = np.linspace(-200,200,100):
                K[0,0] = f;
                K[1,1] = f;
                K[2,2] = 1;
                K[0,2] = 320;
                K[1,2] = 240;

                # apply 3DMM model from predicted parameters
                alpha_matrix = torch.diag(alphas)
                shape_cov = torch.mm(lm_eigenvec,alpha_matrix)
                s = shape_cov.sum(1).view(68,3)
                #shape = (mu_lm + s)
                shape = mu_lm
                shape[:,2] = shape[:,2]*-1

                # run epnp algorithm
                # get control points
                c_w = util.getControlPoints(shape)

                # solve alphas
                alphas = util.solveAlphas(shape,c_w)

                # setup M
                px = 320;
                py = 240;
                Matrix = util.setupM(alphas,x_img.permute(0,2,1),px,py,f)

                # get eigenvectors of M for each view
                u,d,v = torch.svd(Matrix)

                #solve N=1
                c_c_n1 = v[:,:,-1].reshape((100,4,3)).permute(0,2,1)
                _ , x_c_n1, _ = util.scaleControlPoints(c_c_n1,c_w[:3,:],alphas,shape)
                Rn1,Tn1 = util.getExtrinsics(x_c_n1,shape)
                reproj_error2_n1 = util.getReprojError2(x_img,shape,Rn1,Tn1,K)
                reproj_error3_n1 = util.getReprojError3(x_cam_gt,shape,Rn1,Tn1)
                rel_error_n1 = util.getRelReprojError3(x_cam_gt,shape,Rn1,Tn1)

                # solve N=2
                # get distance contraints
                d12,d13,d14,d23,d24,d34 = util.getDistances(c_w)
                distances = torch.stack([d12,d13,d14,d23,d24,d34])**2
                beta_n2 = util.getBetaN2(v[:,:,-2:],distances)
                c_c_n2 = util.getControlPointsN2(v[:,:,-2:],beta_n2)
                _,x_c_n2,_ = util.scaleControlPoints(c_c_n2,c_w[:3,:],alphas,shape)
                Rn2,Tn2 = util.getExtrinsics(x_c_n2,shape)
                reproj_error2_n2 = util.getReprojError2(x_img,shape,Rn2,Tn2,K)
                reproj_error3_n2 = util.getReprojError3(x_cam_gt,shape,Rn2,Tn2)
                rel_error_n2 = util.getRelReprojError3(x_cam_gt,shape,Rn1,Tn1)

                mask = reproj_error2_n1 < reproj_error2_n2
                reproj_errors = torch.cat((reproj_error2_n1[mask],reproj_error2_n2[~mask]))
                rmse_errors = torch.cat((reproj_error3_n1[mask],reproj_error3_n2[~mask]))
                rel_errors = torch.cat((rel_error_n2[~mask],rel_error_n1[mask]))

                print(rel_errors.mean())
                quit()

            # errors
            allerror_3d.append(reproj_errors.cpu().data.numpy())
            allerror_2d.append(rmse_errors.cpu().data.numpy())
            allerror_rel3d.append(rel_errors.cpu().data.numpy())

            reproj_error = torch.mean(reproj_errors)
            reconstruction_error = torch.mean(rmse_errors)
            rel_error = torch.mean(rel_errors)
            f_error = torch.abs(f_gt - f) / f_gt

            error_2d.append(reproj_error.cpu().data.item())
            error_3d.append(reconstruction_error.cpu().data.item())
            error_rel3d.append(rel_error.cpu().data.item())
            error_relf.append(f_error.cpu().data.item())

            print(f"f/sequence: {f_test}/{k}  | f_error_rel: {f_error.item():.4f}  | rmse: {reconstruction_error.item():.4f}  | rel rmse: {rel_error.item():.4f}    | 2d error: {reproj_error.item():.4f}")

            #end for

        avg_2d = np.mean(error_2d)
        avg_rel3d = np.mean(error_rel3d)
        avg_3d = np.mean(error_3d)
        avg_relf = np.mean(error_relf)

        seterror_2d.append(avg_2d)
        seterror_3d.append(avg_3d)
        seterror_rel3d.append(avg_rel3d)
        seterror_relf.append(avg_relf)
Example #9
0
def test(modelin=args.model,
         outfile=args.out,
         feature_transform=args.feat_trans):

    # define model, dataloader, 3dmm eigenvectors, optimization method
    #if modelin != "":
    #    model.load_state_dict(torch.load(modelin))
    #model.eval()
    #model.cuda()

    # mean shape and eigenvectors for 3dmm
    M = 100
    N = 68
    data3dmm = dataloader.SyntheticLoader()
    mu_lm = torch.from_numpy(data3dmm.mu_lm).float().detach()
    mu_lm[:, 2] = mu_lm[:, 2] * -1
    lm_eigenvec = torch.from_numpy(data3dmm.lm_eigenvec).float()
    #optimizer = torch.optim.Adam(model.parameters(),lr=1e-2)

    # sample from f testing set
    allerror_2d = []
    allerror_3d = []
    allerror_rel3d = []
    allerror_relf = []
    all_f = []
    all_depth = []

    seterror_3d = []
    seterror_rel3d = []
    seterror_relf = []
    seterror_2d = []
    f_vals = [400 + i * 100 for i in range(4)]

    # set random seed for reproducibility of test set
    np.random.seed(0)
    torch.manual_seed(0)
    for f_test in f_vals:
        f_test = 1400
        # create dataloader
        loader = dataloader.TestLoader(f_test)

        error_2d = []
        error_3d = []
        error_rel3d = []
        error_relf = []
        M = 100
        N = 68
        batch_size = 1

        for j, data in enumerate(loader):
            # create a model and optimizer for it
            model2 = Model1(k=199, feature_transform=False)
            model2.apply(util.init_weights)
            model = Model1(k=1, feature_transform=False)
            model.apply(util.init_weights)
            opt1 = torch.optim.Adam(model2.parameters(), lr=1e-1)
            opt2 = torch.optim.Adam(model.parameters(), lr=1e-1)

            # load the data
            x_cam_gt = data['x_cam_gt']
            shape_gt = data['x_w_gt']
            fgt = data['f_gt']
            x_img = data['x_img']
            x_img_gt = data['x_img_gt']
            T_gt = data['T_gt']
            all_depth.append(np.mean(T_gt[:, 2]))
            all_f.append(fgt.numpy()[0])

            x_img_pts = x_img.reshape((M, N, 2)).permute(0, 2, 1)
            one = torch.ones(M * N, 1)
            x_img_one = torch.cat([x_img, one], dim=1)
            x_cam_pt = x_cam_gt.permute(0, 2, 1).reshape(M * N, 3)
            x = x_img_one.permute(1, 0)

            ptsI = x_img.reshape((M, N, 2)).permute(0, 2, 1)

            # multi objective optimization
            shape = mu_lm
            for outerloop in itertools.count():

                # calibration alg3
                shape = shape.detach()
                for iter2 in itertools.count():
                    opt2.zero_grad()

                    # focal length prediction
                    curf, _, _ = model(x.unsqueeze(0))
                    curf = curf + 300
                    K = torch.zeros((3, 3)).float()
                    K[0, 0] = curf
                    K[1, 1] = curf
                    K[2, 2] = 1

                    # RMSE between GT and predicted shape
                    rmse = torch.norm(shape_gt - shape, dim=1).mean().detach()

                    # differentiable PnP pose estimation
                    km, c_w, scaled_betas, alphas = util.EPnP(ptsI, shape, K)
                    Xc, R, T, mask = util.optimizeGN(km, c_w, scaled_betas,
                                                     alphas, shape, ptsI, K)
                    error2d = util.getReprojError2(ptsI,
                                                   shape,
                                                   R,
                                                   T,
                                                   K,
                                                   show=False,
                                                   loss='l2')
                    loss = error2d.mean()
                    if iter2 > 20 and prev_loss < loss:
                        break
                    else:
                        prev_loss = loss
                    loss.backward()
                    opt2.step()
                    print(
                        f"iter: {iter2} | error: {loss.item():.3f} | f/fgt: {curf.item():.1f}/{fgt[0].item():.1f} | rmse: {rmse.item():.2f}"
                    )

                # sfm alg2
                curf = curf.detach()
                for iter1 in itertools.count():
                    opt1.zero_grad()

                    # shape prediction
                    betas, _, _ = model2(x.unsqueeze(0))
                    shape = torch.sum(betas * lm_eigenvec, 1)
                    shape = shape.reshape(68, 3) + mu_lm
                    K = torch.zeros((3, 3)).float()
                    K[0, 0] = curf
                    K[1, 1] = curf
                    K[2, 2] = 1

                    # RMSE between GT and predicted shape
                    rmse = torch.norm(shape_gt - shape, dim=1).mean().detach()

                    # differentiable PnP pose estimation
                    km, c_w, scaled_betas, alphas = util.EPnP(ptsI, shape, K)
                    Xc, R, T, mask = util.optimizeGN(km, c_w, scaled_betas,
                                                     alphas, shape, ptsI, K)
                    error2d = util.getReprojError2(ptsI,
                                                   shape,
                                                   R,
                                                   T,
                                                   K,
                                                   show=False,
                                                   loss='l2')
                    loss = error2d.mean()
                    if iter1 > 20 and prev_loss < loss:
                        break
                    else:
                        prev_loss = loss
                    loss.backward()
                    opt1.step()
                    print(
                        f"iter: {iter1} | error: {loss.item():.3f} | f/fgt: {curf.item():.1f}/{fgt[0].item():.1f} | rmse: {rmse.item():.2f}"
                    )

                # closing condition for outerloop on dual objective
                if outerloop == 4: break

            f = curf
            # get errors
            reproj_errors2 = util.getReprojError2(ptsI, shape, R, T, K)
            reproj_errors3 = util.getReprojError3(x_cam_gt, shape, R, T)
            rel_errors = util.getRelReprojError3(x_cam_gt, shape, R, T)

            reproj_error = reproj_errors2.mean()
            reconstruction_error = reproj_errors3.mean()
            rel_error = rel_errors.mean()
            f_error = torch.abs(fgt - f) / fgt

            allerror_3d.append(reproj_error.data.numpy())
            allerror_2d.append(reconstruction_error.data.numpy())
            allerror_rel3d.append(rel_error.data.numpy())

            error_2d.append(reproj_error.cpu().data.item())
            error_3d.append(reconstruction_error.cpu().data.item())
            error_rel3d.append(rel_error.cpu().data.item())
            error_relf.append(f_error.cpu().data.item())

            print(
                f"f/sequence: {f_test}/{j}  | f/fgt: {f[0].item():.3f}/{fgt.item():.3f} |  f_error_rel: {f_error.item():.4f}  | rmse: {reconstruction_error.item():.4f}  | rel rmse: {rel_error.item():.4f}    | 2d error: {reproj_error.item():.4f}"
            )
            #end for

        avg_2d = np.mean(error_2d)
        avg_rel3d = np.mean(error_rel3d)
        avg_3d = np.mean(error_3d)
        avg_relf = np.mean(error_relf)

        seterror_2d.append(avg_2d)
        seterror_3d.append(avg_3d)
        seterror_rel3d.append(avg_rel3d)
        seterror_relf.append(avg_relf)
        #end for
        break

    all_f = np.stack(all_f).flatten()
    all_d = np.stack(all_depth).flatten()
    allerror_2d = np.stack(allerror_2d).flatten()
    allerror_3d = np.stack(allerror_3d).flatten()
    allerror_rel3d = np.stack(allerror_rel3d).flatten()

    matdata = {}
    matdata['fvals'] = np.array(f_vals)
    matdata['all_f'] = np.array(all_f)
    matdata['all_d'] = np.array(all_depth)
    matdata['error_2d'] = allerror_2d
    matdata['error_3d'] = allerror_3d
    matdata['error_rel3d'] = allerror_rel3d
    matdata['seterror_2d'] = np.array(seterror_2d)
    matdata['seterror_3d'] = np.array(seterror_3d)
    matdata['seterror_rel3d'] = np.array(seterror_rel3d)
    matdata['seterror_relf'] = np.array(seterror_relf)
    scipy.io.savemat(outfile, matdata)

    print(f"MEAN seterror_2d: {np.mean(seterror_2d)}")
    print(f"MEAN seterror_3d: {np.mean(seterror_3d)}")
    print(f"MEAN seterror_rel3d: {np.mean(seterror_rel3d)}")
    print(f"MEAN seterror_relf: {np.mean(seterror_relf)}")