2012-05-06 152 views
15

¿Cómo puedo aplicar máscara a una imagen en color en la última vinculación de python (cv2)? En el enlace anterior de python, la forma más simple era usar cv.Copy, p.OpenCV - Aplicar máscara a una imagen en color

cv.Copy(dst, src, mask)

Pero esta función no está disponible en la unión cv2. ¿Hay alguna solución sin usar el código repetitivo?

+0

¿Qué estás tratando de hacer? ya que tiene soporte numpy, puede usar funciones numpy. –

+0

Estoy haciendo algunos filtros en el espacio de color HSV a la imagen original – pzo

Respuesta

30

Aquí, podría usar la función cv2.bitwise_and si ya tiene la imagen de la máscara.

Para comprobar el código de abajo:

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

La salida será la siguiente imagen de lena para, y para la máscara rectangular.

enter image description here

+0

Estoy tratando de hacer algo similar. La máscara debe ser negra o blanca? Perdón por la pregunta básica, soy un novato con opencv. Gracias –

+2

Ya, tienes razón, la máscara debe ser negra/blanca y un solo canal. Cualquiera que sea la región de la imagen que desee procesar, esa región en la máscara debe ser blanca, todo lo demás es negro. Y no tiene que preocuparse por hacer esta pregunta, todos son novatos cuando comienzan a aprender, incluso yo también. –

+0

Muchas gracias Abid! Lo intentaré esta noche cuando esté en casa. Tengo que dividir una imagen en varias regiones (y repetir este proceso en varias imágenes). ¡Saludos! –

-1

Respuesta de la Abid Rahman K no es del todo correcta. También lo probé y encontré muy útil, pero me atascaron.

Así copio la imagen con una máscara determinada.

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] 

Esto es un poco lento pero da resultados correctos.

EDITAR:

Pythonic way.

idx = (mask!=0) 
dst[idx] = src[idx] 
+0

¿Qué es incorrecto sobre la respuesta de Abid? –

+0

No es necesario reinventar la rueda aquí cuando el método "bitwise_and" en cv2 funciona al 100% como se le pidió. No solo eso, sino que es muy obvio en cuanto a lo que hace. –

6

Bueno, esta es una solución si desea que el fondo sea distinto de un color negro sólido. Solo tenemos que invertir la máscara y aplicarla en una imagen de fondo del mismo tamaño y combinar el fondo y el primer plano. Un profesional de esta solución es que el fondo puede ser cualquier cosa (incluso otra imagen).

Este ejemplo se modificó de Hough Circle Transform. La primera imagen es el logotipo de OpenCV, en segundo lugar la máscara original, en tercer lugar el fondo + primer plano combinado.

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: Es mejor utilizar los métodos de OpenCV, ya que se han optimizado.

1

Los otros métodos descritos suponen una máscara binaria. Si desea utilizar una imagen en escala de grises de un solo canal de valor real como una máscara (por ejemplo, de un canal alfa), se puede ampliar a tres canales y luego usarlo para la interpolación:

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 

Tenga en cuenta que mask necesidades estar en el rango 0..1 para que la operación tenga éxito. También se supone que 1.0 codifica mantener el primer plano solamente, mientras que 0.0 significa mantener solo el fondo.

Si la máscara puede tener la forma (h, w, 1), esto ayuda:

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

Aquí np.atleast_3d(mask) hace que la máscara (h, w, 1) si es (h, w) y np.squeeze(...) remodela el resultado (h, w, 3, 1)-(h, w, 3).

Cuestiones relacionadas