-1

I have this image:

enter image description here

And for the beard, I have this mask:

enter image description here

I want to cut the beard out using the mask with a transparent background like this:

enter image description here

I followed this SO post's attempt. Here it is:

for img in input_images:
    gaberiel = Image.open(path + '/gaberiel-images/' + img)

    beard_mask = imread(path + '/gaberiel-masks/' + 'beard_binary_' + img[:-4] + '.png', cv2.IMREAD_GRAYSCALE)

    gaberiel_x, gaberiel_y = gaberiel.size
    beard_mask_x, beard_mask_y, _ = beard_mask.shape

    x_beard_mask= min(gaberiel_x, beard_mask_x)
    x_half_beard_mask = beard_mask.shape[0] // 2

    mask_beard = beard_mask[x_half_beard_mask - x_beard_mask // 2: x_half_beard_mask + x_beard_mask // 2 + 1, :gaberiel_y]

    gaberiel_width_half = gaberiel.size[1] // 2
    gaberiel_to_mask = gaberiel[:, gaberiel_width_half - x_half_beard_mask:gaberiel_width_half + x_half_beard_mask]
    masked = cv2.bitwise_and(gaberiel_to_mask, gaberiel_to_mask, mask=mask_beard)

    tmp = cv2.cvtColor(masked, cv2.COLOR_BGR2GRAY)
    _, alpha = cv2.threshold(tmp, 0, 255, cv2.THRESH_BINARY)
    b, g, r = cv2.split(masked)
    rgba = [b, g, r, alpha]
    masked_tr = cv2.merge(rgba, 4)

    plt.axis('off')
    plt.imshow(masked_tr)

But this is the error I am getting:

gaberiel_to_mask = gaberiel[:, gaberiel_width_half - x_half_beard_mask:gaberiel_width_half + x_half_beard_mask]
TypeError: 'PngImageFile' object is not subscriptable

I think that my attempt is overall bad. Is there a way I can simplify this process?

Onur-Andros Ozbek
  • 2,998
  • 2
  • 29
  • 78

1 Answers1

2

Make sure your mask is of the same size as your image and then use the function as in below:

def apply_mask(image, mask):
    # Convert to numpy arrays
    image = np.array(image)
    mask = np.array(mask)
    # Convert grayscale image to RGB
    mask = np.stack((mask,)*3, axis=-1)
    # Multiply arrays
    resultant = image*mask
    return resultant

image = ...
mask = ...

resultant = apply_mask(image, mask)

Result:

enter image description here

For the code to work, the image array must be in range 0-255 and the mask array must be in binary (either 0 or 1). In the mask array, the area of beard must have pixel value of 1 and the rest 0, so that multiplying the image with the mask will give the desired image as shown above.

Save image as a png with transparent background:

import matplotlib.pyplot as plt
plt.plot(resultant)
plt.savefig('image.png', transparent=True)
MD Mushfirat Mohaimin
  • 1,966
  • 3
  • 10
  • 22