Archivos: https://github.com/tolchx/Touchdesigner_Opencv

 

Que podría hacer con la detección de rostros openCV

En este ejemplo se detectara un rostro para la imagen de una persona, y estará rodeado por un marco cuadrado, esta técnica se puede utilizar con varias personas en simultaneo. También puede cambiar de detección de rostros a detección de nariz, ojos, etc.

 

Que necesitamos?

-TouchDesigner
-Imágenes que desea analizar, cámara web, video, etc.
-Detectores de reconocimiento de rostros ↓
https://github.com/opencv/opencv/tree/master/data/haarcascades

En este ejemplo usaremos haarcascade_frontalface_default para detectar caras que miren al frente.

Que esta haciendo cada programa?

TouchDesigner

  • Carga de imágenes.
  • Ajuste de resolución y relación de aspecto.
  • Generación de máscaras.

Python

  • Detección de rostros
  • Incluye la ubicación detectada en un cuadrado, y envía las coordenadas y el tamaño del cuadrado a Touch Designer.

Si aun no tienen instalado Python y OpenCV, les dejo un tutorial acontinuacion:

 

 

 

 

 

Descripción general del método de detección de rostros

Una parte de la imagen completa se recorta y se juzga de acuerdo con varios criterios. Si se considera que «no es una cara» incluso una vez, no se realiza la evaluación posterior y el dispositivo de evaluación se puede aplicar a otra parte de la imagen. Al no realizar todos los juicios, se logra la velocidad del procesamiento de detección de rostros (la precisión de cada juicio es baja, pero aumenta a medida que se acumulan).

Como punto débil, si no tiene una cara frontal, la precisión de detección se reducirá significativamente.

Explicación

voy a explicar el contenido del proyecto adjunto, donde se encuentran los contenedores Base y Face

① Base

Preparación del detector

Para reconocer una cara, necesita un detector entrenado que se encargue de esta tarea, utilizaremos el siguiente del repositor OpenCV
https://github.com/opencv/opencv/blob/master/data/haarcascades/haarcascade_frontalface_default.xml

Desarrollo del sistema:

La resolución de la imagen es 1/4 y monocromática antes de pasarla a Python. Dado que opera en tiempo real, estamos tratando de acelerar el procesamiento.

  • Reciba la imagen o el video que desea reconocer su rostro.
  • La resolución se reduce a 1/4 de la imagen original para reducir la carga de procesamiento.
  • se parece al movimiento que Python escribió aquí después de ejecutar Cook.
  • Se escribe el proceso para detectar la cara.
  • Recibe información sobre la posición y el ancho del rostro detectada
  • Genera un cuadrado para cubrir la cara.
  • La imagen original está cubierta con una máscara.

 

Código python: face_detect

import cv2
import numpy as np

face_cascade = cv2.CascadeClassifier('./tools/haarcascade_frontalface_default.xml')

def onPostCook(changeOp):
    arr = changeOp.numpyArray(delayed=True)
    gray = arr[:, :, 0]
    gray = gray * 255.0
    gray = gray.astype(np.uint8)
    gray_invert = np.flipud(gray)

    faces = face_cascade.detectMultiScale(gray_invert)

    if len(faces) > 0:
        resX = op('face_pre').width
        resY = op('face_pre').height

        for (x, y, w, h) in faces:
            centerX = ((x + w/2) - resX/2) * 4
            centerY = (-(y + h/2) + resY/2) * 4

            op('face_pos').par.value0 = centerX
            op('face_pos').par.value1 = centerY
            op('face_pos').par.value2 = w * 4
            op('face_pos').par.value3 = h * 4
        pass
    return


Explicación por partes:

import cv2
import numpy as np

face_cascade = cv2.CascadeClassifier('./tools/haarcascade_frontalface_default.xml')

def onPostCook(changeOp):
    return
  • Primero, importe OpenCV y Numpy, la cual es una biblioteca que maneja matrices.
  • Luego genere un detector con cv2.CascadeClassifier , El archivo de haarcascade_frontalface_default.xml está guardado en la carpeta de herramientas (tools) al mismo nivel que el proyecto face_detect.toe, por lo que se especifica la ruta del archivo .xml en ‘./tools/haarcascade_frontalface_default.xml’. Vuelva a escribir según la ubicación donde se coloque el archivo.

  • onPostCook: Escriba el procesamiento que desea que ocurra después de que Cook entre en funcionamiento.
  • En el operador DAT face_detect no olvide activar Post Cook.

Dentro de onPostCook

arr = changeOp.numpyArray(delayed=True)
gray = arr[:, :, 0]
  • Los datos de imagen se pueden obtener llamando al método de la clase TOP numpy.ndarray.
  • gray = arr[:,:,0]   El canal rojo se extrae y se convierte en una escala de grises
  • delayed   Es una opción que acelera el procesamiento.

 

Entonces, aquí, obtengo las imágenes de entrada como una matriz y las hago en escala de grises.

gray = gray* 255.0
gray = gray.astype(np.uint8)
gray_invert = np.flipud(gray)

Dado que la matriz obtenida en el proceso anterior se pasa a OpenCV, es necesario convertirla al formato de datos de Python solo. Según los artículos referenciados

En Python
[Azul, Verde, Rojo] (el rango de valores es de 0 a 255)

Touchdesigner + Python
[Azul, Verde, Rojo, Alfa] (rango de valores) Fue de 0 a 1)f_arr = np.flipud (f_arr)
También se necesitaba dar vuelta la matriz.

Entonces, la matriz de imágenes adquirida se estira de 0 a 1 a 0 a 255 para que sea compatible con OpenCV, se convierte en un entero sin signo de 8 bits y la matriz se invierte.

faces = face_cascade.detectMultiScale(gray_invert)
if len(faces) > 0:

Analizamos la matriz de imagen, si se detecta una cara, se ejecute el siguiente proceso.

for (x, y, w, h) in faces:
    centerX = ((x + w/2) - resX/2) * 4
    centerY = (-(y + h/2) + resY/2) * 4

    op('face_pos').par.value0 = centerX
    op('face_pos').par.value1 = centerY
    op('face_pos').par.value2 = w * 4
    op('face_pos').par.value3 = h * 4
pass

El rostro se detecta como un cuadrado.

faces Tiene las coordenadas xy de la esquina superior izquierda del cuadrilátero y el ancho y alto del cuadrilátero como información, obtendremos los datos x y w h.  Asigne los valores al operador Face_pos y multiplique por 4 para que coincida con la resolución de la imagen original.

El sistema de coordenadas en OpenCV y TouchDesigner son diferentes, podemos ver un ejemplo visual:

Hasta acá analizamos el sistema Base

② Caras

El flujo básico de información es el mismo al ejemplo Base, veremos las diferencias.

Detección de rostro

– position: recibe información sobre el número de caras, la posición y el ancho del cuadrado, detectadas en face_detect.
– cal_ratio: La información recibida de Python se calcula con el valor requerido para el enmascaramiento.
– aspect_ratio: La relación entre el ancho y el alto de la imagen de entrada.
– face_pos: Posición de la cara calculada adecuadamente para el enmascaramiento.

Dentro de cal_ratio

– info2: La resolución de la imagen original.
・math3: Se calcula la proporción de la imagen original.
・info1: La resolución de face_pre
– math1: Normalizamos el número recibido de face_detect
・math2: Las coordenadas se expanden de 0 a 1 a -1 a 1.
・math4: El valor horizontal se multiplica por rename1 ,el valor para obtener la misma proporción que la imagen original.

face_detect codigo:

import cv2
import numpy as np

face_cascade = cv2.CascadeClassifier('./tools/haarcascade_frontalface_default.xml')

def onPostCook(changeOp):
    arr = changeOp.numpyArray(delayed=True)
    gray = arr[:, :, 0]
    gray = gray * 255.0
    gray = gray.astype(np.uint8)
    gray_invert = np.flipud(gray)

    faces = face_cascade.detectMultiScale(gray_invert)

    position = op('position')
    position.clear()
    position.numSamples = len(faces)

    centerX = position.appendChan('centerX')
    centerY = position.appendChan('centerY')
    w = position.appendChan('w')
    h = position.appendChan('h')

    if len(faces) > 0:
        resX = op('face_pre').width
        resY = op('face_pre').height

        for i in range(position.numSamples):
            face = faces[i]

            w[i] = face[2]
            h[i] = face[3]

            centerX[i] = face[0] + face[2]/2
            centerY[i] = -(face[1] + face[3]/2) + resY
        pass
    return

Explicando diferencias con ejemplo Base.

position = op('position')
position.clear()

position.numSamples = len(faces)

centerX = position.appendChan('centerX')
centerY = position.appendChan('centerY')
w = position.appendChan('w')
h = position.appendChan('h')

Aquí, se establece el destino al que se pasa el valor numérico position.

len(faces) Al establecer el número de muestras, podrá tener el número de caras detectadas y su información.

for i in range(position.numSamples):
    face = faces[i]

    w[i] = face[2]
    h[i] = face[3]

    centerX[i] = face[0] + face[2]/2
    centerY[i] = -(face[1] + face[3]/2) + resY
pass

face Contiene cuatro números: coordenada x, coordenada y, ancho y alto comenzado desde la parte superior izquierda del cuadrilátero.
Se asignan esos valores numéricos a las variables correspondientes.

Ahora que tenemos un sistema de coordenadas lo ajustaremos con unos cálculos.
Obtenemos las coordenadas y el tamaño del cuadrilátero varias veces utilizando la variable position.numSamples, es decir, el número de caras detectadas.

Composición de la masca

Geo1: a partir de la información de face_pos, está instalando un rectángulo que es la fuente de la máscara.
Cam1: El método de proyección se establece en Ortográfico para que el tamaño no cambie según la distancia del objeto.
Render1: El cuadrado instanciado se renderiza con la misma resolución que la imagen original.
Res2: La resolución de la parte enmascarada (rostro detectado) se reduce para que parezca un mosaico. mosaic_slinder La tosquedad del mosaico se puede cambiar fácilmente.
Res3: La resolución de la parte de la máscara se ajusta a la imagen original.

 

Según las especificaciones de TouchDesigner, Cook se detiene para los TOP en la jerarquía oculta, excepto para los TOP específicos.

Si observa face_detectP.toe en el archivo de muestra, puede ver face_pre TOP en Opviewer TOP en la misma jerarquía que COMP (proyecto1) que se muestra en el modo de ejecución.

Al hacer esto, Cook  face_pre TOP continuará ejecutándose incluso cuando la configuracion del proyecto este en el modo ejecución, por lo que la detección de rostros funcionará.

  • Si quiere saber mas sobre procesos Cook, puede ver el siguiente post: Cocinar solo cuando sea necesario
  • La versión 2020 de Touchdesigner incluye Python 3.7.2
  • En caso de tener algún error asegúrese de tener instalado las librerías de python Numpy y Matplotlib
  • Puede instalar Anaconda como entorno de ejecución para sus librerías python:
    https://anaconda.orgAnaconda es una Suite de código abierto que abarca una serie de aplicaciones, librerías y conceptos diseñados para el desarrollo de la Ciencia de datos con Python. Es una distribución que funciona como un gestor de entorno, un gestor de paquetes y que posee una colección de más de 720 paquetes de código abierto.

Dado que solo recibe las coordenadas detectadas, la parte que conecta los nodos de TouchDesigner es un mecanismo sencillo. El cálculo para convertir una imagen en una matriz en Python y sintetizarla con la imagen original es un poco mas complicado, se escribió lo mas simple posible. Si tiene alguna pregunta o error, puede dejar un comentario.

Tutorial origianl By komakinex

 

Share this: