2011-11-13 42 views
2

我正在看C#中的一個項目,看看圖像文件不確定的擴展,並注意到RGB值,如果它太黑暗將其移動到我的另一個文件夾看看以後獲取圖像的RGB值,並可能移動圖像文件在C#

所以這裏以方框圖的形式

加載多個圖片來自目錄>檢查每一個文件的RGB值>如果太暗>移動到不同的文件夾。如果不忽略(在原來的文件夾中保留)

我知道像從get目錄獲取文件但檢查整個圖片的RGB值,然後移動它或忽略它的基礎知識我很難過。

我有這樣的代碼:

private void button1_Click(object sender, EventArgs e) 
    { 
     CompareImages(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), 
      Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), "checked"), 127.0, new string[] {"*.jpg", "*.png"}); 
    } 

    private void CompareImages(string sourceFolder, string disposedImgFolder, double threshold, string[] extensions) 
    { 
     if (Directory.Exists(sourceFolder)) 
     { 
      DirectoryInfo dir = new DirectoryInfo(sourceFolder); 
      List<FileInfo> pictures = new List<FileInfo>(); 

      foreach (string ext in extensions) 
      { 
       FileInfo[] fi = dir.GetFiles(ext); 
       pictures.AddRange(fi); 
      } 


      Directory.CreateDirectory(disposedImgFolder); 

      int j = 0; 

      if (pictures.Count > 0) 
      { 
       for (int i = 0; i < pictures.Count; i++) 
       { 
        Image img = null; 
        Bitmap bmp = null; 

        try 
        { 

         img = Image.FromFile(pictures[i].FullName); 
         bmp = new Bitmap(img); 
         img.Dispose(); 

         double avg = GetAveragePixelValue(bmp); 

         bmp.Dispose(); 


         if (avg < threshold) 
         { 
          string dest = Path.Combine(disposedImgFolder, pictures[i].Name); 

          if (File.Exists(dest) == false) 
          { 
           pictures[i].MoveTo(dest); 
           j++; 
          } 
          else 
          { 

          } 
         } 
         else 
         { 

         } 
        } 
        catch 
        { 
         if (img != null) 
          img.Dispose(); 
         if (bmp != null) 
          bmp.Dispose(); 
        } 
       } 

       MessageBox.Show("Done, " + j.ToString() + " files moved."); 
      } 
     } 
    } 

    private unsafe double GetAveragePixelValue(Bitmap bmp) 
    { 
     BitmapData bmData = null; 

     try 
     { 
      bmData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); 

      int stride = bmData.Stride; 
      IntPtr scan0 = bmData.Scan0; 
      int w = bmData.Width; 
      int h = bmData.Height; 

      double sum = 0; 
      long pixels = bmp.Width * bmp.Height; 

      byte* p = (byte*)scan0.ToPointer(); 

      for (int y = 0; y < h; y++) 
      { 
       p = (byte*)scan0.ToPointer(); 
       p += y * stride; 

       for (int x = 0; x < w; x++) 
       { 

        double i = ((double)p[0] + p[1] + p[2])/3.0; 
        sum += i; 


        p += 4; 
       } 

      } 

      bmp.UnlockBits(bmData); 

      double result = sum/(double)pixels; 

      return result; 
     } 
     catch 
     { 
      try 
      { 
       bmp.UnlockBits(bmData); 
      } 
      catch 
      { 

      } 
     } 

     return -1; 
    } 

如何定義的threashold?

+0

您必須指定「太黑」的含義。您是否想將所有像素亮度值的平均值與閾值進行比較?這會忽略高對比度圖像中的黑暗區域... – foowtf

+0

太黑我的意思是圖像的RGB值爲黑色或類似的地方 – Matthew

+0

含義單一黑色像素會使圖像太暗?然後使用弗朗西斯的解決方案,如果性能對於您的應用來說不是太重要。 – foowtf

回答

0

我認爲你需要讀取一點RGB。每個像素都會有一個與之相關的紅色,綠色和藍色值,我想你正在尋找一種方法來獲得「平均」像素亮度的一些測量方法嗎?如果是這樣,你需要遍歷所有像素。這樣做時會計算每個像素的亮度。每個像素的「亮度」可以通過多種方式進行計算,您可以簡單地做(R + G + B)/ 3,或者您可以嘗試模仿人眼對R,G和B不均勻敏感。

然後,您將不得不決定如何使用像素的「亮度」。平均值,中位值,還有其他值?這取決於你想要做什麼..

更新:閱讀更多您的意見後,我仍然不確定你的意思是「明亮」或「黑暗」。您似乎還覺得您的術語有點混亂,您一直在討論整個圖像的RGB值,但圖像中的RGB值是指單個像素值。

我相信,這個頁面可以幫助你做你想要的東西: http://www.nbdtech.com/Blog/archive/2008/04/27/Calculating-the-Perceived-Brightness-of-a-Color.aspx

此外,一些免費的閱讀理解RGB:

http://en.wikipedia.org/wiki/Luma_(video

http://en.wikipedia.org/wiki/RGB_color_space

+0

是的,這是即時通訊嘗試做的事情,因爲光線在圖像中的位置並不總是相同的 – Matthew

+0

我會再次解釋,對不起我的大腦今天運作不錯, 我和我的父親正在做天文攝影, 我們打算在晚上拍照留下照相機,然後我希望這個程序能夠留意照片上的照片,以便刪除那些在望遠鏡前面有些雲已經消失的照片 ,並確保它只刪除那些雲,我認爲它會在「亮度」作爲唯一的方式告訴如果圖片是好的,否則我們必須通過它們並手動做到這一點。 – Matthew

+0

如果是這樣,我想你可以簡單地使用弗朗西斯所擁有的GetPixel循環(可能除以像素數)「添加upp」所有像素值,然後通過試驗和錯誤找到適合的閾值。也許你可以先將整個圖像轉換爲灰度。 http://www.switchonthecode.com/tutorials/csharp-tutorial-convert-a-color-image-to-grayscale http://www.bobpowell.net/lockingbits.htm – Niclas

0

如果你想要讀取圖像的每個像素,必須將其轉換爲位圖。然後你可以使用GetPixel方法。但是,這個過程非常緩慢,需要大量的CPU。如果你這樣做,你真的應該運行一些測試。

 using (var m = new MemoryStream()) 
     { 
      using (var img = Image.FromFile(args[0])) 
      { 
       img.Save(m, ImageFormat.Bmp); 
      } 

      m.Position = 0; 

      using (var bitmap = (Bitmap)Bitmap.FromStream(m)) 
      { 
       for (var x = 0; x < bitmap.Width; x++) 
       { 
        for (var y = 0; y < bitmap.Height; y++) 
        { 
         var color = bitmap.GetPixel(x, y); 

         // TODO: Do what ever you want 
        } 
       } 
      } 
     } 
+0

我看着做bitlock作爲我正在讀取GetPixel是起訴人餓了。但我似乎無法得到我的頭周圍所有整個程序是煩我 – Matthew

+0

閱讀http://msdn.microsoft.com/en-us/library/5ey6h79d.aspx – foowtf

+0

好吧,我找到了一個更好的方式做一次它讀取圖像,並在它的下方將它移動到「保持文件夾」,如果不是「檢查」文件夾 – Matthew