예제 #1
0
def estimate_alpha_rw(
    image, trimap, preconditioner=None, laplacian_kwargs={}, cg_kwargs={}
):
    """
    Estimate alpha from an input image and an input trimap using Learning Based Digital Matting as proposed by :cite:`grady2005random`.

    Parameters
    -----------------
    image: numpy.ndarray
        Image with shape :math:`h \\times  w \\times d` for which the alpha matte should be estimated
    trimap: numpy.ndarray
        Trimap with shape :math:`h \\times  w \\times 1` of the image
    preconditioner: function or scipy.sparse.linalg.LinearOperator
        Function or sparse matrix that applies the preconditioner to a vector (default: jacobi)
    laplacian_kwargs: dictionary
        Arguments passed to the :code:`rw_laplacian` function
    cg_kwargs: dictionary
        Arguments passed to the :code:`cg` solver

    Returns
    ----------------
    alpha: numpy.ndarray
        Estimated alpha matte
    """
    if preconditioner is None:
        preconditioner = jacobi

    A, b = make_linear_system(rw_laplacian(image, **laplacian_kwargs), trimap)

    x = cg(A, b, M=preconditioner(A), **cg_kwargs)

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

    return alpha
예제 #2
0
def estimate_alpha_lkm(image, trimap, laplacian_kwargs={}, cg_kwargs={}):
    """
    Estimate alpha from an input image and an input trimap as described in Fast Matting Using Large Kernel Matting Laplacian Matrices by :cite:`he2010fast`.

    Parameters
    ----------
    image: numpy.ndarray
        Image with shape :math:`h \\times  w \\times d` for which the alpha matte should be estimated
    trimap: numpy.ndarray
        Trimap with shape :math:`h \\times  w` of the image
    laplacian_kwargs: dictionary
        Arguments passed to the :code:`lkm_laplacian` function
    cg_kwargs: dictionary
        Arguments passed to the :code:`cg` solver

    Returns
    -------
    alpha: numpy.ndarray
        Estimated alpha matte

    Example
    -------
    >>> from pymatting import *
    >>> image = load_image("data/lemur/lemur.png", "RGB")
    >>> trimap = load_image("data/lemur/lemur_trimap.png", "GRAY")
    >>> alpha = estimate_alpha_lkm(
    ...     image,
    ...     trimap,
    ...     laplacian_kwargs={"epsilon": 1e-6, "radius": 15},
    ...     cg_kwargs={"maxiter":2000})

    """

    sanity_check_image(image)

    L_matvec, diag_L = lkm_laplacian(image, **laplacian_kwargs)

    is_fg, is_bg, is_known, is_unknown = trimap_split(trimap)

    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, **cg_kwargs)

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

    return alpha
예제 #3
0
def estimate_alpha_lbdm(image,
                        trimap,
                        preconditioner=None,
                        laplacian_kwargs={},
                        cg_kwargs={}):
    """
    Estimate alpha from an input image and an input trimap using Learning Based Digital Matting as proposed by :cite:`zheng2009learning`.

    Parameters
    ----------
    image: numpy.ndarray
        Image with shape :math:`h \\times  w \\times d` for which the alpha matte should be estimated
    trimap: numpy.ndarray
        Trimap with shape :math:`h \\times  w` of the image
    preconditioner: function or scipy.sparse.linalg.LinearOperator
        Function or sparse matrix that applies the preconditioner to a vector (default: ichol)
    laplacian_kwargs: dictionary
        Arguments passed to the :code:`lbdm_laplacian` function
    cg_kwargs: dictionary
        Arguments passed to the :code:`cg` solver

    Returns
    -------
    alpha: numpy.ndarray
        Estimated alpha matte

    Example
    -------
    >>> from pymatting import *
    >>> image = load_image("data/lemur/lemur.png", "RGB")
    >>> trimap = load_image("data/lemur/lemur_trimap.png", "GRAY")
    >>> alpha = estimate_alpha_lbdm(
    ...     image,
    ...     trimap,
    ...     laplacian_kwargs={"epsilon": 1e-6},
    ...     cg_kwargs={"maxiter":2000})

    """
    if preconditioner is None:
        preconditioner = ichol

    sanity_check_image(image)

    A, b = make_linear_system(lbdm_laplacian(image, **laplacian_kwargs),
                              trimap)

    x = cg(A, b, M=preconditioner(A), **cg_kwargs)

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

    return alpha
예제 #4
0
def estimate_alpha_knn(image,
                       trimap,
                       preconditioner=None,
                       laplacian_kwargs={},
                       cg_kwargs={}):
    """
    Estimate alpha from an input image and an input trimap using KNN Matting similar to :cite:`chen2013knn`.
    See `knn_laplacian` for more details.

    Parameters
    ----------
    image: numpy.ndarray
        Image with shape :math:`h \\times  w \\times d` for which the alpha matte should be estimated
    trimap: numpy.ndarray
        Trimap with shape :math:`h \\times  w` of the image
    preconditioner: function or scipy.sparse.linalg.LinearOperator
        Function or sparse matrix that applies the preconditioner to a vector (default: jacobi)
    laplacian_kwargs: dictionary
        Arguments passed to the :code:`knn_laplacian` function
    cg_kwargs: dictionary
        Arguments passed to the :code:`cg` solver

    Returns
    -------
    alpha: numpy.ndarray
        Estimated alpha matte

    Example
    -------
    >>> from pymatting import *
    >>> image = load_image("data/lemur/lemur.png", "RGB")
    >>> trimap = load_image("data/lemur/lemur_trimap.png", "GRAY")
    >>> alpha = estimate_alpha_knn(
    ...     image,
    ...     trimap,
    ...     laplacian_kwargs={"n_neighbors": [15, 10]},
    ...     cg_kwargs={"maxiter":2000})
    """
    if preconditioner is None:
        preconditioner = jacobi

    sanity_check_image(image)

    A, b = make_linear_system(knn_laplacian(image, **laplacian_kwargs), trimap)

    x = cg(A, b, M=preconditioner(A), **cg_kwargs)

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

    return alpha
예제 #5
0
def estimate_alpha_lkm(image, trimap, laplacian_kwargs={}, cg_kwargs={}):
    """
    Estimate alpha from an input image and an input trimap using Learning Based Digital Matting as proposed by :cite:`he2010fast`.

    Parameters
    -----------------
    image: numpy.ndarray
        Image with shape :math:`h \\times  w \\times d` for which the alpha matte should be estimated
    trimap: numpy.ndarray
        Trimap with shape :math:`h \\times  w \\times 1` of the image
    laplacian_kwargs: dictionary
        Arguments passed to the :code:`lkm_laplacian` function
    cg_kwargs: dictionary
        Arguments passed to the :code:`cg` solver

    Returns
    ----------------
    alpha: numpy.ndarray
        Estimated alpha matte
    """
    L_matvec, diag_L = lkm_laplacian(image, **laplacian_kwargs)

    is_fg, is_bg, is_known, is_unknown = trimap_split(trimap)

    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, **cg_kwargs)

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

    return alpha
예제 #6
0
def estimate_alpha_cf(image,
                      trimap,
                      preconditioner=None,
                      laplacian_kwargs={},
                      cg_kwargs={}):
    """
    Estimate alpha from an input image and an input trimap using Closed-Form Alpha Matting as proposed by :cite:`levin2007closed`.

    Parameters
    -----------------
    image: numpy.ndarray
        Image with shape :math:`h \\times  w \\times d` for which the foreground should be estimated
    trimap: numpy.ndarray
        Trimap with shape :math:`h \\times  w \\times 1` of the image
    preconditioner: function or scipy.sparse.linalg.LinearOperator
        Function or sparse matrix that applies the preconditioner to a vector (default: ichol)
    laplacian_kwargs: dictionary
        Arguments passed to the :code:`cf_laplacian` function
    cg_kwargs: dictionary
        Arguments passed to the :code:`cg`

    Returns
    ----------------
    alpha: numpy.ndarray
        Estimated alpha matte
    """
    if preconditioner is None:
        preconditioner = ichol

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

    x = cg(A, b, M=preconditioner(A), **cg_kwargs)

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

    return alpha
예제 #7
0
def estimate_foreground_cf(
    image,
    alpha,
    regularization=1e-5,
    rtol=1e-5,
    neighbors=[(-1, 0), (1, 0), (0, -1), (0, 1)],
    return_background=False,
    foreground_guess=None,
    background_guess=None,
    ichol_kwargs={},
    cg_kwargs={},
):
    """Estimates the foreground of an image given alpha matte and image.

    This method is based on the publication :cite:`levin2007closed`.

    Parameters
    ----------
    image: numpy.ndarray
        Input image with shape :math:`h \\times  w \\times d`
    alpha: numpy.ndarray
        Input alpha matte with shape :math:`h \\times  w \\times 1`
    regularization: float
        Regularization strength :math:`\\epsilon`, defaults to :math:`10^{-5}`
    neighbors: list of tuples of ints
        List of relative positions that define the neighborhood of a pixel
    return_background: bool
        Whether to return the estimated background in addition to the foreground
    foreground_guess: numpy.ndarray
        An initial guess for the foreground image in order to accelerate convergence.
        Using input image by default.
    background_guess: numpy.ndarray
        An initial guess for the background image.
        Using input image by default.
    ichol_kwargs: dictionary
        Keyword arguments for the incomplete Cholesky preconditioner
    cg_kwargs: dictionary
        Keyword arguments for the conjugate gradient descent solver

    Returns
    -------
    F: numpy.ndarray
        Extracted foreground
    B: numpy.ndarray
        Extracted background (not returned by default)

    Example
    -------
    >>> from pymatting import *
    >>> image = load_image("data/lemur/lemur.png", "RGB")
    >>> alpha = load_image("data/lemur/lemur_alpha.png", "GRAY")
    >>> F = estimate_foreground_cf(image, alpha, return_background=False)
    >>> F, B = estimate_foreground_cf(image, alpha, return_background=True)


    See Also
    --------
    stack_images: This function can be used to place the foreground on a new background.
    """
    h, w, d = image.shape

    assert alpha.shape == (h, w)

    n = w * h

    a = alpha.flatten()

    S = None
    for dx, dy in neighbors:
        # directional derivative
        D = sparse_conv_matrix_with_offsets(w, h, [1.0, -1.0], [0, dx],
                                            [0, dy])

        S2 = D.T.dot(scipy.sparse.diags(regularization +
                                        np.abs(D.dot(a)))).dot(D)

        S = S2 if S is None else S + S2

        del D, S2

    V = scipy.sparse.bmat([[S, None], [None, S]])

    del S

    U = scipy.sparse.bmat([[scipy.sparse.diags(a), scipy.sparse.diags(1 - a)]])

    A = U.T.dot(U) + V

    A.sum_duplicates()

    del V

    # Compute preconditioner for faster convergence
    precondition = ichol(A, **ichol_kwargs)

    # By default use input image as initialization
    foreground = (image
                  if foreground_guess is None else foreground_guess).copy()
    background = (image
                  if background_guess is None else background_guess).copy()

    # For each image color channel
    for channel in range(d):
        image_channel = image[:, :, channel].flatten()

        b = U.T.dot(image_channel)

        # Initialization vector for conjugate gradient descent
        f0 = foreground[:, :, channel].flatten()
        b0 = background[:, :, channel].flatten()
        fb = np.concatenate([f0, b0])

        # Solve linear system
        # A fb = b
        # for fb using conjugate gradient descent
        fb = cg(A, b, x0=fb, M=precondition, rtol=rtol, **cg_kwargs)

        foreground[:, :, channel] = fb[:n].reshape(h, w)
        background[:, :, channel] = fb[n:].reshape(h, w)

    foreground = np.clip(foreground, 0, 1)
    background = np.clip(background, 0, 1)

    if return_background:
        return foreground, background

    return foreground
def estimate_alpha_cf(
    image, trimap, preconditioner=None, laplacian_kwargs={}, cg_kwargs={}
):
    """
    Estimate alpha from an input image and an input trimap using Closed-Form Alpha Matting as proposed by :cite:`levin2007closed`.

    Parameters
    ----------
    image: numpy.ndarray
        Image with shape :math:`h \\times  w \\times d` for which the alpha matte should be estimated
    trimap: numpy.ndarray
        Trimap with shape :math:`h \\times  w \\times 1` of the image
    preconditioner: function or scipy.sparse.linalg.LinearOperator
        Function or sparse matrix that applies the preconditioner to a vector (default: ichol)
    laplacian_kwargs: dictionary
        Arguments passed to the :code:`cf_laplacian` function
    cg_kwargs: dictionary
        Arguments passed to the :code:`cg` solver
    is_known: numpy.ndarray
        Binary mask of pixels for which to compute the laplacian matrix.
        Providing this parameter might improve performance if few pixels are unknown.

    Returns
    -------
    alpha: numpy.ndarray
        Estimated alpha matte

    Example
    -------
    >>> from pymatting import *
    >>> image = load_image("data/lemur/lemur.png", "RGB")
    >>> trimap = load_image("data/lemur/lemur_trimap.png", "GRAY")
    >>> alpha = estimate_alpha_cf(
    ...     image,
    ...     trimap,
    ...     laplacian_kwargs={"epsilon": 1e-6},
    ...     cg_kwargs={"maxiter":2000})
    """
    if preconditioner is None:
        preconditioner = ichol

    h, w = trimap.shape[:2]

    is_fg, is_bg, is_known, is_unknown = trimap_split(trimap)

    L = cf_laplacian(image, **laplacian_kwargs, is_known=is_known)

    # Split Laplacian matrix L into
    #
    #     [L_U   R ]
    #     [R^T   L_K]
    #
    # and then solve L_U x_U = -R is_fg_K for x where K (is_known) corresponds to
    # fixed pixels and U (is_unknown) corresponds to unknown pixels. For reference, see
    # Grady, Leo, et al. "Random walks for interactive alpha-matting." Proceedings of VIIP. Vol. 2005. 2005.

    L_U = L[is_unknown, :][:, is_unknown]

    R = L[is_unknown, :][:, is_known]

    m = is_fg[is_known]

    x = trimap.copy().ravel()

    x[is_unknown] = cg(L_U, -R.dot(m), M=preconditioner(L_U), **cg_kwargs)

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

    return alpha