• Domingo 17 de Noviembre de 2024, 17:26

Autor Tema:  Re: Erosion Binaria De Un Mapa De Bits  (Leído 1917 veces)

patitofeo

  • Miembro MUY activo
  • ***
  • Mensajes: 145
    • Ver Perfil
Re: Erosion Binaria De Un Mapa De Bits
« en: Lunes 7 de Junio de 2004, 20:05 »
0
:hola:

Estoy trabajando en un proyecto en el que debo hacer una localización desde una imagen de video.

Debo encontrar una pelotita naranja.

La imagen queda guardado en un array que toma la forma:

camframe imagen[n_filas][n_columnas][bytes_RGB];

se ve claro ¿no?

camframe es un typedef de unsigned char.

esta imagen la binarizo de forma que se coloreen los pixels naranjas.
El resultado queda en un array

camframe_bin imagen[n_filas][n_columnas].

camframe_bin vuelve a ser unsigned char.

Despues implemente la siguiente función para erosionar la imagen y eliminar ruido.

Código: Text
  1.  
  2. int erode(camframe_bin *img)
  3. {
  4.  
  5. int x,y;
  6.  
  7. for(y=1;y<61;y++)
  8.   {
  9.     for(x=1;x<81;x++)
  10.       {
  11.   if((*img)[y][x])
  12.     {
  13.       if(!((*img)[y+1][x]&&(*img)[y-1][x]&&(*img)[y][x+1]&&(*img)[y][x-1]))
  14.         (*img)[y][x]=MARK;;
  15.     }
  16.       }
  17.   }
  18. for(y=0;y<62;y++)
  19.   {
  20.     (*img)[y][0]=NO_ASERT;
  21.     (*img)[y][81]=NO_ASERT;
  22.   }
  23.  
  24. for(x=0;x<82;x++)
  25.   {
  26.     (*img)[0][x]=NO_ASERT;
  27.     (*img)[61][x]=NO_ASERT;
  28.   }
  29.  
  30. for(y=0;y<62;y++)
  31.   {
  32.     for(x=0;x<82;x++)
  33.       {
  34.   if((*img)[y][x]==MARK)
  35.     (*img)[y][x]=NO_ASERT;
  36.       }
  37.   }
  38. return(0);
  39. }
  40.  
  41.  

pero me parece muy tosca y lenta. ¿verdad?


La pregunta es si podrian aconsejarme algun algoritmo mas eficiente o si conocen algun sitio donde encontrarlo ("yo busque y busque y nada encontre").

muchas gracias.

Por si quieren hecharle un ojo mejor, les escribi un pequeño codigo donde se recoge una imagen de un .bmp y se introduce en un "camframe". despues se binariza, se erosiona y se pasa de nuevo a un .bmp. así podran verlo.

Gracias a cualquiera que tenga un ratito y le heche un ojo.

 :gracias:
El mensaje contiene 1 archivo adjunto. Debes ingresar o registrarte para poder verlo y descargarlo.

patitofeo

  • Miembro MUY activo
  • ***
  • Mensajes: 145
    • Ver Perfil
Re: Erosion Binaria De Un Mapa De Bits
« Respuesta #1 en: Lunes 7 de Junio de 2004, 20:12 »
0
Se me olvido decirles, que el tamaño de la imagen debe ser fija de 62x82 pixels (chiquitilla) y 24 bpp.

Si desean darle una ojeada al codigo, primero se les pide que introduzcan el path de la imagen origen.
Se binariza y se les pide un nombre para guardar el resultado.
Despues se erosiona y se vuelve a pedir un path para almacenar el resultado.



Les he hecho una pequeña imagen un poco artesanal para probar. Se la incluyo.


Gracias a todos de antemano.

 :hola:

PD: les envio la imagen comprimida porque no me deja de otro modo
El mensaje contiene 1 archivo adjunto. Debes ingresar o registrarte para poder verlo y descargarlo.

Ruben3d

  • Miembro HIPER activo
  • ****
  • Mensajes: 710
  • Nacionalidad: es
    • Ver Perfil
    • Web personal
Re: Erosion Binaria De Un Mapa De Bits
« Respuesta #2 en: Lunes 7 de Junio de 2004, 22:18 »
0
Hola.

Hace unos días también implementé una función que manipulaba una imagen (realiza un blur). Inicialmente la realicé refiriendome a cada pixel con un método getPixel y otro putPixel que básicamente hacían lo que tú: multiplicaciones de enteros para situarse en los diferentes píxeles de la imagen (con los índices entre corchetes []). De este manera me funcionaba a 35-37 fps a 240x320.

A continuación lo que hice fue mantener mis dos bucles anidados para moverme por la imagen pero, en vez de usar los contadores, iba sumando +1 a un puntero que inicialmente inicialicé con la dirección del primer píxel. De esta manera puedo recorrer la pantalla sin multiplicar en ningún punto. Para saber el valor del píxel de arriba o de abajo calculé cuánto debía sumar o restar al puntero para subir o bajar un píxel. De esta forma subí a 160-170 fps con una imagen del mismo tamaño. Para que lo veas más claro (porque no sé si me he explicado claro, que estoy espeso) te pongo el código del que hablo:

Antes de optimizar
Código: Text
  1.   int _x;
  2.   int x_;
  3.   int _y;
  4.   int y_;
  5.   int r;
  6.   int g;
  7.   int b;
  8.  
  9.   for (int y=1; y<io3dCore.getDisplay().getHeight()-2; y++)
  10.   {
  11.     int x;
  12.  
  13.     // caso de x=0
  14.     _x = g2d.getPixel(0, y);
  15.     x_ = g2d.getPixel(0+1, y);
  16.     _y = g2d.getPixel(0, y-1);
  17.     y_ = g2d.getPixel(0, y+1);
  18.     r = (CR5(_x)+CR5(x_)+CR5(_y)+CR5(y_))>>2;
  19.     g = (CG6(_x)+CG6(x_)+CG6(_y)+CG6(y_))>>2;
  20.     b = (CB5(_x)+CB5(x_)+CB5(_y)+CB5(y_))>>2;
  21.     g2d.putPixel(0,y, C565(r,g&0xFFFE,b));
  22.  
  23.     for (x=1; x<io3dCore.getDisplay().getWidth()-2; x++)
  24.     {
  25.       _x = g2d.getPixel(x-1, y);
  26.       x_ = g2d.getPixel(x+1, y);
  27.       _y = g2d.getPixel(x, y-1);
  28.       y_ = g2d.getPixel(x, y+1);
  29.       r = (CR5(_x)+CR5(x_)+CR5(_y)+CR5(y_))>>2;
  30.       g = (CG6(_x)+CG6(x_)+CG6(_y)+CG6(y_))>>2;
  31.       b = (CB5(_x)+CB5(x_)+CB5(_y)+CB5(y_))>>2;
  32.       g2d.putPixel(x,y, C565(r,g&0xFFFE,b));
  33.     }
  34.  
  35.     // caso de x=width-1
  36.     x = io3dCore.getDisplay().getWidth()-2;
  37.     _x = g2d.getPixel(x-1, y);
  38.     x_ = g2d.getPixel(x, y);
  39.     _y = g2d.getPixel(x, y-1);
  40.     y_ = g2d.getPixel(x, y+1);
  41.     r = (CR5(_x)+CR5(x_)+CR5(_y)+CR5(y_))>>2;
  42.     g = (CG6(_x)+CG6(x_)+CG6(_y)+CG6(y_))>>2;
  43.     b = (CB5(_x)+CB5(x_)+CB5(_y)+CB5(y_))>>2;
  44.     g2d.putPixel(x,y, C565(r,g&0xFFFE,b));
  45.   }
  46.  
  47.  

Tiene algunas diferencias (y algún bug) con respecto a la optimizada, ya que la generalicé para rectángulos de tamaño arbitrario. haz caso al bucle central, ya que trato por separado los casos de los extremos.

Ahora la versión optimizada. Es un poco más larga, pero si te fijas en todo el código sólo hay una multiplicación (y no está en ningún bucle). Es tan larga porque trato las esquinas y los bordes por separado, pero fijate en el bucle más central (el que tiene el comentario '//centro').

Versión optimizada
Código: Text
  1. void io3d::CGraphics2D::blurArea(int x1, int y1, int x2, int y2)
  2. {
  3.   if (x1>x2)
  4.   {
  5.     switchElems<int>(x1,x2);
  6.     switchElems<int>(y1,y2);
  7.   }
  8.   if (y1>y2)
  9.   {
  10.     switchElems<int>(y1,y2);
  11.   }
  12.  
  13.   int _x;  // Píxel de la izquierda
  14.   int x_;  // Píxel de la derecha
  15.   int _y;  // Píxel de arriba
  16.   int y_;  // Píxel de abajo
  17.   int r;
  18.   int g;
  19.   int b;
  20.  
  21.   int next_line = -(x2-x1+1)+m_nNormYPitch;
  22.  
  23.   int x;
  24.   WORD *pPixel = &m_pBackBuffer[x1+y1*m_nNormYPitch];
  25.  
  26.   // Esquina superior izq.
  27.   _x = *pPixel;
  28.   x_ = *(pPixel+1);
  29.   _y = *(pPixel+1+m_nNormYPitch); // En diagonal abajo-dcha.
  30.   y_ = *(pPixel+m_nNormYPitch);
  31.   r = (CR5(_x)+CR5(x_)+CR5(_y)+CR5(y_))>>2;
  32.   g = (CG6(_x)+CG6(x_)+CG6(_y)+CG6(y_))>>2;
  33.   b = (CB5(_x)+CB5(x_)+CB5(_y)+CB5(y_))>>2;
  34.   *(pPixel++) = C565(r,g&0xFFFE,b);
  35.  
  36.   // Centro primera fila
  37.   for (x=x1+1; x<x2; x++)
  38.   {
  39.     _x = *(pPixel-1);
  40.     x_ = *(pPixel+1);
  41.     _y = *pPixel;
  42.     y_ = *(pPixel+m_nNormYPitch);
  43.     r = (CR5(_x)+CR5(x_)+CR5(_y)+CR5(y_))>>2;
  44.     g = (CG6(_x)+CG6(x_)+CG6(_y)+CG6(y_))>>2;
  45.     b = (CB5(_x)+CB5(x_)+CB5(_y)+CB5(y_))>>2;
  46.     *(pPixel++) = C565(r,g&0xFFFE,b);
  47.   }
  48.  
  49.   // Esquina superior dcha.
  50.   _x = *(pPixel-1);
  51.   x_ = *pPixel;
  52.   _y = *(pPixel-m_nNormYPitch);
  53.   y_ = *(pPixel-1+m_nNormYPitch); // En diagonal abajo-izq.
  54.   r = (CR5(_x)+CR5(x_)+CR5(_y)+CR5(y_))>>2;
  55.   g = (CG6(_x)+CG6(x_)+CG6(_y)+CG6(y_))>>2;
  56.   b = (CB5(_x)+CB5(x_)+CB5(_y)+CB5(y_))>>2;
  57.   *(pPixel++) = C565(r,g&0xFFFE,b);
  58.  
  59.   // Parte central
  60.   for (int y=y1+1; y<y2; y++)
  61.   {
  62.     // Reajuste para la siguiente línea
  63.     pPixel += next_line;
  64.  
  65.     // caso de x=x1
  66.     _x = *pPixel;
  67.     x_ = *(pPixel+1);
  68.     _y = *(pPixel-m_nNormYPitch);
  69.     y_ = *(pPixel+m_nNormYPitch);
  70.     r = (CR5(_x)+CR5(x_)+CR5(_y)+CR5(y_))>>2;
  71.     g = (CG6(_x)+CG6(x_)+CG6(_y)+CG6(y_))>>2;
  72.     b = (CB5(_x)+CB5(x_)+CB5(_y)+CB5(y_))>>2;
  73.     (*pPixel++) = C565(r,g&0xFFFE,b);
  74.  
  75.     // Centro
  76.     for (int x=x1+1; x<x2; x++)
  77.     {
  78.       _x = *(pPixel-1);
  79.       x_ = *(pPixel+1);
  80.       _y = *(pPixel-m_nNormYPitch);
  81.       y_ = *(pPixel+m_nNormYPitch);
  82.       r = (CR5(_x)+CR5(x_)+CR5(_y)+CR5(y_))>>2;
  83.       g = (CG6(_x)+CG6(x_)+CG6(_y)+CG6(y_))>>2;
  84.       b = (CB5(_x)+CB5(x_)+CB5(_y)+CB5(y_))>>2;
  85.       *(pPixel++) = C565(r,g&0xFFFE,b);      // Optimizará cambiar 0xFFFE por 0xFE ?
  86.     }
  87.  
  88.     // caso de x=x2
  89.     _x = *(pPixel-1);
  90.     x_ = *pPixel;
  91.     _y = *(pPixel-m_nNormYPitch);
  92.     y_ = *(pPixel+m_nNormYPitch);
  93.     r = (CR5(_x)+CR5(x_)+CR5(_y)+CR5(y_))>>2;
  94.     g = (CG6(_x)+CG6(x_)+CG6(_y)+CG6(y_))>>2;
  95.     b = (CB5(_x)+CB5(x_)+CB5(_y)+CB5(y_))>>2;
  96.     *(pPixel++) = C565(r,g&0xFFFE,b);
  97.   }
  98.  
  99.   // Reajuste para la siguiente línea
  100.   pPixel += next_line;
  101.  
  102.   // Esquina inferior izq.
  103.   _x = *pPixel;
  104.   x_ = *(pPixel+1);
  105.   _y = *(pPixel-m_nNormYPitch);
  106.   y_ = *(pPixel+1-m_nNormYPitch);  // En diagonal arriba-dcha
  107.   r = (CR5(_x)+CR5(x_)+CR5(_y)+CR5(y_))>>2;
  108.   g = (CG6(_x)+CG6(x_)+CG6(_y)+CG6(y_))>>2;
  109.   b = (CB5(_x)+CB5(x_)+CB5(_y)+CB5(y_))>>2;
  110.   *(pPixel++) = C565(r,g&0xFFFE,b);
  111.  
  112.   // Centro última fila
  113.   for (x=x1+1; x<x2; x++)
  114.   {
  115.     _x = *(pPixel-1);
  116.     x_ = *(pPixel+1);
  117.     _y = *(pPixel-m_nNormYPitch);
  118.     y_ = *pPixel;
  119.     r = (CR5(_x)+CR5(x_)+CR5(_y)+CR5(y_))>>2;
  120.     g = (CG6(_x)+CG6(x_)+CG6(_y)+CG6(y_))>>2;
  121.     b = (CB5(_x)+CB5(x_)+CB5(_y)+CB5(y_))>>2;
  122.     *(pPixel++) = C565(r,g&0xFFFE,b);
  123.   }
  124.  
  125.   // Esquina inferior dcha.
  126.   _x = *(pPixel-1);
  127.   x_ = *pPixel;
  128.   _y = *(pPixel-m_nNormYPitch);
  129.   y_ = *(pPixel-1-m_nNormYPitch); // En diagonal arriba-izq.
  130.   r = (CR5(_x)+CR5(x_)+CR5(_y)+CR5(y_))>>2;
  131.   g = (CG6(_x)+CG6(x_)+CG6(_y)+CG6(y_))>>2;
  132.   b = (CB5(_x)+CB5(x_)+CB5(_y)+CB5(y_))>>2;
  133.   *(pPixel++) = C565(r,g&0xFFFE,b);
  134. }
  135.  

Espero que con todo esto veas lo que te estoy tratando de decir. Si tienes alguna duda pregunta por aqui.

Un saludo.

Ruben3d

patitofeo

  • Miembro MUY activo
  • ***
  • Mensajes: 145
    • Ver Perfil
Re: Erosion Binaria De Un Mapa De Bits
« Respuesta #3 en: Miércoles 9 de Junio de 2004, 17:23 »
0
:hola:

Muchas gracias, he cambiado la division por un desplazamiento y ahora consigo mucha mas velocidad.

Me ha venido genial tu código.  De todas formas seguiré trabajando en ello, seguro que aun se le puede sacar un poquitin más de partido. Ya os contaré. De todos modos cualquier sugerencia sigue siendo bien recibida.

Muchas gracias ruben3d