Seguimiento de Objetos por Color
Esta vez intentaremos detectar un objeto basándonos en su color, esta técnico nos servirá para detectar objetos de un color uniforme, veremos cómo extraer las coordenadas en las que se encuentre el color que deseamos detectar y como resaltar el objeto encontrado.
Lo primero que haremos será cambiar el color space de BGR a HSV, de este modo podemos establecer un filtro para obtener solo aquellas secciones de la imagen cuyo color se encuentre en el rango de color indicado, en HSV es más fácil establecer este rango.
Realizar la conversión es fácil, usamos la función cvtColor(src, dst, CV_BGR2HSV) indicamos la imagen fuente, destino y el tipo de conversión que puede ser: COLOR_BGR2HSV, COLOR_RGB2HSV, COLOR_HSV2BGR, COLOR_HSV2RGB.
Para filtrar solo aquellos colores que se encuentren en el rango indicado usaremos la función inRange, para este ejemplo filtraremos el color azul, por lo que los rangos superior e inferior estarán definidos de la siguiente manera: inferior { Scalar(110, 50, 50) }, superior { Scalar(130, 255, 255) } en HSV color space.
Este es el resultado de filtrar el color azul con la función inRange, obtenemos una imagen binaria donde el color blanco representa las áreas que contienen el color filtrado.
Para descartar aquellos segmentos no deseados usaremos las transformaciones morfológicas erode y dilate, los configuramos para buscar elementos rectangulares (MORPH_RECT) en nuestra imagen binaria, MORPH_ELLIPSE para figuras circulares.
En este punto lo siguiente que debemos hacer es encontrar las coordenadas donde se encuentra nuestra región de interés, OpenCV cuenta con funciones de búsqueda de contornos que utilizaremos para este propósito, findContours(binary, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE), binary es la imagen binaria que creamos anteriormente, contours es la variable tipo vector<vector<Point>> donde se almacenaran los contornos encontrados, CV_RETR_EXTERNAL indica que solo necesitamos los contornos externos.
Para finalizar utilizaremos la información obtenida de los contornos para dibujar un rectángulo sobre la imagen original y marcar el color seleccionado, agregamos también el texto con las coordenadas correspondientes, estas coordenadas las obtenemos con la función Rect r = boundingRect(contour);, la función rectangle y putText dibujan el rectángulo y el texto, las hemos visto en tutoriales anteriores.
Finalmente tenemos el siguiente resultado:
GitHub: Seguimiento de Objeto por Color
Lo primero que haremos será cambiar el color space de BGR a HSV, de este modo podemos establecer un filtro para obtener solo aquellas secciones de la imagen cuyo color se encuentre en el rango de color indicado, en HSV es más fácil establecer este rango.
Realizar la conversión es fácil, usamos la función cvtColor(src, dst, CV_BGR2HSV) indicamos la imagen fuente, destino y el tipo de conversión que puede ser: COLOR_BGR2HSV, COLOR_RGB2HSV, COLOR_HSV2BGR, COLOR_HSV2RGB.
Para filtrar solo aquellos colores que se encuentren en el rango indicado usaremos la función inRange, para este ejemplo filtraremos el color azul, por lo que los rangos superior e inferior estarán definidos de la siguiente manera: inferior { Scalar(110, 50, 50) }, superior { Scalar(130, 255, 255) } en HSV color space.
// obtener frame de la web cam cap >> img; // convertir imagen RGB a HSV cvtColor(img, hsv, CV_BGR2HSV); // aplicar filtro para color deseado inRange(hsv, Scalar(110, 50, 50), Scalar(130, 255, 255), binary); // aplicar tranformaciones morfologicas (extrae la region de interes) Mat element = getStructuringElement(MORPH_RECT, Size(15, 15)); erode(binary, binary, element); dilate(binary, binary, element);
Este es el resultado de filtrar el color azul con la función inRange, obtenemos una imagen binaria donde el color blanco representa las áreas que contienen el color filtrado.
Para descartar aquellos segmentos no deseados usaremos las transformaciones morfológicas erode y dilate, los configuramos para buscar elementos rectangulares (MORPH_RECT) en nuestra imagen binaria, MORPH_ELLIPSE para figuras circulares.
En este punto lo siguiente que debemos hacer es encontrar las coordenadas donde se encuentra nuestra región de interés, OpenCV cuenta con funciones de búsqueda de contornos que utilizaremos para este propósito, findContours(binary, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE), binary es la imagen binaria que creamos anteriormente, contours es la variable tipo vector<vector<Point>> donde se almacenaran los contornos encontrados, CV_RETR_EXTERNAL indica que solo necesitamos los contornos externos.
// buscar contornos en la imagen binaria vector< vector<Point> > contours; findContours(binary, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE); // dibujar todos los contornos encontrados drawContours(binary, contours, -1, Scalar(255), CV_FILLED);
Para finalizar utilizaremos la información obtenida de los contornos para dibujar un rectángulo sobre la imagen original y marcar el color seleccionado, agregamos también el texto con las coordenadas correspondientes, estas coordenadas las obtenemos con la función Rect r = boundingRect(contour);, la función rectangle y putText dibujan el rectángulo y el texto, las hemos visto en tutoriales anteriores.
// dibujar rectangulo y texto con coordenadas (x, y) for (vector<Point> contour : contours) { Rect r = boundingRect(contour); rectangle(img, r.tl(), r.br(), CV_RGB(255, 0, 0), 2, CV_AA, 0); Point center(r.x + (r.width / 2), r.y + (r.height / 2)); ostringstream str; str << center.x << "," << center.y; putText(img, str.str(), center, FONT_HERSHEY_COMPLEX_SMALL, 0.60, CV_RGB(0, 255, 0), 1, CV_AA); }
Finalmente tenemos el siguiente resultado:
GitHub: Seguimiento de Objeto por Color
Hola. Lo acabo de ejecutar. Mi computadora tiene cámara y conectó directamente (Apple iMac). Me estoy divirtiendo tirando una botellita azul que tengo en la mano al aire. Genial. Muchas gracias.
ResponderEliminarSaludos apenas me estoy familiarizando con el uso de POO en c++ y pues aprendiendo a usar opencv ...gracias por el curso; Con el se acelera el aprendizaje.
ResponderEliminarEs posible crear esto en app inventor?
ResponderEliminarHola! muy bueno tu codigo. Veras, necesito manipular las coordenadas de cada objeto que aparecen en la imagen final de la camara, sin embargo no he logrado hacerlo, te agradeceria mucho si puedes ayudarme, gracias,saludos.
ResponderEliminarno lo tienes en python?
ResponderEliminar