2012-10-02 19 views
6

Ho cercato ovunque ma non sembra essere uno standard (ho potuto vedere) di come si farebbe per verificare se un'immagine è vuota. In C#Controllo per vedere se un'immagine è vuota in C#

Ho un modo per farlo, ma mi piacerebbe sapere qual è il modo corretto di controllare per vedere se un'immagine è vuota, così tutti potrebbero anche sapere in futuro.

Non ho intenzione di copiare incolla un po 'di codice, se vuoi, sarà per me un piacere, ma prima voglio solo spiegare come vado a controllare per vedere se un'immagine è vuota.

Prendi un'immagine .jpg, ottieni la larghezza. Ad esempio 500 pixel Poi si dividono che entro 2 dando 250

Poi si controlla ciò che il colore di ogni pixel è nella posizione di (250 di larghezza, ed io altezza) (dove eseguire iterazioni pensato l'altezza del

Ciò che allora fa è solo controllare la linea mediana dei pixel di un'immagine, verticalmente, ma controlla tutti i pixel per vedere se il colore è qualcosa Eccetto il bianco. L'ho fatto così non avrai per cercare TUTTI i 500 * altezza dei pixel e quasi sempre troverai un colore nel mezzo della pagina

Il suo funzionamento ... un po 'lento ... Ci deve essere un modo migliore per farlo? Puoi cambiarlo per cercare le linee 2/3/4 in verticale per aumentare la possibilità di individuare una pagina che non è vuota, ma che richiederà ancora più tempo.

(Si noti inoltre, utilizzando la dimensione dell'immagine per verificare se contiene qualcosa non funziona in questo caso, dal momento che una pagina con due frasi su e le dimensioni di una pagina bianca è troppo vicini l'uno all'altro)

Dopo aver aggiunto la soluzione.

Risorse utili per l'implementazione e la comprensione della soluzione.

(Si noti che il primo sito web, il Pizelformat dichiarato è in realtà PixelFormat) - piccolo errore lo so, basta ricordare, potrebbe causare una certa confusione ad alcuni.

Dopo aver implementato il metodo per accelerare la ricerca dei pixel, la velocità non è aumentata di molto. Quindi penso che sto facendo qualcosa di sbagliato.

Vecchio orario = 15,63 per 40 immagini.

nuovo tempo = 15.43 per 40 immagini

ho visto con il grande articolo DocMax quoted, che il codice "blocca" in un insieme di pixel. (o come ho capito) Quindi quello che ho fatto è bloccare la fila centrale di pixel di ogni pagina. Sarebbe la mossa giusta da fare?

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; 
    } 

E allora la classe

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

Hai tempo per quanto tempo ci vuole? Se sì, qual era il tempo e qual era l'altezza dell'immagine? – 3aw5TZetdf

+1

Devi fare qualcosa di sbagliato nella tua implementazione, perché il tuo algoritmo mi sembra corretto. Non dovrebbe impiegare tempo per scansionare una colonna di una bitmap. –

+0

Tempo totale per 32 immagini = 00: 00: 12.9187389 Altezza = 6552 Larghezza = 4580 – Ruan

risposta

7

Se si può tollerare la possibilità di sbagliare, l'approccio sembra bene; Ho fatto qualcosa di molto simile nel mio caso, anche se ho sempre avuto una conferma visiva per gestire gli errori.

Per le prestazioni, la domanda chiave aperta è come si stanno verificando i pixel. Se si utilizza Bitmap.GetPixel, si riscontrano problemi di prestazioni. (Cerca "Bitmap.GetPixel slow" in Google per vedere un sacco di discussioni.)

Le prestazioni migliori derivano dall'ottenere tutti i pixel in una sola volta e quindi da un loop su di essi. Personalmente mi piace Bob Powell's LockBits discussion per chiarezza e completezza. Con questo approccio, la verifica di tutti i pixel potrebbe essere ragionevole in base alle esigenze di prestazioni.

+0

Sei davvero azzeccato, sto usando Bitmap.GetPixel. Grazie, malato Controllare la soluzione e postare i risultati qui, quindi c'è una soluzione completa e "oserei dire" standard su come controllare un'immagine. – Ruan

+0

Quindi ho implementato la soluzione. L'unica cosa è che i tempi sono quasi identici all'ora precedente = 15,63 per 40 immagini. E il nuovo tempo è = 15,43 per 40 immagini. Ill spiegare come informazioni aggiuntive sulla mia domanda sopra quello che ho fatto. – Ruan

+0

Lo accelera con una frazione. Penso che sia difficile vedere l'aumento con la quantità di dati che ho. Grazie mille – Ruan

2

se si sta utilizzando System.Drawing.Bitmap è possibile accelerare le cose (sostanzialmente), da:

  1. Non usando GetPixel per accedere ai pixel, LockBits uso e UnLockBits per copiare l'immagine da bitmap memoria regolare. Vedere gli esempi su MSDN documentation per l'uso.
  2. Non chiamare le proprietà Larghezza, Altezza o Dimensioni nel ciclo for. Chiama una volta, archivia i valori in una variabile locale e utilizza quelli nel ciclo.

Note:

  1. Quando si utilizza System.Drawing.Bitmap vostra immagine può essere nella memoria del dispositivo e l'accesso potrebbe richiedere molto tempo.
  2. Non ricordo se il caricamento di un'immagine in una bitmap lo converte già in formato RGB poiché altri formati sono più difficili da utilizzare, ma in caso contrario è possibile creare una bitmap RGB della stessa dimensione della immagine originale, ottieni l'oggetto grafico (Graphics.FromImage) e usa DrawImage per disegnare l'immagine originale nella bitmap RGB.

Modifica: Beat to the punch di DocMax.

In ogni caso per la velocità è anche possibile provare a utilizzare librerie alternative come l'eccellente FreeImage che include wrapper C#.

0

Scala l'immagine di 1x1 quindi controllare un pixel

nuovo bitmap (previousImage, nuovo formato (1, 1));

+0

Questo è brillante, sfortunatamente non funziona sulla maggior parte delle immagini con cui ho provato (un set di piastrelle 64x56 con valori di colore argb). Il singolo pixel è spesso 0,0,0,0 anche quando la fonte contiene alcuni dati di immagine. – PeteB

+0

Ho eseguito un ulteriore test utilizzando 2x2 e controllando tutti e quattro i pixel. Era meglio, ma veniva comunque segnalato vuoto quando c'era una piccola quantità di contenuto nella tessera. – PeteB

Problemi correlati