4
votes

Comment masquer l'image avec un masque binaire

Supposons que j'ai une image en niveaux de gris ici: entrez la description de l'image ici

Et une image masquée binaire ici: entrez la description de l'image ici

Avec les mêmes dimensions et forme. Comment générer quelque chose comme ceci: entrez la description de l'image ici

Où les valeurs indiquées par le 1 dans le masque binaire sont les valeurs réelles, et les valeurs qui sont 0 dans le masque sont nulles dans l'image finale.


4 commentaires

les multiplier?


Ce ne sont pas des images en niveaux de gris.


J'utilise matplotlib avec la palette de couleurs viridis pour qu'ils n'apparaissent pas gris, mais ils ne sont pas RVB.


Vos images ne sont pas de la même taille. Veuillez également toujours publier une image correcte sans carte de couleur; sinon, vous confondez les gens et compliquez également la démonstration d'une solution pour les images en niveaux de gris.


3 Réponses :


2
votes

Utilisez cv2.bitwise_and pour masquer une image avec un masque binaire. Tous les pixels blancs sur le masque (valeurs avec 1) seront conservés tandis que les pixels noirs (valeur avec 0) seront ignorés. Voici un exemple:

Image d'entrée (gauche), masque (droite)

Résultat après masquage

Code

import cv2
import numpy as np

# Load image, create mask, and draw white circle on mask
image = cv2.imread('1.jpeg')
mask = np.zeros(image.shape, dtype=np.uint8)
mask = cv2.circle(mask, (260, 300), 225, (255,255,255), -1) 

# Mask input image with binary mask
result = cv2.bitwise_and(image, mask)
# Color background white
result[mask==0] = 255 # Optional

cv2.imshow('image', image)
cv2.imshow('mask', mask)
cv2.imshow('result', result)
cv2.waitKey()


0 commentaires

0
votes

Voici deux autres façons d'utiliser Python Opencv. Le premier est similaire à celui de @nathancy. Le second utilise la multiplication pour faire le masquage. J'utilise les mêmes images que celles fournies par @nathancy:

entrez la description de l'image ici

entrez la description de l'image ici

import cv2
import numpy as np

# read image
img = cv2.imread('pink_flower.png')

#mask it - method 1:
# read mask as grayscale in range 0 to 255
mask1 = cv2.imread('pink_flower_mask.png',0)
result1 = img.copy()
result1[mask1 == 0] = 0
result1[mask1 != 0] = img[mask1 != 0]

# mask it - method 2:
# read mask normally, but divide by 255.0, so range is 0 to 1 as float
mask2 = cv2.imread('pink_flower_mask.png') / 255.0
# mask by multiplication, clip to range 0 to 255 and make integer
result2 = (img * mask2).clip(0, 255).astype(np.uint8)

cv2.imshow('image', img)
cv2.imshow('mask1', mask1)
cv2.imshow('masked image1', result1)
cv2.imshow('masked image2', result2)
cv2.waitKey(0)
cv2.destroyAllWindows()

# save results
cv2.imwrite('pink_flower_masked1.png', result1)
cv2.imwrite('pink_flower_masked2.png', result2)


Les résultats sont les mêmes pour les deux méthodes:

entrez la description de l'image ici


0 commentaires

0
votes

Les autres réponses n'ont pas fonctionné pour moi. À l'époque, je passais tellement de temps à trouver une bonne fonction de masquage. Voici deux réponses simples avec numpy uniquement.

import numpy as np

arr = np.arange(27).reshape(3,3,3) #3 channel image
mask = np.zeros(shape=(3,3))
mask[1,1] = 1 # binary mask
mask_3d = np.stack((mask,mask,mask),axis=0) #3 channel mask

## Answer 1
# Simply multiply the image array with the mask

masked_arr = arr*mask_3d

## Answer 2
# Use the where function in numpy

masked_arr = np.where(mask_3d==1,arr,mask_3d)

#Both answer gives
print(masked_arr)

array([[[ 0.,  0.,  0.],
        [ 0.,  4.,  0.],
        [ 0.,  0.,  0.]],

       [[ 0.,  0.,  0.],
        [ 0., 13.,  0.],
        [ 0.,  0.,  0.]],

       [[ 0.,  0.,  0.],
        [ 0., 22.,  0.],
        [ 0.,  0.,  0.]]])


0 commentaires