Python | Extracción de primer plano en una imagen usando el algoritmo Grabcut

Discutamos un método eficiente de extracción de primer plano del fondo en una imagen. La idea aquí es encontrar el primer plano y eliminar el fondo. 
La extracción de primer plano es cualquier técnica que permite extraer el primer plano de una imagen para su posterior procesamiento, como reconocimiento de objetos, seguimiento, etc. El algoritmo utilizado para la extracción de primer plano aquí es GrabCut Algorithm. En este algoritmo, la región se dibuja de acuerdo con el primer plano, se dibuja un rectángulo sobre ella. Este es el rectángulo que encierra nuestro objeto principal. Las coordenadas de la región se deciden sobre la comprensión de la máscara de primer plano. Pero esta segmentación no es perfecta, ya que puede haber marcado alguna región de primer plano como fondo y viceversa. Este problema se puede evitar manualmente. Esta técnica de extracción de primer plano funciona como una pantalla verde en las cinemáticas. 
 

  • La región de interés se decide por la cantidad de segmentación de primer plano y fondo que se va a realizar y la elige el usuario. Todo lo que está fuera del ROI se considera como fondo y se vuelve negro. Los elementos dentro del ROI aún se desconocen.
  • Luego se utiliza el modelo de mezcla gaussiana (GMM) para modelar el primer plano y el fondo. Luego, de acuerdo con los datos proporcionados por el usuario, el GMM aprende y crea etiquetas para los píxeles desconocidos y cada píxel se agrupa en términos de estadísticas de color.
  • Se genera un gráfico a partir de esta distribución de píxeles donde los píxeles se consideran Nodes y se agregan dos Nodes adicionales, que son el Node Fuente y el Node Sumidero. Todos los píxeles de primer plano están conectados al Node Fuente y cada píxel de Fondo está conectado al Node Sumidero. Los pesos de los bordes que conectan los píxeles al Node de origen y al Node final se definen por la probabilidad de que un píxel esté en primer plano o en segundo plano.
  • Si se encuentra una gran disimilitud en el color del píxel, el peso bajo se asigna a ese borde. Luego se aplica el algoritmo para segmentar el gráfico. El algoritmo segmenta el gráfico en dos, separando el Node fuente y el Node sumidero con la ayuda de una función de coste que es la suma de todos los pesos de las aristas que se segmentan.
  • Después de la segmentación, los píxeles que están conectados al Node Fuente se etiquetan como primer plano y los píxeles que están conectados al Node Sumidero se etiquetan como fondo. Este proceso se realiza para múltiples iteraciones según lo especificado por el usuario. Esto nos da el primer plano extraído.

La función utilizada aquí es cv2.grabCut()
 

Sintaxis: cv2.grabCut(imagen, máscara, rectángulo, modelo de fondo, modelo de primer plano, número de iteraciones [, modo])
Parámetros: 
 

  • imagen: Entrada de imagen de 3 canales de 8 bits.
  • mask: Máscara monocanal de entrada/salida de 8 bits. La función inicializa la máscara cuando el modo se establece en GC_INIT_WITH_RECT. Sus elementos pueden tener uno de los siguientes valores: 
    • GC_BGD define un fondo de píxeles obvio.
    • GC_FGD define un píxel de primer plano (objeto) obvio.
    • GC_PR_BGD define un posible píxel de fondo.
    • GC_PR_FGD define un posible píxel de primer plano.
  • rectángulo: Es la región de interés que contiene un objeto segmentado. Los píxeles fuera del ROI están marcados como fondo obvio. El parámetro solo se usa cuando mode==GC_INIT_WITH_RECT.
  • backgroundModel: array temporal para el modelo de fondo.
  • primer planoModelo: array temporal para el modelo de primer plano.
  • iterationCount: Número de iteraciones que debe realizar el algoritmo antes de devolver el resultado. Tenga en cuenta que el resultado se puede refinar con más llamadas con mode==GC_INIT_WITH_MASK o mode==GC_EVAL.
  • mode: Define el modo de Operación. Puede ser uno de los siguientes: 
    • GC_INIT_WITH_RECT : la función inicializa el estado y la máscara utilizando el rectángulo proporcionado. Después de eso, ejecuta iterCount iteraciones del algoritmo.
    • GC_INIT_WITH_MASK : la función inicializa el estado utilizando la máscara proporcionada. Tenga en cuenta que GC_INIT_WITH_RECT y GC_INIT_WITH_MASK se pueden combinar. Luego, todos los píxeles fuera del ROI se inicializan automáticamente con GC_BGD.
    • GC_EVAL : el valor significa que el algoritmo debería reanudarse.

A continuación se muestra la implementación: 
 

Python3

# Python program to illustrate
# foreground extraction using
# GrabCut algorithm
  
# organize imports
import numpy as np
import cv2
from matplotlib import pyplot as plt
  
# path to input image specified and
# image is loaded with imread command
image = cv2.imread('image.jpg')
  
# create a simple mask image similar
# to the loaded image, with the
# shape and return type
mask = np.zeros(image.shape[:2], np.uint8)
  
# specify the background and foreground model
# using numpy the array is constructed of 1 row
# and 65 columns, and all array elements are 0
# Data type for the array is np.float64 (default)
backgroundModel = np.zeros((1, 65), np.float64)
foregroundModel = np.zeros((1, 65), np.float64)
  
# define the Region of Interest (ROI)
# as the coordinates of the rectangle
# where the values are entered as
# (startingPoint_x, startingPoint_y, width, height)
# these coordinates are according to the input image
# it may vary for different images
rectangle = (20, 100, 150, 150)
  
# apply the grabcut algorithm with appropriate
# values as parameters, number of iterations = 3
# cv2.GC_INIT_WITH_RECT is used because
# of the rectangle mode is used
cv2.grabCut(image, mask, rectangle, 
            backgroundModel, foregroundModel,
            3, cv2.GC_INIT_WITH_RECT)
  
# In the new mask image, pixels will
# be marked with four flags
# four flags denote the background / foreground
# mask is changed, all the 0 and 2 pixels
# are converted to the background
# mask is changed, all the 1 and 3 pixels
# are now the part of the foreground
# the return type is also mentioned,
# this gives us the final mask
mask2 = np.where((mask == 2)|(mask == 0), 0, 1).astype('uint8')
  
# The final mask is multiplied with
# the input image to give the segmented image.
image = image * mask2[:, :, np.newaxis]
  
# output segmented image with colorbar
plt.imshow(image)
plt.colorbar()
plt.show()

Imagen de entrada: 
 

Producción: 
 

Aquí hemos tomado una imagen de entrada de tamaño 500X281 y decidimos las coordenadas para el rectángulo en consecuencia. La imagen de salida muestra cómo el objeto a la izquierda de la imagen se convierte en parte del primer plano y se resta el fondo.
 

Publicación traducida automáticamente

Artículo escrito por rishabhsingh1304 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *