2010-05-16 12 views
6

Estoy intentando implementar la detección de rostros en C#. Actualmente tengo un contorno negro + blanco de una foto con una cara dentro (Here). Sin embargo, ahora trato de eliminar el ruido y luego dilatar la imagen para mejorar la fiabilidad cuando implemente la detección.Erosión de imagen para la detección de rostros en C#

El método que tengo hasta ahora es aquí:

  using System; 
using System.Collections.Generic 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using System.Drawing.Imaging; 

namespace ImageErosion 
{ 
    public partial class Form1 : Form 
    { 
     public int CompareEmptyColor { get; set; } 

     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void btErodeImage_Click(object sender, EventArgs e) 
     { 
      Image inputImage = pbInputImage.Image; 

      Image result = Process(inputImage); 

      pbInputImage.Image = result; 
     } 

     unsafe public Image Process(Image input) 
     { 
      Bitmap bmp = (Bitmap)input; 
      Bitmap bmpSrc = (Bitmap)input; 

      BitmapData bmData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), 
           ImageLockMode.ReadWrite, 
           PixelFormat.Format1bppIndexed); 

      int stride = bmData.Stride; 
      int stride2 = bmData.Stride * 2; 
      IntPtr Scan0 = bmData.Scan0; 

      byte* p = (byte*)(void*)Scan0; 

      int nOffset = stride - bmp.Width * 3; 
      int nWidth = bmp.Width - 2; 
      int nHeight = bmp.Height - 2; 

      var w = bmp.Width; 
      var h = bmp.Height; 

      var rp = p; 
      var empty = CompareEmptyColor; 
      byte c, cm; 
      int i = 0; 

      // Erode every pixel 
      for (int y = 0; y < h; y++) 
      { 
       for (int x = 0; x < w; x += 3, i++) 
       { 
        // Middle pixel 
        cm = p[y * stride + x]; 
        if (cm == empty) { continue; } 

        #region FirstRow 
        // Row 0 
        // Left pixel 
        if (x - 3 > 0 && y - 2 > 0) 
        { 
         c = p[(y - 2) * stride + (x - 3)]; 
         if (c == empty) { continue; } 
        } 
        // Middle left pixel 
        if (x - 2 > 0 && y - 2 > 0) 
        { 
         c = p[(y - 2) * stride + (x - 2)]; 
         if (c == empty) { continue; } 
        } 
        if (x - 1 > 0 && y - 2 > 0) 
        { 
         c = p[(y - 2) * stride + (x - 1)]; 
         if (c == empty) { continue; } 
        } 
        if (y - 2 > 0) 
        { 
         c = p[(y - 2) * stride + x]; 
         if (c == empty) { continue; } 
        } 
        if (x + 1 < w && y - 2 > 0) 
        { 
         c = p[(y - 2) * stride + (x + 1)]; 
         if (c == empty) { continue; } 
        } 
        if (x + 2 < w && y - 2 > 0) 
        { 
         c = p[(y - 2) * stride + (x + 2)]; 
         if (c == empty) { continue; } 
        } 
        if (x + 3 < w && y - 2 > 0) 
        { 
         c = p[(y - 2) * stride + (x + 3)]; 
         if (c == empty) { continue; } 
        } 
        #endregion 

        #region SecondRow 
        // Row 1 
        // Left pixel 
        if (x - 3 > 0 && y - 1 > 0) 
        { 
         c = p[(y - 1) * stride + (x - 3)]; 
         if (c == empty) { continue; } 
        } 
        if (x - 2 > 0 && y - 1 > 0) 
        { 
         c = p[(y - 1) * stride + (x - 2)]; 
         if (c == empty) { continue; } 
        } 
        if (x - 1 > 0 && y - 1 > 0) 
        { 
         c = p[(y - 1) * stride + (x - 1)]; 
         if (c == empty) { continue; } 
        } 
        if (y - 1 > 0) 
        { 
         c = p[(y - 1) * stride + x]; 
         if (c == empty) { continue; } 
        } 
        if (x + 1 < w && y - 1 > 0) 
        { 
         c = p[(y - 1) * stride + (x + 1)]; 
         if (c == empty) { continue; } 
        } 
        if (x + 2 < w && y - 1 > 0) 
        { 
         c = p[(y - 1) * stride + (x + 2)]; 
         if (c == empty) { continue; } 
        } 
        if (x + 3 < w && y - 1 > 0) 
        { 
         c = p[(y - 1) * stride + (x + 3)]; 
         if (c == empty) { continue; } 
        } 

        #endregion 

        #region ThirdRow 
        // Row 2 
        if (x - 3 > 0) 
        { 
         c = p[y * stride + (x - 3)]; 
         if (c == empty) { continue; } 
        } 
        if (x - 2 > 0) 
        { 
         c = p[y * stride + (x - 2)]; 
         if (c == empty) { continue; } 
        } 
        if (x - 1 > 0) 
        { 
         c = p[y * stride + (x - 1)]; 
         if (c == empty) { continue; } 
        } 
        if (x + 1 < w) 
        { 
         c = p[y * stride + (x + 1)]; 
         if (c == empty) { continue; } 
        } 
        if (x + 2 < w) 
        { 
         c = p[y * stride + (x + 2)]; 
         if (c == empty) { continue; } 
        } 
        if (x + 3 < w) 
        { 
         c = p[y * stride + (x + 3)]; 
         if (c == empty) { continue; } 
        } 
        #endregion 

        #region FourthRow 
        // Row 3 
        if (x - 3 > 0 && y + 1 < h) 
        { 
         c = p[(y + 1) * stride + (x - 3)]; 
         if (c == empty) { continue; } 
        } 
        if (x - 2 > 0 && y + 1 < h) 
        { 
         c = p[(y + 1) * stride + (x - 2)]; 
         if (c == empty) { continue; } 
        } 
        if (x - 1 > 0 && y + 1 < h) 
        { 
         c = p[(y + 1) * stride + (x - 1)]; 
         if (c == empty) { continue; } 
        } 
        if (y + 1 < h) 
        { 
         c = p[(y + 1) * stride + x]; 
         if (c == empty) { continue; } 
        } 
        if (x + 1 < w && y + 1 < h) 
        { 
         c = p[(y + 1) * stride + (x + 1)]; 
         if (c == empty) { continue; } 
        } 
        if (x + 2 < w && y + 1 < h) 
        { 
         c = p[(y + 1) * stride + (x + 2)]; 
         if (c == empty) { continue; } 
        } 
        if (x + 3 < w && y + 1 < h) 
        { 
         c = p[(y + 1) * stride + (x + 3)]; 
         if (c == empty) { continue; } 
        } 
        #endregion 

        #region FifthRow 
        // Row 4 
        if (x - 3 > 0 && y + 2 < h) 
        { 
         c = p[(y + 2) * stride + (x - 3)]; 
         if (c == empty) { continue; } 
        } 
        if (x - 2 > 0 && y + 2 < h) 
        { 
         c = p[(y + 2) * stride + (x - 2)]; 
         if (c == empty) { continue; } 
        } 
        if (x - 1 > 0 && y + 2 < h) 
        { 
         c = p[(y + 2) * stride + (x - 1)]; 
         if (c == empty) { continue; } 
        } 
        if (y + 2 < h) 
        { 
         c = p[(y + 2) * stride + x]; 
         if (c == empty) { continue; } 
        } 
        if (x + 1 < w && y + 2 < h) 
        { 
         c = p[(y + 2) * stride + (x + 1)]; 
         if (c == empty) { continue; } 
        } 
        if (x + 2 < w && y + 2 < h) 
        { 
         c = p[(y + 2) * stride + (x + 2)]; 
         if (c == empty) { continue; } 
        } 
        if (x + 3 < w && y + 2 < h) 
        { 
         c = p[(y + 2) * stride + (x + 3)]; 
         if (c == empty) { continue; } 
        } 
        #endregion 

        // If all neighboring pixels are processed 
        // it's clear that the current pixel is not a boundary pixel. 
        rp[i] = cm; 
       } 
      } 

      bmpSrc.UnlockBits(bmData); 
      return bmpSrc; 
     } 
    } 
} 

Según tengo entendido, con el fin de erosionar la imagen (y eliminar el ruido), tenemos que comprobar cada píxel para ver si se trata de píxeles circundantes son negras, y si es así, entonces es un píxel de borde y no es necesario que lo conserve, lo cual creo que mi código sí lo hace, por lo tanto, no entiendo por qué no funciona.

Cualquier ayuda o sugerencias serán bienvenidos

Gracias, Chris

Respuesta

2

Un par de espantajos que saltan. El formato de imagen es 24bpp pero está leyendo bytes. Eso podría funcionar si se trata de una imagen negra + blanca pura, pero el pixel izquierdo estaría en x - 3. La indexación x por 3 también sería acertada.

Indexar la fila es incorrecta, se multiplica por w, se debe multiplicar por zancada.

+0

Muchas gracias por la respuesta Hans! He actualizado mi método para incluir las soluciones sugeridas, pero fue en vano :(Al ejecutar el método en la imagen no hay cambios. ¿Me he perdido algo? ¡Gracias de nuevo! Chris –

+0

No lo sé. Si quieres ayuda depurando esto, actualiza el código en tu pregunta, publica un enlace a una imagen de muestra y explica cómo mides el éxito. –

+0

He creado una solución para el método y publiqué el código anterior. La solución contiene solo 1 formulario con una imagen (pbInputImage) y un botón (btErodeImage). He configurado la imagen de la imagen en este: http://img192.imageshack.us/img192/5821/blackscale.png Los resultados que esperaría serían bastante muchos de los puntos blancos al azar, y algunos de aquellos alrededor del grueso del blanco, para cambiar a negro, similar a esto: http://img232.imageshack.us/img232/2917/ erosionresult.png Espero que esto sea lo que esperabas? Muchas gracias de nuevo, Chris –

1

debería echar un vistazo a la biblioteca AForge.net (http://code.google.com/p/aforge/). Hay muchos filtros diferentes disponibles para las imágenes. Allí también puede encontrar ejemplos de cómo puede modificar imágenes directamente

0

¿Por qué no utiliza openCV? Dilate es una función directa allí y generalmente es más óptima para todas las imágenes ...

Cuestiones relacionadas