Difference between revisions of "Segmentación de la imagen"

From robotica.unileon.es
Jump to: navigation, search
m
m
 
(9 intermediate revisions by one other user not shown)
Line 1: Line 1:
== Introducción ==
+
=Introducción=
  
 
La segmentación de una imagen es un proceso que suele ser el segundo paso para analizar una imagen digital y tiene lugar normalmente después del pre-procesamiento de la imagen. Una secuencia típica de un sistema de tratamiento de imagen podría ser: Captura de la imagen → Pre-procesamiento → Segmentación → Extracción de características → Post-procesado.
 
La segmentación de una imagen es un proceso que suele ser el segundo paso para analizar una imagen digital y tiene lugar normalmente después del pre-procesamiento de la imagen. Una secuencia típica de un sistema de tratamiento de imagen podría ser: Captura de la imagen → Pre-procesamiento → Segmentación → Extracción de características → Post-procesado.
Line 7: Line 7:
 
En los ejemplos que se mostrarán a continuación se van a emplear las técnicas incluidas en el primer grupo, esto es, aquellas basadas en características de color de los píxeles que forman la imagen, concretamente las basadas en umbral.
 
En los ejemplos que se mostrarán a continuación se van a emplear las técnicas incluidas en el primer grupo, esto es, aquellas basadas en características de color de los píxeles que forman la imagen, concretamente las basadas en umbral.
  
== Segmentación de color ==
+
=Segmentación de color=
  
La segmentación de la imagen se podría definir como la división de la imagen en regiones con características similares.A cada una de estas regiones que comparten
+
La primera etapa en el análisis de la imagen suele consistir por lo general en una separación de regiones o partes constituyentes de la misma que sean de interés para la aplicación que se desarrolla. A estas partes se les suele dar el nombre de ''segmentos'' (blobs). Actualmente existen muchos algoritmos de segmentación de imagen y siguen apareciendo más y más cada día, por lo que hacer una clasificación de los mismos puede ser bastante difícil.  
ciertas propiedades se las denomina regiones de interés u objetos, por lo que la segmentación no es más que la separación de objetos en una imagen.
 
  
 +
Sea cual sea el método de segmentación utilizado, todos ellos suelen comenzar realizando un ''filtrado'' previo de la imagen a procesar. El filtrado se usa para eliminar información no útil que puede afectar al procesamiento posterior. Habitualmente esta información no útil suele recibir el nombre de '''ruido'''. Eliminar el ruido de una imagen no es tarea fácil y la mayor parte de las veces no se consigue por completo sin que se pague un precio computacionalmente alto por ello. En los ejemplos que se mostrarán a continuación se hará uso del filtrado para mejorar la calidad de la segmentación.
 +
 +
De todos los métodos empleados en segmentación, el más simple es, sin lugar a dudas, el de '''umbralización''' o '''umbral'''. En este método, se utiliza el valor del píxel (valor del color) para realizar la separación de los objetos en la imagen. Aquellos píxeles con valores de color por encima y por debajo de unos márgenes serán considerados como parte del segmento a seleccionar y el resto serán descartados.
 +
 +
Como ejemplo de partida, tomaremos el siguiente código que se muestra a continuación. Este código ha sido tomado y adaptado de [http://www.lirtex.com/robotics/fast-object-tracking-robot-computer-vision/ aquí].
 +
 +
<geshi lang=C lines=0>#include <opencv/cvaux.h>
 +
#include <opencv/highgui.h>
 +
#include <opencv/cxcore.h>
 +
#include <stdio.h>
 +
 +
#include <stdio.h>
 +
#include <stdlib.h>
 +
#include <string.h>
 +
#include <assert.h>
 +
#include <math.h>
 +
#include <float.h>
 +
#include <limits.h>
 +
#include <time.h>
 +
#include <ctype.h>
 +
 +
int hmin = 150, smin = 84, vmin = 130, hmax = 358, smax = 256, vmax = 255;
 +
unsigned int img_width, img_height;
 +
 +
int main(int argc, char* argv[])
 +
{
 +
 +
    // Default capture size - 640x480
 +
    img_width = 640;
 +
    img_height = 480;
 +
    CvSize size = cvSize(img_width,img_height);
 +
 +
    // Open capture device. 0 is /dev/video0, 1 is /dev/video1, etc.
 +
    CvCapture* capture = cvCaptureFromCAM( 0 );
 +
    if( !capture )
 +
    {
 +
            fprintf( stderr, "ERROR: capture is NULL \n" );
 +
            getchar();
 +
            return -1;
 +
    }
 +
 +
    // Create a window in which the captured images will be presented
 +
    cvNamedWindow( "Camera", CV_WINDOW_AUTOSIZE );
 +
    //cvNamedWindow( "HSV", CV_WINDOW_AUTOSIZE );
 +
    //cvNamedWindow( "EdgeDetection", CV_WINDOW_AUTOSIZE );
 +
 +
    // Detect a red ball
 +
    //CvScalar hsv_min = cvScalar(150, 84, 130, 0);
 +
    //CvScalar hsv_max = cvScalar(358, 256, 255, 0);
 +
 +
    cvCreateTrackbar( "H_min", "Camera", &hmin, 360, 0 );
 +
    cvCreateTrackbar( "S_min", "Camera", &smin, 256, 0 );
 +
    cvCreateTrackbar( "V_min", "Camera", &vmin, 256, 0 );
 +
 +
    cvCreateTrackbar( "H_max", "Camera", &hmax, 360, 0 );
 +
    cvCreateTrackbar( "S_max", "Camera", &smax, 256, 0 );
 +
    cvCreateTrackbar( "V_max", "Camera", &vmax, 256, 0 );
 +
   
 +
    IplImage *  hsv_frame    = cvCreateImage(size, IPL_DEPTH_8U, 3);
 +
    IplImage*  thresholded  = cvCreateImage(size, IPL_DEPTH_8U, 1);
 +
 +
    while( 1 )
 +
    {
 +
        // Get one frame
 +
        IplImage* frame = cvQueryFrame( capture );
 +
        if( !frame )
 +
        {
 +
                fprintf( stderr, "ERROR: frame is null...\n" );
 +
                getchar();
 +
                break;
 +
        }
 +
 +
CvScalar hsv_min = cvScalar(hmin, smin, vmin, 0);
 +
CvScalar hsv_max = cvScalar(hmax, smax, vmax, 0);
 +
   
 +
        // Covert color space to HSV as it is much easier to filter colors in the HSV color-space.
 +
        cvCvtColor(frame, hsv_frame, CV_BGR2HSV);
 +
        // Filter out colors which are out of range.
 +
        cvInRangeS(hsv_frame, hsv_min, hsv_max, thresholded);
 +
 +
        // Memory for hough circles
 +
        CvMemStorage* storage = cvCreateMemStorage(0);
 +
        // hough detector works better with some smoothing of the image
 +
        cvSmooth( thresholded, thresholded, CV_GAUSSIAN, 9, 9 );
 +
        CvSeq* circles = cvHoughCircles(thresholded, storage, CV_HOUGH_GRADIENT, 2,
 +
                                        thresholded->height/4, 100, 50, 10, 400);
 +
 +
        for (int i = 0; i < circles->total; i++)
 +
        {
 +
            float* p = (float*)cvGetSeqElem( circles, i );
 +
            printf("Ball! x=%f y=%f r=%f\n\r",p[0],p[1],p[2] );
 +
            cvCircle( frame, cvPoint(cvRound(p[0]),cvRound(p[1])),
 +
                                    3, CV_RGB(0,255,0), -1, 8, 0 );
 +
            cvCircle( frame, cvPoint(cvRound(p[0]),cvRound(p[1])),
 +
                                    cvRound(p[2]), CV_RGB(255,0,0), 3, 8, 0 );
 +
        }
 +
 +
        cvShowImage( "Camera", frame ); // Original stream with detected ball overlay
 +
        //cvShowImage( "HSV", hsv_frame); // Original stream in the HSV color space
 +
        cvShowImage( "After Color Filtering", thresholded ); // The stream after color filtering
 +
 +
        cvReleaseMemStorage(&storage);
 +
 +
        // Do not release the frame!
 +
 +
        //If ESC key pressed, Key=0x10001B under OpenCV 0.9.7(linux version),
 +
        //remove higher bits using AND operator
 +
        if( (cvWaitKey(10) & 255) == 27 ) break;
 +
    }
 +
 +
    // Release the capture device housekeeping
 +
    cvReleaseCapture( &capture );
 +
    cvDestroyWindow( "mywindow" );
 +
    return 0;
 +
  }}</geshi>
  
 
Pendiente de redacción.
 
Pendiente de redacción.

Latest revision as of 09:07, 25 June 2014

Introducción

La segmentación de una imagen es un proceso que suele ser el segundo paso para analizar una imagen digital y tiene lugar normalmente después del pre-procesamiento de la imagen. Una secuencia típica de un sistema de tratamiento de imagen podría ser: Captura de la imagen → Pre-procesamiento → Segmentación → Extracción de características → Post-procesado.

Las técnicas de segmentación de imagen digital se suelen dividir en cuatro grandes grupos. El primer grupo lo conforman las técnicas de segmentación basadas en características como el nivel de gris, el valor del color del píxel o la textura. El segundo grupo incluye las técnicas basadas en la homogeneidad de la imagen, esto es, delimitación de áreas o regiones homogéneas. Las técnicas basadas en transiciones, como la detección de bordes, pertenecen al tercer grupo y en el cuarto grupo nos encontramos a las técnicas basadas en modelos, como las que utilizan la transformada de Hough.

En los ejemplos que se mostrarán a continuación se van a emplear las técnicas incluidas en el primer grupo, esto es, aquellas basadas en características de color de los píxeles que forman la imagen, concretamente las basadas en umbral.

Segmentación de color

La primera etapa en el análisis de la imagen suele consistir por lo general en una separación de regiones o partes constituyentes de la misma que sean de interés para la aplicación que se desarrolla. A estas partes se les suele dar el nombre de segmentos (blobs). Actualmente existen muchos algoritmos de segmentación de imagen y siguen apareciendo más y más cada día, por lo que hacer una clasificación de los mismos puede ser bastante difícil.

Sea cual sea el método de segmentación utilizado, todos ellos suelen comenzar realizando un filtrado previo de la imagen a procesar. El filtrado se usa para eliminar información no útil que puede afectar al procesamiento posterior. Habitualmente esta información no útil suele recibir el nombre de ruido. Eliminar el ruido de una imagen no es tarea fácil y la mayor parte de las veces no se consigue por completo sin que se pague un precio computacionalmente alto por ello. En los ejemplos que se mostrarán a continuación se hará uso del filtrado para mejorar la calidad de la segmentación.

De todos los métodos empleados en segmentación, el más simple es, sin lugar a dudas, el de umbralización o umbral. En este método, se utiliza el valor del píxel (valor del color) para realizar la separación de los objetos en la imagen. Aquellos píxeles con valores de color por encima y por debajo de unos márgenes serán considerados como parte del segmento a seleccionar y el resto serán descartados.

Como ejemplo de partida, tomaremos el siguiente código que se muestra a continuación. Este código ha sido tomado y adaptado de aquí.

<geshi lang=C lines=0>#include <opencv/cvaux.h>

  1. include <opencv/highgui.h>
  2. include <opencv/cxcore.h>
  3. include <stdio.h>
  1. include <stdio.h>
  2. include <stdlib.h>
  3. include <string.h>
  4. include <assert.h>
  5. include <math.h>
  6. include <float.h>
  7. include <limits.h>
  8. include <time.h>
  9. include <ctype.h>

int hmin = 150, smin = 84, vmin = 130, hmax = 358, smax = 256, vmax = 255; unsigned int img_width, img_height;

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

   // Default capture size - 640x480
   img_width = 640;
   img_height = 480;
   CvSize size = cvSize(img_width,img_height);

   // Open capture device. 0 is /dev/video0, 1 is /dev/video1, etc.
   CvCapture* capture = cvCaptureFromCAM( 0 );
   if( !capture )
   {
           fprintf( stderr, "ERROR: capture is NULL \n" );
           getchar();
           return -1;
   }

   // Create a window in which the captured images will be presented
   cvNamedWindow( "Camera", CV_WINDOW_AUTOSIZE );
   //cvNamedWindow( "HSV", CV_WINDOW_AUTOSIZE );
   //cvNamedWindow( "EdgeDetection", CV_WINDOW_AUTOSIZE );

   // Detect a red ball
   //CvScalar hsv_min = cvScalar(150, 84, 130, 0);
   //CvScalar hsv_max = cvScalar(358, 256, 255, 0);

   cvCreateTrackbar( "H_min", "Camera", &hmin, 360, 0 );
   cvCreateTrackbar( "S_min", "Camera", &smin, 256, 0 );
   cvCreateTrackbar( "V_min", "Camera", &vmin, 256, 0 );
   cvCreateTrackbar( "H_max", "Camera", &hmax, 360, 0 );
   cvCreateTrackbar( "S_max", "Camera", &smax, 256, 0 );
   cvCreateTrackbar( "V_max", "Camera", &vmax, 256, 0 );
   
   IplImage *  hsv_frame    = cvCreateImage(size, IPL_DEPTH_8U, 3);
   IplImage*  thresholded   = cvCreateImage(size, IPL_DEPTH_8U, 1);

   while( 1 )
   {
       // Get one frame
       IplImage* frame = cvQueryFrame( capture );
       if( !frame )
       {
               fprintf( stderr, "ERROR: frame is null...\n" );
               getchar();
               break;
       }

	CvScalar hsv_min = cvScalar(hmin, smin, vmin, 0);
	CvScalar hsv_max = cvScalar(hmax, smax, vmax, 0);
   
       // Covert color space to HSV as it is much easier to filter colors in the HSV color-space.
       cvCvtColor(frame, hsv_frame, CV_BGR2HSV);
       // Filter out colors which are out of range.
       cvInRangeS(hsv_frame, hsv_min, hsv_max, thresholded);

       // Memory for hough circles
       CvMemStorage* storage = cvCreateMemStorage(0);
       // hough detector works better with some smoothing of the image
       cvSmooth( thresholded, thresholded, CV_GAUSSIAN, 9, 9 );
       CvSeq* circles = cvHoughCircles(thresholded, storage, CV_HOUGH_GRADIENT, 2,
                                       thresholded->height/4, 100, 50, 10, 400);

       for (int i = 0; i < circles->total; i++)
       {
           float* p = (float*)cvGetSeqElem( circles, i );
           printf("Ball! x=%f y=%f r=%f\n\r",p[0],p[1],p[2] );
           cvCircle( frame, cvPoint(cvRound(p[0]),cvRound(p[1])),
                                   3, CV_RGB(0,255,0), -1, 8, 0 );
           cvCircle( frame, cvPoint(cvRound(p[0]),cvRound(p[1])),
                                   cvRound(p[2]), CV_RGB(255,0,0), 3, 8, 0 );
       }
       cvShowImage( "Camera", frame ); // Original stream with detected ball overlay
       //cvShowImage( "HSV", hsv_frame); // Original stream in the HSV color space
       cvShowImage( "After Color Filtering", thresholded ); // The stream after color filtering

       cvReleaseMemStorage(&storage);

       // Do not release the frame!

       //If ESC key pressed, Key=0x10001B under OpenCV 0.9.7(linux version),
       //remove higher bits using AND operator
       if( (cvWaitKey(10) & 255) == 27 ) break;
   }

    // Release the capture device housekeeping
    cvReleaseCapture( &capture );
    cvDestroyWindow( "mywindow" );
    return 0;
  }}</geshi>

Pendiente de redacción.