🎚️ Trackbar + 👨👩 Rostros borrosos | OpenCV – Python

Por Administrador

Imagina que estás trabajando en tus proyectos de OpenCV, cuando de pronto alguien desesperado por tu ayuda te dice: mira tengo unas imágenes y quiero que los rostros que aparezcan dentro de cada una de ellas sean borrados, por aquello de la privacidad y necesito poder variar el grado de borrosidad para ver cual queda mejor. Además es necesario que las imágenes puedan mostrarse a color y a escala de grises.

Después de haber escuchado todo esto, tú te preguntas como mostrarle todo esto a ese usuario, porque no podrías estar ejecutando, finalizando y cambiando el valor de las variables dentro del programa a cada momento, ya que se perdería la percepción de los efectos de borrosidad. Otra opción sería guardar varias imágenes con los distintos niveles de borrosidad y en escala de grises, pero no sería eficiente en este caso. Finalmente recuerdas que alguna vez viste que se podía incrustar una barra deslizante a las imágenes con OpenCV, y de hecho esta es una muy buena idea.

En este tutorial vamos a ver precisamente eso, el realizar una aplicación en la cual deberemos a través del control de una barra deslizante, dar distintos niveles de borrosidad a los rostros que estén dentro de una imagen, además podremos mostrarla a color o grises. Finalmente veremos como realizar este proceso en un video streaming.

CONTENIDO:

  • ¿Qué es trackbar o barra deslizante (control deslizante / control de rango) en OpenCV?
    • ¿Cómo crear y obtener el valor de un trackbar / barra deslizante en OpenCV?
      • cv2.createTrackbar
      • cv2.getTrackbarPos
  1. Empecemos con la aplicación sobre una imagen
    1. Creando los trackbar / barra deslizante
    2. Obteniendo las posiciones de las barras de seguimiento
      1. ¿A color o a escala de grises?
      2. Detectando rostros y haciéndolos borrosos
    3. Finalmente…
    4. Programa completo
    5. Resultados
  2. Empleando esta aplicación sobre un video streaming
    1. Resultados

La detección de rostros que vamos a utilizar en el tutorial del hoy ya la he explicado antes, por lo que si quieres un tutorial más completo sobre ello visita: 👨 DETECCIÓN DE ROSTROS 👩 con Haar Cascades Python – OpenCV.

¿Qué es trackbar o barra deslizante (control deslizante / control de rango) en OpenCV?

Figura 1: Visualización de la barra deslizante (trackbar).

OpenCV ofrece algunas herramientas GUI (Interfaz Gráfica de Usuario) para integrarlas dentro de nuestras aplicaciones. Una de ellas es trackbar o barra deslizante, que podrá ser controlada por el usuario mediante el movimiento de una “perilla”, de tal modo que variará el valor de cierto parámetro entero, mientras la aplicación se está ejecutando.

¿Cómo crear y obtener el valor de un trackbar / barra deslizante en OpenCV?

Para crear el control deslizante se necesita de la función cv2.createTrackbar mientras que para obtener el valor correspondiente a posición de esta barra de seguimiento se necesita de cv2.getTrackbarPos. Veamos como usar cada una de estas dos funciones:

cv2.createTrackbar

Figura 2: Barra deslizante (winnname y trackbarname).

Según nos explica OpenCV, esta función crea una barra de seguimiento/ control deslizante/control de rango y la adjunta a una ventana con un nombre específico. 

Parámetros:

  • trackbarname, nombre de la barra de seguimiento creada. 
  • winname, nombre de la ventana que será usada como padre de la barra de seguimiento creada. 
  • value, puntero opcional a una variable entera cuyo valor refleja la posición del slider (control deslizante). Después de la creación, la posición del slider es definida por esta variable. 
  • count, posición máxima del slider. La posición mínima siempre será cero. 
  • onChange, puntero a la función a llamar cada vez que el slider cambia su pocisión.

Recuerda visitar la documentación de OpenCV para más información.

cv2.getTrackbarPos

 Esta retorna la posición de la barra de seguimiento. 

Parámetros:

  • trackbarname, nombre de la barra de seguimiento creada. 
  • winname, nombre de la ventana que será usada como padre de la barra de seguimiento creada. 

1. Empecemos con la aplicación sobre una imagen

La imagen con la que vamos a trabajar en esta ocasión es la siguiente:

Figura 3: Imagen de entrada

import cv2

def nothing(x):
    pass

image = cv2.imread('oficina.jpeg')
faceClassif = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
cv2.namedWindow('Imagen')

Línea 1: Importamos OpenCV.

Línea 3 y 4: Creamos una función llamada nothing que nos servirá como parámetro para crear el trackbar. De hecho esta función no hará ninguna operación, simplemente servirá como auxiliar en este caso. Tú podrías desarrollar en vez de esta función otra con operaciones que dependan del valor x  que corresponde al cambio de posición de la barra deslizante.

Línea 6: Leemos la imagen de entrada.

Línea 7: Llamamos al clasificador de rostros pre entrenado haar cascade. Recuerda que el archivo haarcascade_frontalface_default.xml debe estar en la misma carpeta en donde está guardado el script donde estás desarrollando este programa. Si tienes alguna duda sobre como se realiza el proceso de detección de rostros te recomiendo que visites el post anterior.

Línea 8: Especificamos el nombre de la ventana en donde se va a visualizar la imagen, en este caso el nombre que se ha asignado es 'Imagen'.

1.1 Creando los trackbar / barra deslizante

cv2.createTrackbar('Blur','Imagen',0,15,nothing) 
cv2.createTrackbar('Gray','Imagen',0,1,nothing)

Línea 9: Vamos a crear la barra deslizante correspondiente a la borrosidad o difuminado. Para ello estableceremos el nombre del trackbar 'Blur', el nombre de la ventana 'Imagen' que habíamos especificado en la línea 8. En cuanto al parámetro value se ha puesto 0, que quiere decir que en un principio el slider va a estar ubicado en 0. El valor máximo será 15 pero podrías probar con otros valores, y finalmente llamamos a la función que habíamos creado en un principio nothing.

NOTA: En el parámetro value, tú podrías ajustarlo en algún entero mayor a 0 por ejemplo, esto querría decir que en un principio la posición tomaría ese valor. Sin embargo ten en cuenta que el valor mínimo siempre será 0.

Línea 10: Este será el segundo trackbar correspondiente a mostrar la imagen a color o escala de grises. Seguimos el mismo procedimiento que la anterior línea, las diferencias estarán en que en el parámetro trackbarname será 'Gray' y en count 1. Lo que quiere decir que si se mantiene en 0 se mostrará la imagen a color, mientras que si está en 1 se mostrará en escala de grises.

1.2 Obteniendo las posiciones de las barras de seguimiento

while True:

    val = cv2.getTrackbarPos('Blur','Imagen')
    grayVal = cv2.getTrackbarPos('Gray','Imagen')

Línea 12: Vamos por el ciclo while, que nos permitirá realizar el proceso indefinidamente hasta que una tecla sea presionada.

Línea 14: Para obtener el valor de la posición de la barra deslizante necesitamos de cv2.getTrackbarPos, en ella se debe especificar el nombre del trackbar en este caso 'Blur' y el nombre de la ventana en donde se mostrará, en este caso 'Imagen'. Este valor se almacenará enval.

Línea 15: Ahora es el turno de la segunda barra de control deslizante. Debemos especificar 'Gray' como su nombre, mientras que al  igual que la anterior barra 'Imagen' para el nombre de la ventana, ya que ambas barras se mostrarán en la misma. El valor de la posición se almacenará en grayVal.

Ahora que tenemos las posiciones almacenadas en variables podremos usarlas como cualquier variable entera, veamos:

1.2.1 ¿A color o a escala de grises?

Recordemos que el trackbar que establecimos para indicar si una imagen se muestra a color o escala de grises puede tomar dos valores 0 o 1.

if grayVal == 1:
    imageN = cv2.cvtColor(image.copy(), cv2.COLOR_BGR2GRAY)
else: imageN = image.copy()

Línea 16: Vamos con la condición si grayVal == 1 eso quiere decir que la imagen debe mostrarse a escala de grises, caso contrario a colores.

Línea 17: Si se cumple con la condición de la línea 16 entonces debe mostrarse la imagen en escala de grises, para ello debemos usar la función cv2.cvtColor.

Línea 18: Si grayVal es 0, entonces la imagen será la misma que la entrada.

NOTA: Toma en cuenta que tanto en la línea 17 y 18 he usado image.copy() esto para que se tome en todo momento la imagen de entrada. Si quitáramos la extensión .copy() se estaría llamando a una imagen modificada por cada iteración.

1.2.2 Detectando rostros y haciéndolos borrosos

Es hora de detectar los rostros presentes en la imagen de entrada y difuminarlos a distinto grado.

faces = faceClassif.detectMultiScale(image, 1.1, 5)

for (x,y,w,h) in faces:
    if val > 0:
        imageN[y:y+h,x:x+w] = cv2.blur(imageN[y:y+h,x:x+w],(val,val))

Línea 19: En faces se almacenarán todos los rostros encontrados.

Línea 21: Ahora procedemos a desempaquetar la información de faces que son las coordenadas x e y en donde se encuentran rostros, además de su ancho y alto.

Línea 22 y 23: Si val > 0 entonces se procederá a aplicar cv2.blur en el área en donde se encuentre el rostro. Por cierto se establece un valor mayor a 0, ya que si usamos 0 en cv2.blur obtendremos un error. Además de este modo podremos comparar las imágenes al no tener ningún grado de borrosidad y cuando este incrementa. Si deseas más información sobre esta función usada para difuminar visita la documentación de OpenCV.

1.3 Finalmente…

    cv2.imshow('Imagen',imageN)
    k = cv2.waitKey(1)
    if k == 27:
        break
cv2.destroyAllWindows()

Línea 25: Visualizamos la imagen.

Línea 26 a 28: El proceso se detendrá hasta que sea presionada la tecla ‘Esc’.

Línea 29: Se cierran todas las ventanas creadas.

1.4 Programa completo

import cv2

def nothing(x):
    pass

image = cv2.imread('oficina.jpeg')
faceClassif = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
cv2.namedWindow('Imagen')
cv2.createTrackbar('Blur','Imagen',0,15,nothing)
cv2.createTrackbar('Gray','Imagen',0,1,nothing)

while True:

    val = cv2.getTrackbarPos('Blur','Imagen')
    grayVal = cv2.getTrackbarPos('Gray','Imagen')
    if grayVal == 1:
        imageN = cv2.cvtColor(image.copy(), cv2.COLOR_BGR2GRAY)
    else: imageN = image.copy()
    faces = faceClassif.detectMultiScale(image, 1.1, 5)

    for (x,y,w,h) in faces:
        if val > 0:
            imageN[y:y+h,x:x+w] = cv2.blur(imageN[y:y+h,x:x+w],(val,val))

    cv2.imshow('Imagen',imageN)
    k = cv2.waitKey(1)
    if k == 27:
        break
cv2.destroyAllWindows()

1.5 Resultados

A continuación vamos a ver algunas pruebas realizadas con el programa que hemos desarrollado, veamos:

En la visualización nos podemos dar cuenta que los rostros  sen han detectado y conforme cambiamos la posición en ‘Blur’, la borrosidad o difuminado se hace más evidente.

En cuanto a ‘Gray’, también podemos visualizar que si se mantiene en 0, la imagen se muestra a color mientras que si cambia a 1 se visualiza en escala de grises.

2. Empleando esta aplicación sobre un video streaming

A continuación te podrás dar cuenta que el proceso es prácticamente el mismo.

import cv2

def nothing(x):
    pass

cap = cv2.VideoCapture(0)
faceClassif = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
cv2.namedWindow('frame')
cv2.createTrackbar('Blur','frame',0,15,nothing)
cv2.createTrackbar('Gray','frame',0,1,nothing)

while True:    
    ret,frame = cap.read()    
    val = cv2.getTrackbarPos('Blur','frame')
    grayVal = cv2.getTrackbarPos('Gray','frame')
    if grayVal == 1:
        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    faces = faceClassif.detectMultiScale(frame, 1.3, 5)

    for (x,y,w,h) in faces:
        if val > 0: 
            frame[y:y+h,x:x+w] = cv2.blur(frame[y:y+h,x:x+w],(val,val))
    cv2.imshow('frame',frame)
    k = cv2.waitKey(1) & 0xFF
    if k == 27:
        break
cap.release()
cv2.destroyAllWindows()

La diferencia está (aparte de que se está leyendo una secuencia de imágenes y ya no una sola) en que ya no es necesario usar .copy(), puesto que en cada momento se está tomando una nueva imagen.

2.1 Resultados

Y bien esto ha sido todo por este tutorial. Logramos solucionar el problema que en un principio se había planteado. Si deseas puede dejar algún comentario, sugenrencia o corrección y ¡sigamos aprendiendo juntos!.

Referencias