예제 #1
0
def test_lkm():
    index = 1
    scale = 0.2
    epsilon = 1e-7
    radius = 2
    image_dir = "data"

    name = f"GT{index:02d}"

    image = load_image(f"{image_dir}/input_training_lowres/{name}.png", "rgb",
                       scale, "bilinear")
    trimap = load_image(
        f"{image_dir}/trimap_training_lowres/Trimap1/{name}.png",
        "gray",
        scale,
        "nearest",
    )

    L_lkm, diag_L_lkm = lkm_laplacian(image, epsilon=epsilon, radius=radius)

    L_cf = cf_laplacian(image, epsilon=epsilon, radius=radius)

    A_cf, b, c = make_linear_system(L_cf, trimap, return_c=True)

    def A_lkm(x):
        return L_lkm(x) + c * x

    inv_diag_A_lkm = 1.0 / (diag_L_lkm + c)

    def jacobi_lkm(r):
        return inv_diag_A_lkm * r

    jacobi_cf = jacobi(A_cf)

    lkm_callback = ProgressCallback()
    cf_callback = ProgressCallback()

    x_lkm = cg(A_lkm, b, M=jacobi_lkm)
    x_cf = cg(A_cf, b, M=jacobi_cf)

    difference = np.linalg.norm(x_lkm - x_cf)

    assert difference < 2e-4
    assert abs(lkm_callback.n - cf_callback.n) <= 2
예제 #2
0
def test_preconditioners():
    atol = 1e-6
    index = 1
    scale = 0.2

    name = f"GT{index:02d}"
    # print(name)

    image_dir = "data"

    image = load_image(f"{image_dir}/input_training_lowres/{name}.png", "rgb",
                       scale, "bilinear")
    trimap = load_image(
        f"{image_dir}/trimap_training_lowres/Trimap1/{name}.png",
        "gray",
        scale,
        "nearest",
    )

    A, b = make_linear_system(cf_laplacian(image), trimap)

    preconditioners = [
        ("no", lambda A: None),
        ("jacobi", lambda A: jacobi(A)),
        ("icholt", lambda A: ichol(A, max_nnz=500000)),
        ("vcycle", lambda A: vcycle(A, trimap.shape)),
    ]

    expected_iterations = {
        "no": 532,
        "jacobi": 250,
        "icholt": 3,
        "vcycle": 88,
    }

    for preconditioner_name, preconditioner in preconditioners:
        callback = CounterCallback()

        M = preconditioner(A)

        x = cg(A, b, M=M, atol=atol, rtol=0, maxiter=10000, callback=callback)

        r = b - A.dot(x)

        norm_r = np.linalg.norm(r)

        assert norm_r <= atol

        n_expected = expected_iterations[preconditioner_name]

        if callback.n > n_expected:
            print(
                "WARNING: Unexpected number of iterations. Expected %d, but got %d"
                % (n_expected, callback.n))

        assert callback.n <= n_expected
예제 #3
0
def main():
    print("loading images")

    size = (34, 22)
    size = (680, 440)
    image = np.array(
        Image.open("images/lemur.png").convert("RGB").resize(
            size, Image.BOX)) / 255.0
    trimap = np.array(
        Image.open("images/lemur_trimap.png").convert("L").resize(
            size, Image.NEAREST)) / 255.0

    is_fg = trimap == 1.0
    is_bg = trimap == 0.0
    is_known = is_fg | is_bg
    is_unknown = ~is_known

    b = 100.0 * is_fg.flatten()
    c = 100.0 * is_known.flatten()

    shape = trimap.shape
    h, w = shape

    L = cf_laplacian(image)

    cache = {}
    C = scipy.sparse.diags(c)
    build_cache_L(L, shape, cache)

    # If the trimap changes, simply call this function again with the new vector c
    build_cache_c(c, shape, cache)

    M = lambda x: vcycle_step(x, shape, cache)

    x = cg(lambda x: L.dot(x) + c * x, b, M=M, callback=ProgressCallback())

    print("\nbaseline:")
    print("iteration      69 - 2.690681e-03 (0.00269068076571873623)")
    print()
    print("slight error due to discarding of C-offdiagonals")

    alpha = np.clip(x, 0, 1).reshape(h, w)

    import matplotlib.pyplot as plt
    for i, img in enumerate([image, trimap, alpha]):
        plt.subplot(1, 3, 1 + i)
        plt.imshow(img, cmap='gray')
        plt.axis('off')
    plt.show()
예제 #4
0
def main():
    print("loading images")

    size = (34, 22)
    size = (680, 440)
    image = np.array(
        Image.open("images/lemur.png").convert("RGB").resize(
            size, Image.BOX)) / 255.0
    trimap = np.array(
        Image.open("images/lemur_trimap.png").convert("L").resize(
            size, Image.NEAREST)) / 255.0

    is_fg = trimap == 1.0
    is_bg = trimap == 0.0
    is_known = is_fg | is_bg
    is_unknown = ~is_known

    b = 100.0 * is_fg.flatten()
    c = 100.0 * is_known.flatten()

    shape = trimap.shape
    h, w = shape

    L = cf_laplacian(image)
    C = scipy.sparse.diags(c)
    A = L + C

    M = vcycle(A, (h, w))

    x = cg(A, b, M=M, callback=ProgressCallback())

    print("\nbaseline:")
    print("iteration      69 - 2.690681e-03 (0.00269068076571873623)")

    alpha = np.clip(x, 0, 1).reshape(h, w)

    import matplotlib.pyplot as plt
    for i, img in enumerate([image, trimap, alpha]):
        plt.subplot(1, 3, 1 + i)
        plt.imshow(img, cmap='gray')
        plt.axis('off')
    plt.show()
예제 #5
0
def compute_alpha(image, trimap, laplacian_name, is_fg, is_bg, is_known):
    laplacians = dict(
        (laplacian.__name__, laplacian) for laplacian in LAPLACIANS)

    atol = ATOL * np.sum(is_known)

    if laplacian_name == "lkm_laplacian":
        L_matvec, diag_L = lkm_laplacian(image)

        lambda_value = 100.0

        c = lambda_value * is_known.ravel()
        b = lambda_value * is_fg.ravel()

        inv_diag_A = 1.0 / (diag_L + c)

        A = lambda x: L_matvec(x) + c * x
        # jacobi preconditioner for lkm_laplacian
        M = lambda x: inv_diag_A * x

    else:
        laplacian = laplacians[laplacian_name]

        A, b = make_linear_system(laplacian(image), trimap)

        preconditioner = {
            "knn_laplacian": jacobi,
            "rw_laplacian": jacobi,
            "cf_laplacian": ichol,
            "lbdm_laplacian": ichol,
            "uniform_laplacian": ichol,
        }[laplacian_name]

        M = preconditioner(A)

    x = cg(A, b, M=M, atol=atol)

    alpha = np.clip(x, 0, 1).reshape(trimap.shape)

    return alpha
예제 #6
0
def test_cg():
    np.random.seed(0)

    atol = 1e-10

    for n in [1, 5, 10]:
        x_true = np.random.rand(n)

        # make positive definite matrix
        A = np.random.rand(n, n)
        A += A.T + n * np.eye(n)

        b = A.dot(x_true)

        M_jacobi = np.diag(1.0 / np.diag(A))

        def precondition(x):
            return M_jacobi.dot(x)

        for x0 in [None, np.random.rand(n)]:
            for M in [None, M_jacobi, precondition]:
                for callback in [None, CounterCallback(), ProgressCallback()]:
                    x = cg(A,
                           b,
                           x0=x0,
                           M=M,
                           rtol=0,
                           atol=atol,
                           callback=callback)

                    r = np.linalg.norm(A.dot(x) - b)

                    assert np.linalg.norm(r) < 1e-10

                    if callback is not None:
                        assert 0 < callback.n < 20
예제 #7
0
def build_solver(solver_name, A, Acsr, Acsc, Acoo, AL, b, atol, rtol):
    # Construct a solver from matrix A and vector b.

    if solver_name == "cg_icholt":
        from pymatting import cg, ichol

        M = ichol(A, discard_threshold=1e-3, shifts=[0.002])

        return lambda: cg(A, b, M=M, atol=atol, rtol=0)

    if solver_name == "pyamg":
        import pyamg
        from pymatting import cg

        M = pyamg.smoothed_aggregation_solver(A).aspreconditioner()

        return lambda: cg(Acsr, b, M=M, atol=atol, rtol=0)

    if solver_name == "mumps":
        from solve_mumps import solve_mumps_coo, init_mpi, finalize_mpi

        init_mpi()

        return lambda: solve_mumps_coo(
            AL.data, AL.row, AL.col, b, is_symmetric=True)

    if solver_name == "petsc":
        from solve_petsc import solve_petsc_coo, init_petsc, finalize_petsc

        init_petsc()

        return lambda: solve_petsc_coo(
            Acoo.data, Acoo.row, Acoo.col, b, atol=atol, gamg_threshold=0.1)

    if solver_name == "amgcl":
        from solve_amgcl import solve_amgcl_csr

        return lambda: solve_amgcl_csr(
            Acsr.data, Acsr.indices, Acsr.indptr, b, atol=atol, rtol=0)

    if solver_name == "umfpack":
        # Alternatively:
        # return lambda: scipy.sparse.linalg.spsolve(Acsc, b, use_umfpack=True)

        import scikits.umfpack

        return lambda: scikits.umfpack.spsolve(A, b)

    if solver_name == "superlu":
        # Alternatively:
        # scipy.sparse.linalg.spsolve(A, b, use_umfpack=False)

        return lambda: scipy.sparse.linalg.splu(Acsc).solve(b)

    if solver_name == "eigen_cholesky":
        from solve_eigen import solve_eigen_cholesky_coo

        return lambda: solve_eigen_cholesky_coo(Acoo.data, Acoo.row, Acoo.col,
                                                b)

    if solver_name == "eigen_icholt":
        from solve_eigen import solve_eigen_icholt_coo

        # Choose shift hust large enough to not fail for given images
        # (might fail with larger/different images)
        initial_shift = 5e-4

        return lambda: solve_eigen_icholt_coo(Acoo.data,
                                              Acoo.row,
                                              Acoo.col,
                                              b,
                                              rtol=rtol,
                                              initial_shift=initial_shift)

    raise ValueError(f"Solver {solver_name} does not exist.")
예제 #8
0
 def solve_pyamg(A, b, atol):
     M = pyamg.smoothed_aggregation_solver(A).aspreconditioner()
     return cg(A, b, M=M, atol=atol, rtol=0)
예제 #9
0
 def solve_cg_icholt(A, b, atol):
     M = ichol(A, discard_threshold=1e-3, shifts=[0.002])
     return cg(A, b, M=M, atol=atol, rtol=0)
def main():
    indices = 1 + np.arange(27)
    scale = 1.0
    image_dir = "../data"
    info = {}
    
    laplacian_name = "lkm_laplacian"
    print(laplacian_name)
    
    errors = {}
    
    for index in indices:
        name = f"GT{index:02d}"
        print(name)
        
        image = load_image(f"{image_dir}/input_training_lowres/{name}.png", "rgb", scale, "bilinear")
        trimap = load_image(f"{image_dir}/trimap_training_lowres/Trimap1/{name}.png", "gray", scale, "bilinear")
        true_alpha = load_image(f"{image_dir}/gt_training_lowres/{name}.png", "gray", scale, "nearest")
        
        L_matvec, diag_L = lkm_laplacian(image)
        
        is_fg, is_bg, is_known, is_unknown = trimap_split(trimap)
        
        atol = 1e-7 * np.sum(is_known)
        
        lambda_value = 100.0
        
        c = lambda_value * is_known
        b = lambda_value * is_fg
        
        inv_diag_A = 1.0 / (diag_L + c)
        
        def A_matvec(x):
            return L_matvec(x) + c * x
        
        def jacobi(x):
            return inv_diag_A * x
        
        x = cg(A_matvec, b, M=jacobi, atol=atol)
        
        alpha = np.clip(x, 0, 1).reshape(trimap.shape)
        
        difference_unknown = np.abs(alpha - true_alpha)[is_unknown.reshape(trimap.shape)]
        
        error = np.linalg.norm(difference_unknown)
        
        errors[str(index)] = error
    
    info[laplacian_name] = errors
    
    for laplacian in LAPLACIANS:
        laplacian_name = laplacian.__name__
        print(laplacian_name)
        
        errors = {}
        
        for index in indices:
            name = f"GT{index:02d}"
            print(name)
            
            image = load_image(f"{image_dir}/input_training_lowres/{name}.png", "rgb", scale, "bilinear")
            trimap = load_image(f"{image_dir}/trimap_training_lowres/Trimap1/{name}.png", "gray", scale, "bilinear")
            true_alpha = load_image(f"{image_dir}/gt_training_lowres/{name}.png", "gray", scale, "nearest")
            
            A, b = make_linear_system(laplacian(image), trimap)
            
            is_fg, is_bg, is_known, is_unknown = trimap_split(trimap, flatten=False)
            
            atol = 1e-7 * np.sum(is_known)
            
            preconditioner = {
                "knn_laplacian": jacobi,
                "rw_laplacian": jacobi,
                "cf_laplacian": ichol,
                "lbdm_laplacian": ichol,
                "uniform_laplacian": ichol,
            }[laplacian_name]
            
            x = cg(A, b, M=preconditioner(A), atol=atol)
            
            alpha = np.clip(x, 0, 1).reshape(trimap.shape)
            
            difference_unknown = np.abs(alpha - true_alpha)[is_unknown]
            
            error = np.linalg.norm(difference_unknown)
            
            errors[str(index)] = error
    
        info[laplacian_name] = errors
    
    with open("results/laplacians.json", "w") as f:
        print(info)
        json.dump(info, f, indent=4)
예제 #11
0
def main():
    print("loading images")

    mses = []

    for idx in range(1, 28):
        image = np.array(
            Image.open(f"{DATASET_DIRECTORY}/input_training_lowres/GT%02d.png"
                       % idx).convert("RGB")) / 255.0
        trimap = np.array(
            Image.open(
                f"{DATASET_DIRECTORY}/trimap_training_lowres/Trimap1/GT%02d.png"
                % idx).convert("L")) / 255.0
        alpha_gt = np.array(
            Image.open(f"{DATASET_DIRECTORY}/gt_training_lowres/GT%02d.png" %
                       idx).convert("L")) / 255.0

        is_fg = trimap == 1.0
        is_bg = trimap == 0.0
        is_known = is_fg | is_bg
        is_unknown = ~is_known

        b = 100.0 * is_fg.flatten()
        c = 100.0 * is_known.flatten()

        shape = trimap.shape
        h, w = shape

        L = cf_laplacian(image)

        cache = {}
        C = scipy.sparse.diags(c)
        build_cache_L(L, shape, cache)

        # If the trimap changes, simply call this function again with the new vector c
        build_cache_c(c, shape, cache)

        M = lambda x: vcycle_step(x, shape, cache)

        x = cg(lambda x: L.dot(x) + c * x, b, M=M, callback=ProgressCallback())

        alpha = np.clip(x, 0, 1).reshape(h, w)

        difference = np.abs(alpha - alpha_gt)

        mse = np.mean(np.square(difference[is_unknown]))

        print("MSE:", mse)

        mses.append(mse)

        continue

        import matplotlib.pyplot as plt
        for i, img in enumerate([image, trimap, alpha]):
            plt.subplot(1, 3, 1 + i)
            plt.imshow(img, cmap='gray')
            plt.axis('off')
        plt.show()

    print("mean MSE:", np.mean(mses))
    print()
    print("Expected:")
    print("mean MSE: 0.021856688900784647")
예제 #12
0
def test_lkm():
    index = 1
    scale = 0.2
    atol = 1e-5
    epsilon = 1e-7
    radius = 2
    image_dir = "data"

    errors = []

    name = f"GT{index:02d}"
    # print(name)

    image = load_image(
        f"{image_dir}/input_training_lowres/{name}.png", "rgb", scale, "bilinear"
    )
    trimap = load_image(
        f"{image_dir}/trimap_training_lowres/Trimap1/{name}.png",
        "gray",
        scale,
        "bilinear",
    )
    true_alpha = load_image(
        f"{image_dir}/gt_training_lowres/{name}.png", "gray", scale, "nearest"
    )

    L_lkm, diag_L_lkm = lkm_laplacian(image, epsilon=epsilon, radius=radius)

    L_cf = cf_laplacian(image, epsilon=epsilon, radius=radius)

    A_cf, b, c = make_linear_system(L_cf, trimap, return_c=True)

    def A_lkm(x):
        return L_lkm(x) + c * x

    inv_diag_A_lkm = 1.0 / (diag_L_lkm + c)

    def jacobi_lkm(r):
        return inv_diag_A_lkm * r

    jacobi_cf = jacobi(A_cf)

    lkm_callback = ProgressCallback()
    cf_callback = ProgressCallback()

    x_lkm = cg(A_lkm, b, M=jacobi_lkm)
    x_cf = cg(A_cf, b, M=jacobi_cf)

    if 0:
        # show result
        show_images(
            [x_lkm.reshape(trimap.shape), x_cf.reshape(trimap.shape),]
        )

    difference = np.linalg.norm(x_lkm - x_cf)

    # print("norm(x_lkm - x_cf):")
    # print(difference)
    # print("iterations:")
    # print("lkm:", lkm_callback.n)
    # print("cf:", cf_callback.n)

    assert difference < 1e-5
    assert abs(lkm_callback.n - cf_callback.n) <= 2