Entrenar OpenCV en Detección de Objetos

OpenCV cuenta con varios clasificadores en cascada entrenados que podemos encontrar en el directorio opencv\build\etc\haarcascades ó en opencv\build\etc\lbpcascades estos clasificadores nos sirven para la detección de caras o rostros, nariz, boca, placas de autos, rostros de gatos, entre otras cosas, en caso de que deseemos detectar otro tipo de objeto podemos entrenas nuestros propios clasificadores para que detecte por ejemplo, un animal determinado, un automóvil, un teléfono celular o lo que deseemos según lo requiera el proyecto que realicemos.

opencv object detect
En la carpeta opencv\build\x86\vc11\bin podemos encontrar los ejecutables opencv_createsamples.exe y opencv_traincascade.exe que nos ayudaran ha realizar el trabajo de entrenamiento de manera sencilla, el primero prepara el conjunto de imágenes positivas y el otro genera el clasificador en cascada.

La primera tarea que debemos realizar es recolectar el conjunto de imágenes, necesitaremos un conjunto positivo y uno negativo, el conjunto de imágenes positivas en aquel que contiene varias imágenes con el objeto que deseamos detectar con OpenCV y el negativo son todas aquellas imágenes que no contengan el objeto.

Detección de Autos con OpenCV


Para construir este ejemplo usaremos el conjunto de imágenes obtenidos de Datasets for Computer Vision Research donde encontraremos varios bases de datos de imágenes que podemos utilizar para entrenar OpenCV, seleccionaremos las imágenes para detectar autos UIUC Image Database for Car Detection

car dataset opencv


Lo primero que haremos será abrir CMD y ejecutar con el comando:
cd C:\opencv\build\x86\vc11\bin
Nos movemos a la carpeta que contiene las aplicaciones opencv_createsamples.exe y opencv_traincascade.exe.

Usaremos el siguiente comando para crear el archivo binario cars.vec correspondiente a las imágenes positivas, usaremos la aplicación opencv_createsamples.exe también requerimos la carpeta con las imágenes positivas, la llamaremos pos, además del archivo de texto cars.info que nos indica donde localizarlas.

Por facilidad copiamos el archivo cars.info y la carpeta pos en la misma carpeta donde se encuentra el ejecutable opencv_createsamples.exe

opencv_createsamples -info cars.info -num 550 -w 48 -h 24 -vec cars.vec

opencv_createsample.exe

Una vez tenemos el binario cars.vec procedemos a crear el cascade.xml esta vez usaremos la aplicación opencv_traincascade.exe, esta vez necesitaremos el archivo neg.info y la carpeta neg con las imágenes negativas.

Copiamos neg.info y carpeta neg en el directorio donde anterior, además creamos una carpeta llamada data, donde se almacenara nuestro cascade.xml.

opencv_traincascade -data data -vec cars.vec -bg neg.info -numPos 500 -numNeg 500 -numStages 10 -w 48 -h 24 -featureType LBP

Para conocer detalles sobre las aplicaciones opencv_createsamples, opencv_traincascade y sus parámetros visitar la documentación: Cascade Classifier Training

Cargar Clasificador en Cascada


El siguiente código nos muestra como cargar el clasificador que acabamos de crear, funciona igual que cualquier otro clasificador, incluso podemos usar el código del proyecto Detección de Rostros en Tiempo Real solo cambiamos el clasificador .xml y podremos detectar autos con la webcam.

Para este ejemplo usaremos las imágenes de prueba que vienen con la base de datos que descargamos, haremos que la aplicación pruebe con un grupo de las primera 20 imágenes, las mismas irán cambiando al presionar una tecla.

#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main(int argc, char** argv)
{

	String TEST_DIR = "data\\data_file\\test";
	String CAR_CXML = "data\\data_file\\cascade.xml";
	String NAME_WIN = "Entrenar OpenCV";

	CascadeClassifier car_detector;

	if (!car_detector.load(CAR_CXML)) { cout << "Error en el archivo: " + CAR_CXML << endl; return -1; };

	for (int i = 0; i < 20; i++)
	{
		std::stringstream number;
		number << i;

		String image_test = TEST_DIR + "\\test-" + number.str() + ".pgm";
		Mat image = imread(image_test, 1);

		if (!image.data) { cout << "No image data." << endl; return -1; }

		std::vector<Rect> rc;

		car_detector.detectMultiScale(image, rc, 1.1, 8);

		for (size_t i = 0; i < rc.size(); i++)
		{
			rectangle(image, Point(rc[i].x, rc[i].y), Point(rc[i].x + rc[i].width, rc[i].y + rc[i].height), CV_RGB(0, 255, 0), 1);
		}

		namedWindow(NAME_WIN, WINDOW_AUTOSIZE);
		imshow(NAME_WIN, image);
		waitKey(0);
	}

	return 0;
}


Debemos tener en cuenta que nuestro clasificador no es perfecto, está construido de la manera más simple posible, un clasificador bueno requiere de una colección de imágenes positivas y negativas bastante amplia.

Especificando los parámetros adecuados a la hora de crear el clasificador podemos mejoras su eficacia, pero debemos tener en cuenta que un buen entrenamiento puede tardar muchas horas o hasta días.

Puedes encontrar el proyecto completo en: GitHub Tutor de Programación

Comentarios

  1. hola! no encuentro el archivo cars.info... sólo he encontrado un readme.txt...

    ResponderEliminar
    Respuestas
    1. Puedes encontrar los archivos necesarios en la carpeta image_dataset que se encuentra en el repositorio GitHub.
      https://github.com/TutorProgramacion/opencv-traincascade
      Olvide subirla, gracias por el comentario.

      Eliminar
  2. gracias, es que encontré el archivo de otro repositorio, pero creo que no es el mismo... y las carpetas neg y pos, las he hecho partiendo en dos el archivo donde están todas las fotos. Bueno, voy a intentarlo de nuevo con los nuevos archivos...-porque me está dando error en el .exe de createsamples y en el array.cpp Gracias.Un saludo

    ResponderEliminar
  3. Ya he cambiado los archivos, gracias. Una última pregunta: Para el test de "entrenamiento", el .cpp lo ejecuto desde dónde? Gracias de antemano

    ResponderEliminar
  4. Hola de nuevo, lo he compilado y ejecutado con Dev_Cpp, pero no encuentra opencv.hpp-

    ResponderEliminar
  5. He puesto todo el camino para que encuentre el archivo y parece que funciona, pero todavía no lo he conseguido del todo...

    ResponderEliminar
  6. Ya lo he solucionado. Gracias, era la plataforma al hacer el build.

    ResponderEliminar
    Respuestas
    1. Que bueno que lo solucionaras por tu cuenta, pequeños detalles hacen una gran diferencia.

      Eliminar
  7. Hola, no tienen este ejemplo en Python? :c

    ResponderEliminar
  8. Puedes hacer tutoriales de Reconocimiento Facial, Pero usando el Lenguaje Java, pues he visto varios tutoriales suyos, escritos en c++, pero se me dificulta traducirlo a java. Tambien seria bueno que hicieras un tutorial en donde se explique como detectar si la persona está dormida, y hacer sonar una alarma. Yo he realizado parte de los dos proyectos que he mencionado, pero no he podido terminarmlos.. No encuentro la solucion. Gracias.

    ResponderEliminar
  9. Buenas, estoy trabajando en la version 3.1 y con ubuntu. Al ejecutarlo el codigo se me queda colgado. Tengo unos printf para ver hasta donde ejecuta y se para en : "Mat image = imread(image_test, 1);"

    Sabes por que puede ser?
    Muchas gracias.

    ResponderEliminar
    Respuestas
    1. Verifica las rutas de las carpetas y archivos.

      Eliminar
  10. Todos estos tutoriales se los puede trabajar con python tambien ?

    ResponderEliminar

Publicar un comentario

Entradas populares de este blog

Conectar SQL Server con Java

Procesamiento de imágenes en OpenCV

Acceso a la webcam con OpenCV

Conociendo la clase cv::Mat de OpenCV