Menú
Está libre
registro
hogar  /  SOBRE/ Reconocimiento del contorno corporal en tiempo real. Visión por computadora en openCV

Reconocimiento del contorno corporal en tiempo real. Visión por computadora en openCV

Evgeny Borisov Lunes, 24 de julio de 2017

Este artículo proporciona una descripción general de los métodos para encontrar un objeto en una imagen.

1. Introducción

Muchas tareas prácticas, desde la automatización del control en producción hasta el diseño de vehículos robóticos, están directamente relacionadas con la tarea de encontrar objetos en la imagen. Para resolverlo, puede utilizar dos estrategias diferentes, que dependen de las condiciones de disparo: modelado de fondo y modelado de objetos.
  1. Simulación de fondo: este enfoque se puede utilizar si la cámara está estacionaria, es decir, tenemos un trasfondo que cambia poco y, por lo tanto, podemos construir un modelo del mismo. Todos los puntos de la imagen que se desvían significativamente del modelo de fondo se consideran objetos de primer plano. Por tanto, es posible solucionar los problemas de detección y seguimiento de objetos.
  2. Modelado de objetos: este enfoque es más general, se utiliza en casos en los que el fondo cambia constante y significativamente. A diferencia del caso anterior, aquí necesitamos saber qué queremos encontrar exactamente, es decir es necesario construir un modelo del objeto y luego verificar que los puntos de la imagen cumplan con este modelo.
A veces, las condiciones del problema le permiten combinar ambos enfoques, esto puede mejorar significativamente los resultados. La solución al problema de modelar el fondo de una cámara fija se puede encontrar en. A continuación, consideraremos la aplicación de la segunda estrategia, es decir modelado del objeto de búsqueda.

2. Resumen de métodos

En esta sección, presentamos una lista de enfoques que se pueden utilizar para resolver con éxito el problema de encontrar un objeto en una imagen, en orden de complejidad creciente.
  1. Filtros de color: si el objeto se destaca significativamente del fondo en color, puede elegir el filtro apropiado.
  2. Selección y análisis de contornos: si sabemos que el objeto tiene la forma de, por ejemplo, un círculo, entonces podemos buscar círculos en la imagen.
  3. Coincidencia de patrones: tenemos una imagen de un objeto, estamos buscando áreas en otra imagen que coincidan con esta imagen de un objeto.
  4. Trabajando con puntos especiales: en la imagen con el objeto, estamos buscando características (por ejemplo, ángulos), que estamos tratando de comparar con tales características en otra imagen.
  5. Métodos de aprendizaje automático: entrenamos al clasificador en imágenes con un objeto, de alguna manera dividimos la imagen en partes, verificamos cada parte con el clasificador para detectar la presencia de un objeto.
Veremos estos métodos con más detalle a continuación.

3. Filtros de color

El método de los filtros de color se puede utilizar en los casos en que el objeto difiere significativamente del color de fondo y la iluminación es uniforme y no cambia. Puede leer más sobre el método de filtro de color en.

4. Extracción y análisis de contornos

Si el objeto no se destaca significativamente sobre el fondo en color y / o tiene una coloración compleja, entonces el uso del método de filtros de color no dará buenos resultados. En este caso, puede intentar aplicar el método de selección y análisis de contornos. Para ello, seleccionamos los bordes de la imagen. Los bordes son lugares donde el gradiente de brillo cambia abruptamente y se pueden encontrar usando el método Canny. A continuación, podemos verificar que las líneas de límite seleccionadas cumplan con los contornos geométricos del objeto, esto se puede hacer usando el método de transformación de Hough, por ejemplo, podemos buscar dentro de los límites de un círculo.





Figura 4: encontrar círculos

Este método también se puede utilizar junto con filtros de color. Puede leer más sobre la selección y el análisis de contornos en. Se puede descargar el código fuente del ejemplo de búsqueda de círculos.

5. Coincidencia de patrones

Si la imagen tiene muchos detalles pequeños, el análisis de bordes puede resultar complicado. En este caso, puede utilizar el método de coincidencia de plantillas. Consiste en lo siguiente: tomamos una fotografía con un objeto (Fig. 5) y buscamos áreas en la imagen grande que coincidan con la imagen del objeto (Fig. 6,7).


Figura 5: objeto para buscar

Puede escuchar la conferencia con más detalle sobre el método de coincidencia de patrones. El código fuente del ejemplo se puede descargar.

6. Trabajar con puntos especiales

El método de coincidencia de patrones descrito en la sección anterior busca coincidencias exactas entre los puntos de patrón y los puntos de imagen. Si la imagen se gira o se escala en relación con los parámetros de la plantilla, este método no funciona bien. Para superar estas limitaciones, se utilizan métodos basados ​​en los llamados. puntos singulares, los consideraremos a continuación. Un punto clave es un área pequeña que destaca significativamente en la imagen. Existen varios métodos para determinar dichos puntos, estos pueden ser ángulos (detector de esquinas de Harris) o manchas (gota, gota), es decir, pequeñas áreas del mismo brillo, con un borde bastante claro que se destaca sobre el fondo general. Por un punto especial, el llamado. descriptor - una característica de un punto en particular. El descriptor se calcula a partir de una vecindad dada del punto singular, como las direcciones de los gradientes de brillo de diferentes partes de esta vecindad. Existen varios métodos para calcular descriptores para puntos especiales: SIFT, SURF, ORB, etc. Cabe señalar que algunos métodos para calcular descriptores están patentados (por ejemplo, SIFT) y su uso comercial es limitado. Puede escuchar la conferencia con más detalle sobre puntos especiales en imágenes y métodos para trabajar con ellos. Se pueden usar puntos especiales para encontrar un objeto en una imagen. Para hacer esto, necesitamos tener una imagen del objeto deseado y luego realizar las siguientes acciones.
  1. En la imagen con el objeto, buscamos puntos especiales del objeto y calculamos sus descriptores.
  2. En la imagen analizada, también buscamos puntos singulares y calculamos descriptores para ellos.
  3. Comparamos los descriptores de los puntos especiales del objeto y los descriptores de los puntos especiales encontrados en la imagen.
  4. Si se encuentra un número suficiente de coincidencias, marcamos el área con los puntos correspondientes.
La Figura 8 a continuación muestra los resultados del método para buscar un objeto por puntos singulares.


Figura 8: detector de objetos por puntos especiales

El código fuente del ejemplo se puede descargar.

7. Métodos de aprendizaje automático

El método de búsqueda de objetos comparando conjuntos de puntos especiales tiene sus inconvenientes, uno de los cuales es la escasa capacidad de generalización. Si tenemos una tarea, por ejemplo, para seleccionar las caras de las personas en una foto, nuestro método buscará una foto específica en puntos especiales. En la foto en la que se seleccionaron los puntos especiales, el resto de caras se destacarán peor, porque lo más probable es que correspondan a otros conjuntos de puntos especiales. Los resultados pueden ser incluso peores si cambia el ángulo de la cámara. Para resolver estos problemas, ya necesitamos métodos de aprendizaje automático y no una imagen con un objeto, sino conjuntos de entrenamiento completos de cientos (y en algunos casos, cientos de miles) de imágenes diferentes con una imagen de un objeto en diferentes condiciones. Veremos la aplicación de métodos de aprendizaje automático para encontrar objetos en una imagen en la segunda parte de este artículo.

Literatura

  1. Detector de objetos ES Borisov para cámaras fijas.
    - http: //site/cv-backgr.html
  2. Procesamiento de vídeo ES Borisov: detector de objetos basado en filtros de color.
    - http: //site/cv-detector-color.html
  3. ES Borisov Métodos básicos de procesamiento de imágenes.
    - http: //site/cv-base.html
  4. Anton Konushin Visión por computadora (2011). Tema 3. Métodos sencillos de análisis de imágenes. Patrones a juego.
    - http://www.youtube.com/watch?v=TE99wDbRrUI
  5. Documentación de OpenCV: Harris Corner Detection
    - http://docs.opencv.org/3.0-beta/doc/py_tutorials/py_feature2d/py_features_harris/py_features_harris.html
  6. Wikipedia: Blob_detection
    - http://en.wikipedia.org/wiki/Blob_detection
  7. Anton Konushin Visión por computadora (2011). Clase 5. Características locales
    - http://www.youtube.com/watch?v=vFseUICis-s

Una biblioteca de aprendizaje automático y visión por computadora de código abierto. Incluye más de 2500 algoritmos, que incluyen algoritmos clásicos y modernos para visión por computadora y aprendizaje automático. Esta biblioteca tiene interfaces en varios lenguajes, entre los que se encuentran Python (lo usamos en este artículo), Java, C ++ y Matlab.

Instalación

Se pueden ver las instrucciones de instalación para Windows y para Linux -.

Importar y ver una imagen

importar cv2 imagen = cv2.imread ("./ ruta / a / imagen.extensión") cv2.imshow ("Imagen", imagen) cv2.waitKey (0) cv2.destroyAllWindows ()

Nota Al leer el método anterior, la imagen está en el espacio de color, no RGB (como todos están acostumbrados), sino BGR. Puede que no sea tan importante al principio, pero una vez que empiece a trabajar con el color, vale la pena conocer esta característica. Hay 2 soluciones:

  1. Cambie el primer canal (R - rojo) con el tercer canal (B - azul), y luego el color rojo será (0,0,255), no (255,0,0).
  2. Cambie el espacio de color a RGB: rgb_image = cv2.cvtColor (image, cv2.COLOR_BGR2RGB)

    Y luego en el código para trabajar ya no con image, sino con rgb_image.

Nota Presione cualquier tecla para cerrar la ventana en la que se muestra la imagen. Si usa el botón de cierre de la ventana, puede tropezar con bloqueos.

A lo largo del artículo, se utilizará el siguiente código para mostrar imágenes:

Importar cv2 def viewImage (image, name_of_window): cv2.namedWindow (name_of_window, cv2.WINDOW_NORMAL) cv2.imshow (name_of_window, image) cv2.waitKey (0) cv2.destroyAllWindows ()

Recortar

Perrito después de recortar

Importar cv2 recortada = imagen viewImage (recortada, "Perrito después de recortar")

Donde imagen es imagen.

Cambio de talla

Después de cambiar el tamaño en un 20%

Importar cv2 scale_percent = 20 # Porcentaje del tamaño original width = int (img.shape * scale_percent / 100) height = int (img.shape * scale_percent / 100) dim = (width, height) resized = cv2.resize (img, dim , interpolación = cv2.INTER_AREA) viewImage (redimensionado, "Después de redimensionar en un 20%")

Esta función tiene en cuenta la relación de aspecto de la imagen original. Se pueden ver otras funciones de cambio de tamaño de la imagen.

Girar

Perro después de girar 180 grados

Importar cv2 (h, w, d) = image.shape center = (w // 2, h // 2) M = cv2.getRotationMatrix2D (center, 180, 1.0) rotated = cv2.warpAffine (image, M, (w , h)) viewImage (girada, "Perrito después de una rotación de 180 grados")

image.shape devuelve alto, ancho y canales. M (Matriz de rotación): gira la imagen 180 grados alrededor del centro. -ve es la rotación de la imagen en el sentido de las agujas del reloj y + ve es en el sentido contrario a las agujas del reloj, respectivamente.

Umbral de escala de grises y blanco y negro

Perrito en escala de grises

Perrito blanco y negro

Importar cv2 gray_image = cv2.cvtColor (image, cv2.COLOR_BGR2GRAY) ret ,reshold_image = cv2.threshold (im, 127, 255, 0) viewImage (gray_image, "Perrito en escala de grises") viewImage (umbral_imagen, "Perrito blanco y negro")

gray_image es la versión de un solo canal de la imagen.

La función de umbral devuelve una imagen en la que todos los píxeles que son más oscuros (menos de) 127 se reemplazan por 0, y todos los píxeles que son más brillantes (mayores que) 127 se reemplazan por 255.

Para mayor claridad, otro ejemplo:

Ret, umbral = cv2.threshold (im, 150, 200, 10)

Aquí todo lo que es más oscuro que 150 se reemplaza por 10, y todo lo que es más brillante se reemplaza por 200.

Se describen el resto de las funciones de umbral.

Desenfoque / suavizado

Perrito borroso

Importar cv2 blur = cv2.GaussianBlur (imagen, (51, 51), 0) viewImage (borrosa, "Perrito borroso")

La función GaussianBlur toma 3 parámetros:

  1. Imagen original.
  2. Una tupla de 2 números impares positivos. Cuanto más altos sean los números, mayor será la fuerza del suavizado.
  3. sigmaX y sigmaY... Si estos parámetros se dejan iguales a 0, su valor se calculará automáticamente.

Dibujar rectángulos

Dibuja un rectángulo alrededor de la cara del perro.

Importar cv2 output = image.copy () cv2.rectangle (output, (2600, 800), (4100, 2400), (0, 255, 255), 10) viewImage (output, "Dibuja un rectángulo alrededor de la cara del perro" )

Esta función toma 5 parámetros:

  1. La propia imagen.
  2. Coordenada de la esquina superior izquierda (x1, y1).
  3. Coordenada de la esquina inferior derecha (x2, y2).
  4. Color del rectángulo (GBR / RGB según el modelo de color seleccionado).
  5. Ancho de línea del rectángulo.

Dibujo lineal

2 perros separados por una línea

Importar salida cv2 = image.copy () cv2.line (salida, (60, 20), (400, 200), (0, 0, 255), 5) viewImage (salida, "2 perros separados por una línea")

La función de línea toma 5 parámetros:

  1. La imagen real en la que se dibuja la línea.
  2. La coordenada del primer punto (x1, y1).
  3. La coordenada del segundo punto (x2, y2).
  4. Color de línea (GBR / RGB según el modelo de color seleccionado).
  5. Ancho de línea.

Texto en imagen

Imagen con texto

Importar cv2 output = image.copy () cv2.putText (output, "We<3 Dogs", (1500, 3600),cv2.FONT_HERSHEY_SIMPLEX, 15, (30, 105, 210), 40) viewImage(output, "Изображение с текстом")

La función putText toma 7 parámetros:

  1. Directamente imagen.
  2. Texto de la imagen.
  3. La coordenada de la esquina inferior izquierda del inicio del texto (x, y).
  4. Caras detectadas: 2

    Importar cv2 image_path = "./path/to/photo.extension" face_cascade = cv2.CascadeClassifier ("haarcascade_frontalface_default.xml") image = cv2.imread (image_path) gray = cv2.cvtColor (image, cv2.COLOR_Bct_BGR. , scaleFactor = 1.1, minNeighbors = 5, minSize = (10, 10)) faces_detected = "Caras detectadas:" + formato (len (caras)) print (faces_detected) # Dibuja cuadrados alrededor de las caras para (x, y, w, h ) en caras: cv2.rectangle (imagen, (x, y), (x + w, y + h), (255, 255, 0), 2) viewImage (imagen, caras_detectadas)

    detectMultiScale es una función general para reconocer caras y objetos. Para que la función busque específicamente rostros, le pasamos la cascada apropiada.

    La función detectMultiScale toma 4 parámetros:

    1. La imagen procesada en escala de grises.
    2. Parámetro ScaleFactor. Algunas caras pueden ser más grandes que otras porque están más cerca que otras. Este parámetro compensa la perspectiva.
    3. El algoritmo de reconocimiento utiliza una ventana deslizante durante el reconocimiento de objetos. El parámetro minNeighbors determina el número de objetos alrededor de la cara. Es decir, cuanto mayor sea el valor de este parámetro, más objetos similares necesita el algoritmo para definir el objeto actual como una cara. Un valor demasiado pequeño aumentará el número de falsos positivos y demasiado grande hará que el algoritmo sea más exigente.
    4. minSize es el tamaño real de estas áreas.

    Contornos: reconocimiento de objetos

    El reconocimiento de objetos se realiza mediante la segmentación de color de la imagen. Hay dos funciones para esto: cv2.findContours y cv2.drawContours.

    Este artículo detalla la detección de objetos mediante la segmentación de color. Todo lo que necesitas para ella está ahí.

    Guardar una imagen

    import cv2 image = cv2.imread ("./ import / path.extension") cv2.imwrite ("./ export / path.extension", imagen)

    Conclusión

    OpenCV es una biblioteca excelente con algoritmos livianos que se puede usar en renderizado 3D, edición avanzada de imágenes y videos, seguimiento e identificación de objetos y personas en videos, búsqueda de imágenes idénticas de un conjunto y mucho, mucho más.

    Esta biblioteca es muy importante para cualquier persona que desarrolle proyectos relacionados con el aprendizaje automático en el campo de las imágenes.

Este artículo le mostrará cómo crear un script de Python para contar la cantidad de libros en una imagen usando OpenCV.

¿Que haremos?

Echemos un vistazo a la imagen en la que buscaremos libros:

Podemos ver que hay cuatro libros en la imagen, además de elementos que distraen como una taza de café, una taza de Starbucks, algunos imanes y un caramelo.

Nuestro objetivo es encontrar los cuatro libros en la imagen sin identificar ningún otro elemento como libro.

¿Qué bibliotecas necesitamos?

Para escribir un sistema de búsqueda y descubrimiento de libros sobre imágenes, usaremos OpenCV para visión por computadora y procesamiento de imágenes. También necesitamos instalar NumPy para que OpenCV funcione correctamente. ¡Asegúrese de tener estas bibliotecas instaladas!

Búsqueda de libros sobre imágenes con Python y OpenCV

Aprox. transl. Puede notar que el código fuente de nuestro artículo difiere del código original. El autor probablemente utilizó la instalación de las bibliotecas necesarias a través de los repositorios. Sugerimos usar pip, que es mucho más fácil. Para evitar errores, recomendamos utilizar la versión del código que se proporciona en nuestro artículo.

Abra su editor de código favorito, cree un nuevo archivo llamado find_books.py y comience:

# - * - codificación: utf-8 - * - # importar paquetes requeridos import numpy as np import cv2 # cargar imagen, cambiar el color a escala de grises y quitar nitidez de la imagen = cv2.imread ("ejemplo.jpg") gray = cv2. cvtColor (imagen, cv2.COLOR_BGR2GRAY) gris = cv2.GaussianBlur (gris, (3, 3), 0) cv2.imwrite ("gray.jpg", gris)

Comencemos por importar la biblioteca OpenCV. La función cv2.imread maneja la carga de una imagen desde el disco. Aquí simplemente lo cargamos desde el disco y luego convertimos la gama de colores de RGB a escala de grises.

También difuminamos un poco la imagen para reducir el ruido de alta frecuencia y mejorar la precisión de nuestra aplicación. Después de ejecutar el código, la imagen debería verse así:

Cargamos una imagen del disco, la convertimos a escala de grises y la difuminamos un poco.

Ahora definamos los bordes (es decir, los contornos) de los objetos en la imagen:

# detección de bordes edged = cv2.Canny (gris, 10, 250) cv2.imwrite ("edged.jpg", edged)

Nuestra imagen ahora se ve así:

Encontramos los contornos de los objetos en las imágenes. Sin embargo, como puede ver, algunos de los caminos no están cerrados, hay espacios entre los caminos. Para eliminar los espacios entre los píxeles blancos de la imagen, usaremos la operación "cerrar":

# crear y aplicar un cierre kernel = cv2.getStructuringElement (cv2.MORPH_RECT, (7, 7)) closed = cv2.morphologyEx (edged, cv2.MORPH_CLOSE, kernel) cv2.imwrite ("closed.jpg", cerrado)

Ahora las brechas en los contornos están cerradas:

El siguiente paso es detectar realmente los contornos de los objetos en la imagen. Para ello usaremos la función cv2.findContours:

# encuentra los contornos en la imagen y cuenta el número de libros cnts = cv2.findContours (closed.copy (), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) total = 0

Considere la geometría del libro.

El libro es un rectángulo. El rectángulo tiene cuatro vértices. Por lo tanto, si miramos el contorno y encontramos que tiene cuatro vértices, podemos asumir que se trata de un libro y no de otro objeto de la imagen.

Para comprobar si una ruta es un libro o no, necesitamos recorrer cada ruta:

# bucle a lo largo de los contornos para c en cnts: # aproximar (suavizar) el contorno peri = cv2.arcLength (c, True) approx = cv2.approxPolyDP (c, 0.02 * peri, True) # si el contorno tiene 4 vértices, suponga que es un libro si len (approx) == 4: cv2.drawContours (image ,, -1, (0, 255, 0), 4) total + = 1

Para cada una de las rutas, calculamos el perímetro usando cv2.arcLength y luego aproximamos (suaviza) la ruta usando cv2.approxPolyDP.

La razón por la que estamos aproximando la ruta es porque puede que no sea un rectángulo perfecto. Debido al ruido y las sombras en la foto, es poco probable que el libro tenga exactamente 4 vértices. Aproximando el contorno, resolvemos este problema.

Finalmente, comprobamos que el contorno a aproximar sí tiene cuatro vértices. Si es así, dibujamos un contorno alrededor del libro y luego incrementamos el contador para el número total de libros.

Terminemos este ejemplo mostrando la imagen resultante y la cantidad de libros encontrados:

# mostrar la impresión de la imagen resultante ("Encontré (0) libros en esta imagen" .format (total) cv2.imwrite ("output.jpg", image))

En esta etapa, nuestra imagen se verá así:

Resumamos

En este artículo, aprendió cómo encontrar libros en imágenes utilizando técnicas simples de procesamiento de imágenes y visión por computadora con Python y OpenCV.

Nuestro enfoque fue:

  1. Cargue una imagen del disco y conviértala a escala de grises.
  2. Difumina un poco la imagen.
  3. Aplique el detector de bordes Canny para detectar objetos en la imagen.
  4. Cierra los huecos en los caminos.
  5. Encuentra contornos de objetos en la imagen.
  6. Aplique la aproximación de contorno para determinar si el contorno era un rectángulo y, por lo tanto, un libro.

Puede descargar el código fuente del script y la imagen que se utiliza en este artículo.

La idea principal es tener en cuenta las relaciones estadísticas entre la ubicación de los puntos antropométricos del rostro. En cada imagen de la cara, los puntos están numerados en el mismo orden. La comparación de caras se realiza según su posición relativa.

Para comparar rostros, puede utilizar la misma posición del rostro en relación con la cámara. Más preferible para esto.

Capturar una transmisión de video desde una cámara y resaltar una cara

#incluir usando el espacio de nombres cv; int main () (// Cargar Face cascade (archivo .xml) CascadeClassifier face_cascade; face_cascade.load ("haarcascade_frontalface_alt2.xml"); Mat img; VideoCapture cap (0); while (true) (cap >> img; // cvtColor (img, img, CV_BGR2GRAY); // Detectar caras std :: vector caras; face_cascade.detectMultiScale (img, caras, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, Tamaño (30, 30)); // Dibuja círculos en las caras detectadas para (int i = 0; i< faces.size(); i++) { Point center(faces[i].x + faces[i].width*0.5, faces[i].y + faces[i].height*0.5); ellipse(img, center, Size(faces[i].width*0.5, faces[i].height*0.5), 0, 0, 360, Scalar(255, 0, 255), 4, 8, 0); } imshow("Detected Face", img); waitKey(1); } return 0; }

Los archivos en cascada se encuentran en el directorio c: \ opencv \ build \ etc \ ... Coloque la cascada requerida en el directorio del proyecto, en el mismo lugar que el archivo fuente main.cpp.

Resaltando puntos faciales

La aplicación está basada en código C ++ para OpenCV Facemark

#incluir #incluir #incluir #incluir #incluir #incluir #incluya "drawLandmarks.hpp" usando el espacio de nombres std; usando el espacio de nombres cv; usando el espacio de nombres cv :: face; int main (int argc, char ** argv) (// Cargar el detector de caras CascadeClassifier faceDetector ("haarcascade_frontalface_alt2.xml"); // Crear una instancia de Facemark Ptr facemark = FacemarkLBF :: crear (); // Cargar el detector de puntos de referencia facemark-> loadModel ("lbfmodel.yaml"); // Configurar cámara web para captura de video VideoCapture cam (0); // Variable para almacenar un fotograma de video y su fotograma Mat en escala de grises, gris; // Leer un fotograma while (cam.read (fotograma)) (// Encontrar vector de cara caras; // Convierta el fotograma a escala de grises porque // faceDetector requiere una imagen en escala de grises. cvtColor (marco, gris, COLOR_BGR2GRAY); // Detectar caras faceDetector.detectMultiScale (gris, caras); // Variable para puntos de referencia. // Los puntos de referencia de una cara son un vector de puntos // Puede haber más de una cara en la imagen. Por tanto, // usamos un vector de vector de puntos. vector< vector> puntos de referencia; // Ejecutar el detector de hitos bool success = facemark->< faces.size(); i++) { cv::rectangle(frame, faces[i], Scalar(0, 255, 0), 3); } for (int i = 0; i < landmarks.size(); i++) { drawLandmarks(frame, landmarks[i]); /*for (size_t j = 0; j < landmarks[i].size(); j++) circle(frame, Point(landmarks[i][j].x, landmarks[i][j].y), 1, Scalar(255, 0, 0), 2);*/ } } // Display results imshow("Facial Landmark Detection", frame); // Exit loop if ESC is pressed if (waitKey(1) == 27) break; } return 0; }

En el proyecto de la aplicación, en el mismo lugar que el archivo main.cpp, archivos publicados haarcascade_frontalface_alt2.xml, drawLandmarks.hpp y lbfmodel.yaml a los que se hace referencia en el código. Los archivos en cascada se encuentran en el directorio c: \ opencv \ build \ etc \ .... drawLandmarks.hpp y lbfmodel.yaml disponible en el archivo Facemark_LBF.rar.

Después de pegar el código, aparecieron errores debido al hecho de que OpenCV 3.4.3-vc14-vc15 carece de una serie de bibliotecas necesarias para ejecutar la aplicación. Vinculé mi biblioteca (descargue opencv_new.zip) y la instalé en la raíz de la unidad C (C: \ opencv-new).

Ahora, todas las configuraciones que se realizaron deben realizarse para opencv-new:

Realizar ajustes en Windows... Voy a la ventana "Cambiar variable de entorno" (botones de Windows -> Herramientas del sistema -> Panel de control -> Sistema y seguridad -> Sistema -> Configuración avanzada del sistema -> Variables de entorno -> Ruta -> Cambiar). En esta ventana creo la variable C: \ opencv-nuevo\ x64 \ vc14 \ bin. Reiniciar Windows.

En propiedades del proyecto también consulte la biblioteca opencv_new (en lugar de opencv). En la ventana "Páginas de propiedades", hago lo siguiente:

  • C / C ++ -> General -> Directorios de inclusión adicionales -> C: \ opencv-nuevo\ incluir
  • Vinculador -> General -> Directorios de bibliotecas adicionales -> C: \ opencv-nuevo\ x64 \ vc14 \ lib
  • Vinculador -> Entrada -> Dependencias adicionales -> opencv_core400.lib; opencv_face400.lib; opencv_videoio400.lib; opencv_objdetect400.lib; opencv_imgproc400.lib; opencv_highgui400.lib

Al inicio, el programa genera un error si Debug. Para el lanzamiento, el lanzamiento es exitoso.


Seleccionar funciones para el filtrado de imágenes y el reconocimiento facial

El marco punteado de la cara se muestra de diferentes formas dependiendo de factores objetivos y subjetivos.

Los factores objetivos son la posición del rostro en relación con la cámara.

Factores subjetivos: iluminación irregular o deficiente, distorsión facial debido a emociones, ojos entrecerrados, etc. En estos casos, la estructura alámbrica puede no ser correcta, los puntos pueden incluso arrancarse de la cara:

A veces, estas imágenes se omiten durante la captura de video. Deben filtrarse, tanto durante el entrenamiento como durante el reconocimiento.

Algunos de los puntos son los más estables e informativos. Están rígidamente unidos a la cara, independientemente de su posición con respecto a la cámara. Además, caracterizan bien las particularidades del rostro. Estos puntos se pueden utilizar como base para modelar el sistema de características.

Puede utilizar una estructura alámbrica de puntos 2D de la misma posición de cara para comparar caras. ¿Cuál es la posición más informativa de su rostro en relación con la cámara? Evidentemente frontal. No en vano, la ciencia forense se toma una foto de perfil y rostro completo. Por ahora, nos limitaremos a la cara completa.

Todos los signos (distancias) deben ser adimensionales (normalizados), es decir, correlacionados con algún tamaño (distancia). Supongo que el tamaño más adecuado para esto es la distancia entre los puntos medios de las esquinas de los ojos. ¿Por qué no, por ejemplo, los puntos de las esquinas exteriores de los ojos, que en realidad están definidos en la matriz de puntos de referencia? El caso es que las esquinas de los ojos se separan (se acercan) al responder a un cambio de color, expresión de sorpresa, parpadeo, etc. La distancia entre los centros de los ojos neutraliza estas fluctuaciones y, por lo tanto, es más preferible.

¿Qué signo tomaremos como base en la primera aproximación? Asumo la distancia desde la parte superior del puente de la nariz hasta la parte inferior del mentón. A juzgar por la foto, este letrero puede diferir significativamente para diferentes personas.

Entonces, antes de formar rasgos para el entrenamiento y la comparación, es necesario filtrar los cuadros de puntos de rostros obtenidos por captura de video, que, por razones subjetivas u objetivas, no son la imagen frontal correcta del rostro (rostro completo).

Dejamos solo aquellos wireframes de puntos que siguen los siguientes criterios:

  • La línea recta que pasa por los puntos extremos de los ojos (línea de los ojos) es perpendicular a la línea que pasa por los puntos extremos de la nariz (línea de la nariz).
  • La línea de los ojos es paralela a la línea recta que pasa por las comisuras de la boca (línea de la boca).
  • Los puntos anteriores son simétricos con respecto a la línea de la nariz.
  • Los puntos de las esquinas de los ojos (externos e internos) están en la misma línea recta.

Un ejemplo de imágenes frontales que muestran todos los signos:

Un ejemplo de imágenes que se filtran:

Intente determinar por sí mismo cuál de los signos no pasa las imágenes.

¿Cómo se formalizan las funciones que proporcionan filtrado y reconocimiento facial? Básicamente, se basan en las condiciones para determinar las distancias entre puntos, las condiciones de paralelismo y perpendicularidad. La tarea de formalizar tales signos se discute en el tema.

Algoritmo para el reconocimiento facial mediante una estructura alámbrica 2D de puntos

Las coordenadas de los puntos de la estructura alámbrica de la cara se establecen inicialmente en el sistema de coordenadas, que está anclado al punto superior izquierdo de la ventana. En este caso, el eje Y se dirige hacia abajo.

Para la conveniencia de identificar características, utilizamos un sistema de coordenadas personalizado (UCS), cuyo eje X pasa a través del segmento entre los puntos medios de los ojos, y el eje Y es perpendicular a este segmento a través de su centro en la dirección ascendente. Las coordenadas UCS (de -1 a +1) están normalizadas, correlacionadas con la distancia entre los puntos medios de los ojos.

UCS proporciona conveniencia y simplicidad en la identificación de características. Por ejemplo, la posición de la cara en la vista frontal está determinada por el signo de simetría de los puntos correspondientes de los ojos en relación con la línea de la nariz. Esta característica se formaliza por la coincidencia de la línea de la nariz con el eje Y, es decir, X1 = X2 = 0, donde X1 y X2 son las coordenadas de los puntos extremos de la nariz (27 y 30) en el UCS.

Determinación relativa a la ventana SC

Las coordenadas de los puntos medios de los ojos izquierdo y derecho (izquierdo y derecho):

XL = (X45 + X42) / 2; YL = (Y45 + Y42) / 2; XR = (X39 + X 36) / 2; YR = (Y39 + Y 36) / 2;

Inicio de UCS:

X0 = (XL + XR) / 2; Y0 = (YL + YR) / 2;

Distancias entre los puntos medios de los ojos a lo largo de los ejes X e Y:

DX = XR - XL; DY = YR - YL;

La distancia real L entre los puntos medios de los ojos (según el teorema de Pitágoras):

L = raíz cuadrada (DX ** 2 + DY ** 2)

Funciones trigonométricas del ángulo de rotación UCS:

Pasar de coordenadas en CS con ventana a coordenadas en UCS utilizando los parámetros X0, Y0, L, sin AL, cos AL:

X_User_0 = 2 (X_Window - X0) / L;

Y_User_0 = - 2 (Y_Window - Y0) / L;

X_User= X_User_0 * cos_AL - Y_User_0 * sin_AL;

Y_User= X_User_0 * sin_AL + Y_User_0 * cos_AL;

Implementar el filtrado de imágenes comprobando constantemente las señales:

1.Un signo de la perpendicularidad de las líneas de la nariz y los ojos, así como la simetría de las esquinas de los ojos.... La línea de morro está definida por los puntos 27 y 30 (ver figura c). Ambos signos se cumplen si las coordenadas de estos puntos en el UCS son X1 = X2 = 0 (es decir, la línea de la nariz coincide con el eje Y).

2.Un signo de paralelismo de la línea de los ojos y la línea de la boca... La línea de la boca está definida por los puntos 48 y 54 (ver figura c). La característica se cumple si en el UCS Y1-Y2 = 0.

3. Signo de simetría de las comisuras de la boca... La línea de la boca está definida por los puntos 48 y 54 (ver figura c). La característica se cumple si en UCS X1 + X2 = 0

4. Firmar "Los puntos de las esquinas de los ojos están en la misma línea recta".... Las líneas se definen por pares de puntos: (36 y 45), así como (39 y 42). Dado que la prueba del atributo 1 ya ha sido superada, basta con definir en el UCS el atributo Y2-Y1 = 0 solo para los puntos 36 y 39.

No puede haber una igualdad absoluta con cero, por lo que las características se comparan con un valor ciertamente pequeño.

El programa para comparar caras por una característica.

La distancia entre los puntos del puente de la nariz y el mentón se toma como señal (Puntos de referencia 27 y 8, ver figura c). La característica, normalizada, se define en el UCS por la relación: (Y1 - Y2) / L, donde L es la distancia entre los centros de los ojos. Al entrenar el programa, el signo de una persona específica está determinado por el número que se muestra junto a la persona rastreada (esta parte del código está comentada en el programa). Durante el reconocimiento, el valor de una característica se compara con una característica específica ingresada en el programa para cada persona. Si la comparación es positiva, su identificador aparece junto al rostro.

El programa también reconoce la foto en la que tengo 15 años menos, y hasta con bigote. La diferencia en la foto es significativa, no todos se darán cuenta. Pero no se puede engañar a un programa de computadora.

Tareas de control:

  1. Familiarízate con el programa.
  2. Determine el significado de la característica para su rostro y para varios de sus colegas.
  3. Pruebe el programa para la identificación de personas (propias y de colegas).

#incluir #incluir #incluir #incluir #incluir #incluir #incluya "drawLandmarks.hpp" usando el espacio de nombres std; usando el espacio de nombres cv; usando el espacio de nombres cv :: face; int main (int argc, char ** argv) (// Cargar el detector de caras CascadeClassifier faceDetector ("haarcascade_frontalface_alt2.xml"); // Crear una instancia de Facemark Ptr facemark = FacemarkLBF :: crear (); // Cargar el detector de puntos de referencia facemark-> loadModel ("lbfmodel.yaml"); // Configurar cámara web para captura de video VideoCapture cam (0); // Variable para almacenar un fotograma de video y su fotograma Mat en escala de grises, gris; // Leer un fotograma while (cam.read (fotograma)) (// Encontrar vector de cara caras; // Convierta el fotograma a escala de grises porque // faceDetector requiere una imagen en escala de grises. cvtColor (marco, gris, COLOR_BGR2GRAY); // Detectar caras faceDetector.detectMultiScale (gris, caras); // Variable para puntos de referencia. // Los puntos de referencia de una cara son un vector de puntos // Puede haber más de una cara en la imagen. Por tanto, // usamos un vector de vector de puntos. vector< vector> puntos de referencia; // Ejecutar detector de hitos bool success = facemark-> fit (frame, faces, landmarks); if (success) (// Si tiene éxito, renderice los puntos de referencia en la cara para (size_t i = 0; i< faces.size(); i++) { cv::rectangle(frame, faces[i], Scalar(0, 255, 0), 3); } for (int i = 0; i < landmarks.size(); i++) { //if((i >= 30) && (i<= 35)) drawLandmarks(frame, landmarks[i]); for (size_t j = 0; j < landmarks[i].size(); j++) { circle(frame, Point(landmarks[i][j].x, landmarks[i][j].y), 1, Scalar(255, 0, 0), 2); } line(frame, Point(landmarks[i].x, landmarks[i].y), Point(landmarks[i].x, landmarks[i].y), Scalar(0, 0, 255), 2); float XL = (landmarks[i].x + landmarks[i].x) / 2; float YL = (landmarks[i].y + landmarks[i].y) / 2; float XR = (landmarks[i].x + landmarks[i].x) / 2; float YR = (landmarks[i].y + landmarks[i].y) / 2; line(frame, Point(XL, YL), Point(XR, YR), Scalar(0, 0, 255), 2); float DX = XR - XL; float DY = YR - YL; float L = sqrt(DX * DX + DY * DY); float X1 = (landmarks[i].x); float Y1 = (landmarks[i].y); float X2 = (landmarks[i].x); float Y2 = (landmarks[i].y); float DX1 = abs(X1 - X2); float DY1 = abs(Y1 - Y2); float L1 = sqrt(DX1 * DX1 + DY1 * DY1); float X0 = (XL + XR) / 2; float Y0 = (YL + YR) / 2; float sin_AL = DY / L; float cos_AL = DX / L; float X_User_0 = (landmarks[i].x - X0) / L; float Y_User_0 = -(landmarks[i].y - Y0) / L; float X_User27 = X_User_0 * cos_AL - Y_User_0 * sin_AL; float Y_User27 = X_User_0 * sin_AL + Y_User_0 * cos_AL; X_User_0 = (landmarks[i].x - X0) / L; Y_User_0 = -(landmarks[i].y - Y0) / L; float X_User30 = X_User_0 * cos_AL - Y_User_0 * sin_AL; float Y_User30 = X_User_0 * sin_AL + Y_User_0 * cos_AL; if (abs(X_User27 - X_User30) <= 0.1) { //putText(frame, std::to_string(abs(L1 / L)), Point(landmarks[i].x, landmarks[i].y), 1, 2, Scalar(0, 0, 255), 2); if (abs((L1 / L) - 1.6) < 0.1) { putText(frame, "Roman", Point(landmarks[i].x, landmarks[i].y), 1, 2, Scalar(0, 0, 255), 2); } if (abs((L1 / L) - 1.9) < 0.1) { putText(frame, "Pasha", Point(landmarks[i].x, landmarks[i].y), 1, 2, Scalar(0, 0, 255), 2); } if (abs((L1 / L) - 2.1) < 0.1) { putText(frame, "Svirnesvkiy", Point(landmarks[i].x, landmarks[i].y), 1, 2, Scalar(0, 0, 255), 2); } } putText(frame, "Incorrect", Point(landmarks[i].x, landmarks[i].y), 1, 2, Scalar(0, 0, 255), 2); } } // Display results imshow("Facial Landmark Detection", frame); // Exit loop if ESC is pressed if (waitKey(1) == 27) break; } return 0; }

Las fuentes de información más importantes sobre el mundo exterior para un robot son sus sensores ópticos y cámaras. Después de recibir la imagen, es necesario procesarla para analizar la situación o tomar una decisión. Como dije anteriormente, visión por computador combina muchos métodos de trabajo con imágenes. Durante la operación del robot, se supone que la información de video de las cámaras es procesada por algún programa que se ejecuta en el controlador. Para no escribir código desde cero, puede utilizar soluciones de software listas para usar. Por el momento, hay muchas bibliotecas de visión por computadora listas para usar:

  • Biblioteca de imágenes de Matrox
  • Biblioteca camelia
  • Abrir eVision
  • HALCON
  • libCVD
  • Opencv
  • etc ...
Los datos del SDK pueden variar mucho en cuanto a funcionalidad, términos de licencia y lenguajes de programación utilizados. Nos detendremos en Opencv... Es gratuito tanto para fines educativos como para uso comercial. Está escrito en C / C ++ optimizado, admite interfaces C, C ++, Python, Java e incluye más de 2500 algoritmos. Además de las funciones estándar de procesamiento de imágenes (filtrado, desenfoque, transformaciones geométricas, etc.), este SDK permite resolver tareas más complejas, que incluyen la detección de un objeto en una fotografía y su "reconocimiento". Debe entenderse que las tareas de detección y reconocimiento pueden ser completamente diferentes:
  • búsqueda y reconocimiento de un objeto específico,
  • buscar objetos de la misma categoría (sin reconocimiento),
  • solo reconocimiento de objetos (una imagen confeccionada con él).
Para detectar características en una imagen y buscar una coincidencia, OpenCV tiene los siguientes métodos:
  • Histograma de gradientes orientados (HOG): se puede utilizar para detectar peatones
  • Algoritmo de Viola-Jones: utilizado para encontrar caras
  • Algoritmo de detección de características SIFT (Scale Invariant Feature Transform)
  • Algoritmo de detección de características SURF (características robustas aceleradas)
Por ejemplo, SIFT detecta conjuntos de puntos que se pueden utilizar para identificar un objeto. Además de las técnicas anteriores, OpenCV cuenta con otros algoritmos de detección y reconocimiento, así como un conjunto de algoritmos relacionados con el aprendizaje automático, como k vecinos más cercanos, redes neuronales, máquinas de vectores de soporte, etc. En general, OpenCV proporciona un kit de herramientas suficiente para resolver la gran mayoría de los problemas de visión por computadora. Si el algoritmo no está incluido en el SDK, entonces, como regla, se puede programar sin problemas. Además, existen muchas versiones de autor de algoritmos escritos por usuarios basados ​​en OpenCV. También debe tenerse en cuenta que en los últimos años OpenCV se ha expandido mucho y se ha convertido en algo "pesado". En este sentido, diferentes grupos de entusiastas están creando bibliotecas "ligeras" basadas en OpenCV. Ejemplos: SimpleCV, liuliu ccv, tinycv ... Sitios útiles
  1. http://opencv.org/: el sitio principal del proyecto
  2. http://opencv.willowgarage.com/wiki/ - Sitio del proyecto antiguo con documentación para versiones antiguas