tutorial segmentacion ruido recorrer por matriz imagenes imagen gaussiano filtros filtro español convertir python opencv image-processing scikit-image

python - segmentacion - ¿Cómo elimino el fondo de este tipo de imagen?



ruido gaussiano python (5)

Quiero eliminar el fondo de esta imagen para obtener solo a la persona. Tengo miles de imágenes como esta, básicamente, una persona y un fondo algo blanquecino.

Lo que he hecho es usar un detector de bordes como un detector de bordes skimage o un filtro skimage (de la biblioteca de skimage ). Entonces, lo que creo que es posible hacer es blanquear los píxeles dentro de los bordes y ennegrecer los píxeles sin ellos. Luego, la imagen original se puede enmascarar para obtener solo la imagen de la persona.

Sin embargo, es difícil obtener un límite cerrado con el detector de bordes de canny. El resultado usando el filtro Sobel no es tan malo, sin embargo, no sé cómo proceder desde allí.

EDITAR:

¿Es posible eliminar también el fondo entre la mano derecha y la falda y entre los pelos?


Como alternativa, puede usar redes neuronales como esta: CRFRNN .

Da el resultado así:


El siguiente código debería ayudarlo a comenzar. Es posible que desee jugar con los parámetros en la parte superior del programa para ajustar su extracción:

import cv2 import numpy as np #== Parameters ======================================================================= BLUR = 21 CANNY_THRESH_1 = 10 CANNY_THRESH_2 = 200 MASK_DILATE_ITER = 10 MASK_ERODE_ITER = 10 MASK_COLOR = (0.0,0.0,1.0) # In BGR format #== Processing ======================================================================= #-- Read image ----------------------------------------------------------------------- img = cv2.imread(''C:/Temp/person.jpg'') gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #-- Edge detection ------------------------------------------------------------------- edges = cv2.Canny(gray, CANNY_THRESH_1, CANNY_THRESH_2) edges = cv2.dilate(edges, None) edges = cv2.erode(edges, None) #-- Find contours in edges, sort by area --------------------------------------------- contour_info = [] _, contours, _ = cv2.findContours(edges, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE) # Previously, for a previous version of cv2, this line was: # contours, _ = cv2.findContours(edges, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE) # Thanks to notes from commenters, I''ve updated the code but left this note for c in contours: contour_info.append(( c, cv2.isContourConvex(c), cv2.contourArea(c), )) contour_info = sorted(contour_info, key=lambda c: c[2], reverse=True) max_contour = contour_info[0] #-- Create empty mask, draw filled polygon on it corresponding to largest contour ---- # Mask is black, polygon is white mask = np.zeros(edges.shape) cv2.fillConvexPoly(mask, max_contour[0], (255)) #-- Smooth mask, then blur it -------------------------------------------------------- mask = cv2.dilate(mask, None, iterations=MASK_DILATE_ITER) mask = cv2.erode(mask, None, iterations=MASK_ERODE_ITER) mask = cv2.GaussianBlur(mask, (BLUR, BLUR), 0) mask_stack = np.dstack([mask]*3) # Create 3-channel alpha mask #-- Blend masked img into MASK_COLOR background -------------------------------------- mask_stack = mask_stack.astype(''float32'') / 255.0 # Use float matrices, img = img.astype(''float32'') / 255.0 # for easy blending masked = (mask_stack * img) + ((1-mask_stack) * MASK_COLOR) # Blend masked = (masked * 255).astype(''uint8'') # Convert back to 8-bit cv2.imshow(''img'', masked) # Display cv2.waitKey() #cv2.imwrite(''C:/Temp/person-masked.jpg'', masked) # Save

Ouput:


Si desea rellenar el fondo no con un color rojo sino hacerlo transparente, puede agregar las siguientes líneas a la solución:

# split image into channels c_red, c_green, c_blue = cv2.split(img) # merge with mask got on one of a previous steps img_a = cv2.merge((c_red, c_green, c_blue, mask.astype(''float32'') / 255.0)) # show on screen (optional in jupiter) %matplotlib inline plt.imshow(img_a) plt.show() # save to disk cv2.imwrite(''girl_1.png'', img_a*255) # or the same using plt plt.imsave(''girl_2.png'', img_a)

Si lo desea, puede modificar algunos parámetros de compresión png para hacer el archivo más pequeño.

Imagen sobre un fondo blanco a continuación. O en uno negro: http://imgur.com/a/4NwmH


Ejemplo de trabajo con vs2017.
Establece el fondo rojo pero guarda el azul.
También se agregó el ejemplo transperent en.

¿Cómo puedo quitar el cuerpo de las chicas y dejar solo el vestido en la imagen? ¿Algunas ideas?

# == https://.com/questions/29313667/how-do-i-remove-the-background-from-this-kind-of-image import cv2 import numpy as np from matplotlib import pyplot as plt #== Parameters ======================================================================= BLUR = 21 CANNY_THRESH_1 = 10 CANNY_THRESH_2 = 200 MASK_DILATE_ITER = 10 MASK_ERODE_ITER = 10 MASK_COLOR = (0.0,0.0,1.0) # In BGR format #== Processing ======================================================================= #-- Read image ----------------------------------------------------------------------- img = cv2.imread(''img/SYxmp.jpg'') gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #-- Edge detection ------------------------------------------------------------------- edges = cv2.Canny(gray, CANNY_THRESH_1, CANNY_THRESH_2) edges = cv2.dilate(edges, None) edges = cv2.erode(edges, None) #-- Find contours in edges, sort by area --------------------------------------------- contour_info = [] _, contours, _ = cv2.findContours(edges, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE) for c in contours: contour_info.append(( c, cv2.isContourConvex(c), cv2.contourArea(c), )) contour_info = sorted(contour_info, key=lambda c: c[2], reverse=True) max_contour = contour_info[0] #-- Create empty mask, draw filled polygon on it corresponding to largest contour ---- # Mask is black, polygon is white mask = np.zeros(edges.shape) cv2.fillConvexPoly(mask, max_contour[0], (255)) #-- Smooth mask, then blur it -------------------------------------------------------- mask = cv2.dilate(mask, None, iterations=MASK_DILATE_ITER) mask = cv2.erode(mask, None, iterations=MASK_ERODE_ITER) mask = cv2.GaussianBlur(mask, (BLUR, BLUR), 0) mask_stack = np.dstack([mask]*3) # Create 3-channel alpha mask #-- Blend masked img into MASK_COLOR background -------------------------------------- mask_stack = mask_stack.astype(''float32'') / 255.0 # Use float matrices, img = img.astype(''float32'') / 255.0 # for easy blending masked = (mask_stack * img) + ((1-mask_stack) * MASK_COLOR) # Blend masked = (masked * 255).astype(''uint8'') # Convert back to 8-bit plt.imsave(''img/girl_blue.png'', masked) # split image into channels c_red, c_green, c_blue = cv2.split(img) # merge with mask got on one of a previous steps img_a = cv2.merge((c_red, c_green, c_blue, mask.astype(''float32'') / 255.0)) # show on screen (optional in jupiter) #%matplotlib inline plt.imshow(img_a) plt.show() # save to disk cv2.imwrite(''img/girl_1.png'', img_a*255) # or the same using plt plt.imsave(''img/girl_2.png'', img_a) cv2.imshow(''img'', masked) # Displays red, saves blue cv2.waitKey()


  • Después de obtener sus bordes incompletos (como lo ha hecho), puede ejecutar una morfología de cierre (una secuencia de dilatación y erosión) (tendrá que establecer el tamaño y las iteraciones según las necesidades / estado de los bordes).

  • Ahora, suponiendo que tiene un borde constante alrededor del sujeto, use cualquier tipo de algoritmo de relleno (blob) para combinar todos los puntos fuera del objeto con bordes, luego tome el negativo de eso para darle la máscara del interior del objeto .