2012-10-02 48 views
6

我到處看看,但似乎沒有一個標準(我可以看到)如何去檢查以查看圖像是否爲空。在C#檢查圖像是否在C空白#

我有辦法做到這一點,但很想知道檢查圖像是否爲空的正確方法是什麼,所以大家也可以在將來知道。

我不會複製粘貼一堆代碼,如果你想要我,這將是我的榮幸,但我只是首先想解釋我如何去檢查以查看圖像是否爲空。

您拍攝一張.jpg圖像,獲取它的寬度。例如500個像素 然後,你除以2 給你250

然後,你檢查什麼每個像素的顏色是在的位置(250寬度,以及i高度)(其中,你迭代想到了的HIGHT圖像

這樣做只是檢查圖像像素的中間線,垂直。檢查所有像素檢查顏色是否是任何東西除了白色我已經這樣做了,所以你不會有搜索所有500 *像素的高度,因爲你幾乎總是會遇到頁面中間的顏色。

它的工作...有點慢...必須有一個更好的方法來做到這一點?您可以將其更改爲垂直搜索2/3/4行以增加發現非空白頁面的機會,但這需要更長的時間。

(另請注意,使用圖像的大小,以檢查其中是否包含一些不會在這種情況下工作,因爲有兩個句子和一個空白頁面的大小在頁面過於接近彼此)

解決方案添加完成後。

幫助實施和理解解決方案的資源。

(注意,第一個網站上,所陳述的Pizelformat實際上是像素格式) - 小的錯誤,我知道,只是提的是,可能對一些人造成一些混淆。

在我實現了加速像素搜索的方法後,速度沒有那麼大。所以我會認爲我做錯了什麼。

40個圖像的舊時間= 15.63。

新時間= 15.43的40張圖片

我與偉大的文章DocMax quoted看到,在一組像素的代碼「鎖定」。 (或多數民衆贊成我是如何理解它) 所以我所做的是鎖定在每個頁面的像素的中間行。這是正確的舉動嗎?

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

然後是類

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

你計時了多長時間?如果是這樣,什麼時候,圖像的高度是多少? – 3aw5TZetdf

+1

你的執行過程中你必須做錯某些事情,因爲你的算法對我來說聽起來很合理。應該不花時間掃描一列位圖。 –

+0

32個圖像的總時間= 00:00:12.9187389 高度= 6552 寬度= 4580 – Ruan

回答

7

如果你能容忍犯錯的機會,這種方法似乎罰款;在我的情況下,我做了一些非常類似的事情,儘管我總是通過視覺確認來處理錯誤。

對於性能而言,關鍵的問題是如何獲取要測試的像素。如果您使用的是Bitmap.GetPixel,則必然會出現性能問題。 (在Google中搜索「Bitmap.GetPixel slow」以查看大量討論。)

遠遠更好的性能來自於一次獲取所有像素,然後循環遍歷它們。爲了清晰和完整,我個人喜歡Bob Powell's LockBits discussion。採用這種方法,根據您的性能需求,檢查所有像素可能是合理的。

+0

你實際上是點,我使用Bitmap.GetPixel。 謝謝,生病請檢查解決方案,並在此發佈我的發現,以便有一個完整的解決方案和「敢說我」如何檢查圖像的標準。 – Ruan

+0

所以我實現瞭解決方案。唯一的一點是,時間幾乎相同舊時間= 40.6圖像的15.63。 40個圖像的新時間= 15.43。我解釋爲我的問題上面的額外信息,我做了什麼。 – Ruan

+0

它加速了一小部分。我認爲很難看到數據量的增加。 謝謝 – Ruan

2

如果您使用System.Drawing.Bitmap可以加快東西(基本上)由:

  1. 不使用GetPixel訪問像素,使用LockBits和UnlockBits的位圖圖像複製到定期記憶。有關使用情況,請參閱MSDN documentation上的示例。
  2. 不調用for循環中的Width,Height或Size屬性。調用大小一次,將這些值存儲在局部變量中並將其用於循環中。

注:

  1. 當使用System.Drawing.Bitmap您的圖像可以是在裝置存儲器和訪問它可能是耗時的。
  2. 我不記得是否將圖像加載到位圖中已將其轉換爲RGB格式,因爲其他格式更難以處理,但如果不是這種情況,您可以創建與您的圖像大小相同的RGB位圖原始圖像,得到它的Graphic對象(Graphics.FromImage)並使用DrawImage在RGB位圖中繪製原始圖像。

編輯:由DocMax擊敗一拳。

在任何情況下,您都可以嘗試使用替代庫,例如包含C#包裝器的優秀FreeImage

0

縮放圖像以1x1的再檢查一個像素

新位圖(previousImage,新尺寸(1,1));

+0

這太棒了,不幸的是它不適用於我試過的大多數圖像(一組具有argb顏色值的64x56拼貼)。即使源包含一些圖像數據,單個像素也經常是0,0,0,0。 – PeteB

+0

我使用2x2進行了進一步測試,並檢查了所有四個像素。這是更好的,但仍然報告瓦片中有少量的內容時是空的。 – PeteB