2012-05-06 4 views
15

Come posso applicare una maschera a un'immagine a colori nell'ultima associazione Python (cv2)? Nel precedente collegamento con Python il modo più semplice era usare cv.Copy ad es.OpenCV - Applica maschera a un'immagine a colori

cv.Copy(dst, src, mask)

Ma questa funzione non è disponibile nel legame CV2. C'è qualche soluzione alternativa senza utilizzare il codice boilerplate?

+0

cosa stai cercando di fare? dal momento che ha il supporto di numpy, puoi usare le funzioni di numpy. –

+0

Sto facendo un po 'di filtraggio nello spazio colore HSV all'immagine originale – pzo

risposta

30

Qui è possibile utilizzare la funzione cv2.bitwise_and se si dispone già dell'immagine della maschera.

Per controllare il codice qui sotto

img = cv2.imread('lena.jpg') 
mask = cv2.imread('mask.png',0) 
res = cv2.bitwise_and(img,img,mask = mask) 

L'uscita sarà come segue per un'immagine di lena, e per maschera rettangolare.

enter image description here

+0

Sto provando a fare qualcosa di simile. La maschera dovrebbe essere nera o bianca? Scusa per la domanda di base, sono un principiante con opencv. Grazie –

+2

Ya, sei corretto, maschera dovrebbe essere nero/bianco e singolo canale. Qualunque sia la regione nell'immagine che desideri elaborare, quella regione in maschera dovrebbe essere bianca, tutto il resto è nero. E non devi scusarti per aver fatto questa domanda, tutti sono principianti quando iniziano a studiare, anche io. –

+0

Grazie mille Abid! Lo proverò questa notte quando torno a casa. Devo dividere un'immagine in diverse regioni (e ripetere questo processo in diverse immagini). Saluti! –

-1

Risposta data da Abid Rahman K non è del tutto corretto. Ho anche provato e trovato molto utile ma sono rimasto bloccato.

Ecco come copio l'immagine con una data maschera.

x, y = np.where(mask!=0) 
pts = zip(x, y) 
# Assuming dst and src are of same sizes 
for pt in pts: 
    dst[pt] = src[pt] 

Questo è un po 'lento ma dà risultati corretti.

MODIFICA:

Via Pythonica.

+0

Cosa c'è di sbagliato nella risposta di Abid? –

+0

Non è necessario reinventare la ruota qui quando il metodo "bitwise_and" in cv2 funziona al 100% come richiesto. Non solo, ma è molto ovvio su ciò che fa. –

6

Bene, ecco una soluzione se si desidera che lo sfondo sia diverso da un colore nero solido. Abbiamo solo bisogno di invertire la maschera e applicarla in un'immagine di sfondo della stessa dimensione e quindi combinare sia lo sfondo che il primo piano. Un professionista di questa soluzione è che lo sfondo potrebbe essere qualsiasi cosa (anche altra immagine).

Questo esempio viene modificato da Hough Circle Transform. La prima immagine è il logo OpenCV, secondo la maschera originale, terzo lo sfondo + primo piano combinato.

apply mask and get a customized background

# http://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_houghcircles/py_houghcircles.html 
import cv2 
import numpy as np 

# load the image 
img = cv2.imread('E:\\FOTOS\\opencv\\opencv_logo.png') 
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) 

# detect circles 
gray = cv2.medianBlur(cv2.cvtColor(img, cv2.COLOR_RGB2GRAY), 5) 
circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, 20, param1=50, param2=50, minRadius=0, maxRadius=0) 
circles = np.uint16(np.around(circles)) 

# draw mask 
mask = np.full((img.shape[0], img.shape[1]), 0, dtype=np.uint8) # mask is only 
for i in circles[0, :]: 
    cv2.circle(mask, (i[0], i[1]), i[2], (255, 255, 255), -1) 

# get first masked value (foreground) 
fg = cv2.bitwise_or(img, img, mask=mask) 

# get second masked value (background) mask must be inverted 
mask = cv2.bitwise_not(mask) 
background = np.full(img.shape, 255, dtype=np.uint8) 
bk = cv2.bitwise_or(background, background, mask=mask) 

# combine foreground+background 
final = cv2.bitwise_or(fg, bk) 

Nota: È preferibile utilizzare i metodi OpenCV perché sono ottimizzati.

1

Gli altri metodi descritti presuppongono una maschera binaria. Se si desidera utilizzare un'immagine in scala di grigio a canale singolo a valori reali come maschera (ad esempio da un canale alfa), è possibile espandere a tre canali e poi utilizzarlo per interpolazione:

assert len(mask.shape) == 2 and issubclass(mask.dtype.type, np.floating) 
assert len(foreground_rgb.shape) == 3 
assert len(background_rgb.shape) == 3 

alpha3 = np.stack([mask]*3, axis=2) 
blended = alpha3 * foreground_rgb + (1. - alpha3) * background_rgb 

noti che mask esigenze essere nell'intervallo 0..1 per il buon esito dell'operazione. Si presume inoltre che le codifiche 1.0 mantengano solo il primo piano, mentre 0.0 significa mantenere solo lo sfondo.

Se la maschera può avere la forma (h, w, 1), questo aiuta:

alpha3 = np.squeeze(np.stack([np.atleast_3d(mask)]*3, axis=2)) 

Qui np.atleast_3d(mask) rende la maschera (h, w, 1) se è (h, w) e np.squeeze(...) rimodella il risultato (h, w, 3, 1)-(h, w, 3).