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
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
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
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
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
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
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