2012-10-02 8 views
6

He buscado en todas partes pero no parece haber un estándar (podría ver) de cómo se verificaría para ver si una imagen está en blanco. En C#Comprobación para ver si una imagen está en blanco en C#

Tengo una forma de hacerlo, pero me encantaría saber cuál es la forma correcta de verificar si una imagen está en blanco, para que todos puedan saberlo en el futuro.

No voy a copiar pegar un montón de código, si quieres, será un placer, pero primero quiero explicar cómo voy a verificar para ver si una imagen está en blanco.

Toma una imagen .jpg, obtenga el ancho de la misma. Por ejemplo 500 píxeles A continuación, a dividir esta en un 2 que le da 250

Luego de comprobar cuál es el color de cada píxel se encuentra en la ubicación de (250 ancho, y altura) (donde iterar pensaba que la altura del imagen

Lo que esto hace es verificar la línea media de píxeles de una imagen, verticalmente. Revisa todos los píxeles para ver si el color es cualquier cosa excepto blanco. He hecho esto para que no tengas para buscar ALL 500 * altura de píxeles y dado que casi siempre encontrará un color en el medio de la página.

Su funcionamiento ... un poco lento ... Debe haber un mejor manera de hacer esto? Puede cambiarlo para buscar 2/3/4 líneas verticalmente para aumentar su posibilidad de detectar una página que no está en blanco, pero eso llevará incluso más tiempo.

(Tenga en cuenta también, utilizando el tamaño de la imagen para comprobar si contiene algo no funciona en este caso, ya que una página con dos frases sobre y el tamaño de una página en blanco es demasiado cerca uno del otro)

Después de que se haya agregado la solución.

Recursos para ayudar con la implementación y la comprensión de la solución.

(Tenga en cuenta que en la primera página web, el Pizelformat indicado es en realidad PixelFormat) - Pequeño error lo sé, sólo mencionar, podría causa cierta confusión a algunos.

Después de implementar el método para acelerar la búsqueda de píxeles, la velocidad no aumentó tanto. Entonces, creo que estoy haciendo algo mal.

Tiempo anterior = 15.63 para 40 imágenes.

Nueva tiempo = 15,43 por 40 imágenes

vi con el gran artículo DocMax quoted, que el código "bloquea" en un conjunto de píxeles. (o así es como lo entendí) Entonces, lo que hice fue bloquear en la fila central de píxeles de cada página. ¿Ese sería el movimiento correcto para hacer?

private int testPixels(String sourceDir) 
    { 
     //iterate through images 
     string[] fileEntries = Directory.GetFiles(sourceDir).Where(x => x.Contains("JPG")).ToArray(); 

     var q = from string x in Directory.GetFiles(sourceDir) 
       where x.ToLower().EndsWith(".jpg") 
       select new FileInfo(x); 

     int holder = 1; 
     foreach (var z in q) 
     { 
      Bitmap mybm= Bitmap.FromFile(z.FullName) as Bitmap; 
      int blank = getPixelData2(mybm); 

      if (blank == 0) 
      { 
       holder = 0; 
       break; 
      } 
     } 
     return holder; 
    } 

Y entonces la clase

private unsafe int getPixelData2(Bitmap bm) 
     { 
      BitmapData bmd = bm.LockBits(new System.Drawing.Rectangle((bm.Width/2), 0, 1, bm.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, bm.PixelFormat); 

      int blue; 
      int green; 
      int red; 

      int width = bmd.Width/2; 
      for (int y = 0; y < bmd.Height; y++) 
      { 
       byte* row = (byte*)bmd.Scan0 + (y * bmd.Stride); 

       blue = row[width * 3]; 
       green = row[width * 2]; 
       red = row[width * 1]; 

       // Console.WriteLine("Blue= " + blue + " Green= " + green + " Red= " + red); 
       //Check to see if there is some form of color 
       if ((blue != 255) || (green != 255) || (red != 255)) 
       { 
        bm.Dispose(); 
        return 1; 
       } 
      } 
      bm.Dispose(); 
      return 0; 
     } 
+0

¿Ha cronometrado cuánto tiempo lleva? Si es así, ¿cuál fue el tiempo y cuál fue el alto de la imagen? – 3aw5TZetdf

+1

Debe estar haciendo algo mal en su implementación, porque su algoritmo me parece correcto. No debería tomarse un tiempo para escanear una columna de un mapa de bits. –

+0

Tiempo total para 32 imágenes = 00: 00: 12.9187389 Altura = 6552 Ancho = 4580 – Ruan

Respuesta

7

Si usted puede tolerar el riesgo de equivocarse, el enfoque parece estar bien; He hecho algo muy similar en mi caso, aunque siempre tuve una confirmación visual para tratar los errores.

Para el rendimiento, la pregunta clave de apertura es cómo se obtienen los píxeles para probar. Si está utilizando Bitmap.GetPixel, es probable que tenga problemas de rendimiento. (Busque "Bitmap.GetPixel slow" en Google para ver un montón de discusión.)

Mucho mejor rendimiento vendrá de obtener todos los píxeles a la vez y luego pasarlos por encima. Personalmente me gusta Bob Powell's LockBits discussion para mayor claridad e integridad. Con ese enfoque, verificar todos los píxeles puede ser razonable según sus necesidades de rendimiento.

+0

En realidad, eres muy acertada, estoy usando Bitmap.GetPixel. Gracias, enfermo. Revise esa solución y publique mis hallazgos aquí para que haya una solución completa y el estándar "me atrevo a decir" sobre cómo verificar una imagen. – Ruan

+0

Entonces implementé la solución. Lo único es que los tiempos son casi idénticos. Tiempo antiguo = 15.63 para 40 imágenes. Y el nuevo tiempo es = 15.43 para 40 imágenes. Explicaré como información adicional sobre mi pregunta anterior lo que hice. – Ruan

+0

Lo acelera con una fracción. Creo que es difícil ver el aumento con la cantidad de datos que tengo. Gracias – Ruan

2

Si está utilizando System.Drawing.Bitmap puede acelerar las cosas (sustancialmente), por:

  1. No usar GetPixel acceder a los píxeles, LockBits uso y UnLockBits para copiar el mapa de bits de imagen para memoria regular Vea los ejemplos en el MSDN documentation para el uso.
  2. No se llama a las propiedades Ancho, Alto o Tamaño en el bucle for. Llame al tamaño una vez, almacene los valores en una variable local y utilícelos en el ciclo.

Notas:

  1. Al utilizar System.Drawing.Bitmap su imagen puede estar en la memoria del dispositivo y acceder a él puede llevar mucho tiempo.
  2. No recuerdo si cargar una imagen en un mapa de bits ya la convierte a formato RGB ya que es más difícil trabajar con otros formatos, pero si ese no es el caso, puede crear un mapa de bits RGB del mismo tamaño que imagen original, obtenga su objeto Gráfico (Graphics.FromImage) y use DrawImage para dibujar la imagen original en el mapa de bits RGB.

Edit: Beat to the punch de DocMax.

En cualquier caso, para la velocidad también puede intentar utilizar bibliotecas alternativas como la excelente FreeImage que incluye envolturas C#.

0

escalar la imagen a 1x1 a continuación, comprobar un píxel

nuevo Bitmap (previousImage, nuevo Tamaño (1, 1));

+0

Esto es brillante, desafortunadamente no funciona en la mayoría de las imágenes con las que lo he probado (un conjunto de mosaicos de 64x56 con valores de color argb). El píxel individual es con frecuencia 0,0,0,0 incluso cuando la fuente contiene algunos datos de imagen. – PeteB

+0

Hice otra prueba usando 2x2 y comprobando los cuatro píxeles. Fue mejor, pero todavía se informó vacío cuando había una pequeña cantidad de contenido en el mosaico. – PeteB

Cuestiones relacionadas