def bayesian_matte(img, trimap):
        img = img / 255
        h, w, c = img.shape
        alpha = np.zeros((h, w))

        fg_mask = trimap == 255
        bg_mask = trimap == 0
        uk_mask = True ^ np.logical_or(fg_mask, bg_mask)
        foreground = img * np.repeat(fg_mask[:, :, np.newaxis], 3, axis=2)
        background = img * np.repeat(bg_mask[:, :, np.newaxis], 3, axis=2)

        alpha[fg_mask] = 1
        alpha[uk_mask] = np.nan

        gaussian_weights = gauss2d_distribution((N, N), sigma)
        gaussian_weights = gaussian_weights / np.max(gaussian_weights)

        num_uk = np.sum(uk_mask)
        uk_tmp_mask = uk_mask
        kernel = np.ones((3, 3))
        n = 1

        # 每次求解unknown区域最外一层像素
        while n < num_uk:
            uk_tmp_mask = cv2.erode(uk_tmp_mask.astype(np.uint8), kernel, iterations=1)
            uk_pixels = np.logical_and(np.logical_not(uk_tmp_mask), uk_mask)

            Y, X = np.nonzero(uk_pixels)
            for i in range(Y.shape[0]):
                if n % 100 == 0:
                    print(n, num_uk)
                y, x = Y[i], X[i]
                p = img[y, x]
                a = BayesianMatting.get_window(alpha[:, :, np.newaxis], x, y, N)[:, :, 0]

                f_pixels = BayesianMatting.get_window(foreground, x, y, N)
                f_pixels, f_weights = BayesianMatting._get_pixels_and_weights(f_pixels, gaussian_weights, a, N)

                b_pixels = BayesianMatting.get_window(background, x, y, N)
                b_pixels, b_weights = BayesianMatting._get_pixels_and_weights(b_pixels, gaussian_weights, (1-a), N)

                if len(f_weights) < minN or len(b_weights) < minN:
                    continue

                mu_f, sigma_f = clustFunc(f_pixels, f_weights)
                mu_b, sigma_b = clustFunc(b_pixels, b_weights)

                alpha_init = np.nanmean(a.ravel())
                # Solve for F,B for all cluster pairs
                f, b, alphaT = BayesianMatting._solve(mu_f, sigma_f, mu_b, sigma_b, p, 0.01, alpha_init, 1e-6, 50)
                foreground[y, x] = f.ravel()
                background[y, x] = b.ravel()
                alpha[y, x] = alphaT
                uk_mask[y, x] = 0
                n += 1
        return alpha
def bayesian_matte(img, trimap, sigma=8, N=25, minN=10):
    img = img / 255

    h, w, c = img.shape
    alpha = np.zeros((h, w))

    fg_mask = trimap == 255
    bg_mask = trimap == 0
    unknown_mask = True ^ np.logical_or(fg_mask, bg_mask)
    foreground = img * np.repeat(fg_mask[:, :, np.newaxis], 3, axis=2)
    background = img * np.repeat(bg_mask[:, :, np.newaxis], 3, axis=2)

    gaussian_weights = matlab_style_gauss2d((N, N), sigma)
    gaussian_weights = gaussian_weights / np.max(gaussian_weights)

    alpha[fg_mask] = 1
    F = np.zeros(img.shape)
    B = np.zeros(img.shape)
    alphaRes = np.zeros(trimap.shape)

    n = 1
    alpha[unknown_mask] = np.nan
    nUnknown = np.sum(unknown_mask)
    unkreg = unknown_mask

    kernel = np.ones((3, 3))
    while n < nUnknown:
        unkreg = cv2.erode(unkreg.astype(np.uint8), kernel, iterations=1)
        unkpixels = np.logical_and(np.logical_not(unkreg), unknown_mask)

        Y, X = np.nonzero(unkpixels)

        for i in range(Y.shape[0]):
            if n % 100 == 0:
                print(n, nUnknown)
            y, x = Y[i], X[i]
            p = img[y, x]
            # Try cluster Fg, Bg in p's known neighborhood

            # take surrounding alpha values
            a = get_window(alpha[:, :, np.newaxis], x, y, N)[:, :, 0]

            # Take surrounding foreground pixels
            f_pixels = get_window(foreground, x, y, N)
            f_weights = (a**2 * gaussian_weights).ravel()

            f_pixels = np.reshape(f_pixels, (N * N, 3))
            posInds = np.nan_to_num(f_weights) > 0
            f_pixels = f_pixels[posInds, :]
            f_weights = f_weights[posInds]

            # Take surrounding foreground pixels
            b_pixels = get_window(background, x, y, N)
            b_weights = ((1 - a)**2 * gaussian_weights).ravel()

            b_pixels = np.reshape(b_pixels, (N * N, 3))
            posInds = np.nan_to_num(b_weights) > 0
            b_pixels = b_pixels[posInds, :]
            b_weights = b_weights[posInds]

            # if not enough data, return to it later...
            if len(f_weights) < minN or len(b_weights) < minN:
                continue
            # Partition foreground and background pixels to clusters (in a weighted manner)
            mu_f, sigma_f = obc.clustFunc(f_pixels, f_weights)
            mu_b, sigma_b = obc.clustFunc(b_pixels, b_weights)

            alpha_init = np.nanmean(a.ravel())
            # Solve for F,B for all cluster pairs
            f, b, alphaT = solve(mu_f, sigma_f, mu_b, sigma_b, p, 0.01,
                                 alpha_init, 50, 1e-6)
            foreground[y, x] = f.ravel()
            background[y, x] = b.ravel()
            alpha[y, x] = alphaT
            unknown_mask[y, x] = 0
            n += 1

    return alpha
    def bayesian_matte(self, img, trimap):
        img = img.astype('float') / 255.
        h, w, c = img.shape

        alpha = np.zeros((h, w))  # initial alpha

        # forefround, background, unkown, mask
        fg_mask = (trimap == 255)
        bg_mask = (trimap == 0)
        unknown_mask = True ^ np.logical_or(fg_mask, bg_mask)
        foreground = img * np.repeat(fg_mask[:, :, np.newaxis], 3, axis=2)
        background = img * np.repeat(bg_mask[:, :, np.newaxis], 3, axis=2)

        gaussian_weights = self.gaussian2d((self.N, self.N), self.sigma)
        gaussian_weights = gaussian_weights / np.max(gaussian_weights)

        alpha[fg_mask] = 1
        F = np.zeros(img.shape)
        B = np.zeros(img.shape)
        alphaRes = np.zeros(trimap.shape)

        n = 1
        alpha[unknown_mask] = np.nan
        num_unknown = np.sum(unknown_mask)
        unkreg = unknown_mask.copy()
        kernel = np.ones((3, 3))
        while n < num_unknown:
            unkreg = cv2.erode(unkreg.astype(np.uint8), kernel, iterations=1)
            unkpixels = np.logical_and(np.logical_not(unkreg), unknown_mask)

            Y, X = np.nonzero(unkpixels)
            for i in range(Y.shape[0]):
                y, x = Y[i], X[i]
                p = img[y, x]
                a = self.get_window(alpha[:, :, np.newaxis], x, y,
                                    self.N)[:, :, 0]  # surrounding alpha

                ## foreground
                f_pixels = self.get_window(
                    foreground, x, y, self.N)  # surronding foreground pixels
                f_weights = (a**2 * gaussian_weights).ravel()
                f_pixels = np.reshape(f_pixels, (self.N * self.N, 3))
                posInds = np.nan_to_num(f_weights) > 0  # select known alpha
                f_pixels = f_pixels[posInds, :]
                f_weights = f_weights[posInds]

                ## background
                b_pixels = self.get_window(background, x, y, self.N)
                b_weights = ((1 - a)**2 * gaussian_weights).ravel()
                b_pixels = np.reshape(b_pixels, (self.N * self.N, 3))
                posInds = np.nan_to_num(b_weights) > 0
                b_pixels = b_pixels[posInds, :]
                b_weights = b_weights[posInds]

                ## if not enough data, return to it later
                if len(f_weights) < self.minN or len(b_weights) < self.minN:
                    continue

                ## cluster
                mu_f, sigma_f = clustFunc(
                    f_pixels,
                    f_weights)  #(num_cluster1, 3), (num_cluster1, 3, 3)
                mu_b, sigma_b = clustFunc(
                    b_pixels,
                    b_weights)  #(num_cluster2, 3), (num_cluster2, 3, 3)

                alpha_init = np.nanmean(a.ravel())

                ## solver
                f, b, alphaT = self.solve(mu_f, sigma_f, mu_b, sigma_b, p,
                                          0.01, alpha_init, 50, 1e-6)