2012-08-02 101 views
3

我正在嘗試製作掃描應用程序。該應用程序將掃描文檔並在圖片框中顯示圖像。我面對的問題是圖像(保存在掃描儀中或者說'真實'圖像的文檔圖像)在具有某種背景的另一圖像(該背景顏色也在變化)內顯示,其外觀像這個圖像。
enter image description here
我已經嘗試了很多東西,但沒有給我一個完美的結果我試着用forge.net。這是我嘗試過的代碼。如何自動裁剪圖像?

public static System.Drawing.Image AforgeAutoCrop(Bitmap selectedImage) 
    { 
     Bitmap autoCropImage = null; 
    try 
    { 

     autoCropImage = selectedImage; 
     // create grayscale filter (BT709) 
     Grayscale filter = new Grayscale(0.2125, 0.7154, 0.0721); 
     Bitmap grayImage = filter.Apply(autoCropImage); 
     // create instance of skew checker 
     DocumentSkewChecker skewChecker = new DocumentSkewChecker(); 
     // get documents skew angle 
     double angle = skewChecker.GetSkewAngle(grayImage); 
     // create rotation filter 
     RotateBilinear rotationFilter = new RotateBilinear(-angle); 
     rotationFilter.FillColor = Color.White; 
     // rotate image applying the filter 
     Bitmap rotatedImage = rotationFilter.Apply(grayImage); 
     new ContrastStretch().ApplyInPlace(grayImage); 
     new Threshold(100).ApplyInPlace(grayImage); 
     BlobCounter bc = new BlobCounter(); 
     bc.FilterBlobs = true; 
     // bc.MinWidth = 500; 
     //bc.MinHeight = 500; 
     bc.ProcessImage(grayImage); 
     Rectangle[] rects = bc.GetObjectsRectangles(); 
     MemoryStream writeName = new MemoryStream(); 
     if (rects.Length == 0) 
     { 
      System.Windows.Forms.MessageBox.Show("No rectangle found in image "); 
     } 
     else if (rects.Length == 1) 
     { 
      Bitmap cropped = new Crop(rects[0]).Apply(autoCropImage); 
      autoCropImage = cropped; 
      // pictureBox1.Image = cropped; 
     } 
     else if (rects.Length > 1) 
     { 
      // get largets rect 
      Console.WriteLine("Using largest rectangle found in image "); 
      var r2 = rects.OrderByDescending(r => r.Height * r.Width).ToList(); 
      //var r2 = rects.OrderByDescending(r => r.Height < 1500 && r.Width < 1000).ToList(); 
      Bitmap cropped = new Crop(r2[0]).Apply(autoCropImage); 

      Graphics gr = Graphics.FromImage(cropped); 
      gr.DrawRectangles(new Pen(Color.Red), rects); 
      autoCropImage = cropped; 
      // pictureBox1.Image = cropped; 

     } 
     else 
     { 
      Console.WriteLine("Huh? on image "); 
     } 
    } 
    catch(Exception ex) 
    { 
     MessageBox.Show(ex.Message); 
    } 

    return autoCropImage; 
    } 
+0

「沒有完美的結果」 是從beeing一個真正的問題很遠 - 投票關閉。順便說一句,我不會嘗試使用GDI +的東西,更好地利用像ImageMagick這樣的工具(http://www.imagemagick.org/script/index.php)或相應的.NET API(http:///imagemagick.codeplex.com/) – 2012-08-02 14:29:52

+0

@DocBrown它非常有用,謝謝。我嘗試過使用AForge而不是ImageMagick。再次感謝。 – Rakesh 2012-08-02 15:06:02

回答

2

我認爲你總是有一個形象具有鮮明的前景和背景,並且要像做背景的熱心作物。

在這種情況下,我會做類似的地區成長。從可以保證背景像素的位置開始。

獲得另一個圖像(或矩陣或其他),初始化爲零,並將相應的像素值設置爲1.如果任何相鄰像素在原始圖像中的閾值範圍內,遞歸移動它們並設置它們對應的像素值也爲0。

即:

map = 0's, size of image 
function f(x,y,image,map) 
    if map(x,y) is not 0 
     return 
    if pixel value at image(x,y)<T 
     map(x,y) = 1; 
     for all neighbors of x,y 
      function([neighbor coordinates],image,map) 
    else 
     map(x,y) = 2; 
end 

現在映射應該有所有背景像素爲1和forground爲2.您可以將其更改爲允許多個對象和閾值等等。您可能希望閾值是一個值變化而不是絕對值。

然後,只需找到最小值和最大值x和y,並將該範圍內的像素存儲到新圖像。

我希望這是你所需要的。

+0

你是對的。這是我所需要的。你有什麼想法在c#中做到這一點。 – Rakesh 2012-08-03 06:37:11

+0

查看[這裏](http://stackoverflow.com/questions/190385/how-to-manipulate-images-at-pixel-level-in-c)進行像素操作。 看[這裏](http://stackoverflow.com/questions/734930/how-to-crop-an-image-using-c)裁剪。 如果你對它們很熟悉,其餘的應該很簡單,轉換成C/C++/C#。 – Bill 2012-08-06 17:32:52

+0

好的,我會嘗試你的解決方案,並在這裏更新。希望它能解決我的問題..謝謝Bill .. :-) – Rakesh 2012-08-06 18:41:15

3

我改變了你的代碼,並且運行良好。 謝謝

public static System.Drawing.Image AforgeAutoCrop(Bitmap selectedImage) 
     { 
      Bitmap autoCropImage = null; 
      try 
      { 

       autoCropImage = selectedImage; 
       // create grayscale filter (BT709) 
       Grayscale filter = new Grayscale(0.2125, 0.7154, 0.0721); 
       Bitmap grayImage = filter.Apply(autoCropImage); 
       // create instance of skew checker 
       DocumentSkewChecker skewChecker = new DocumentSkewChecker(); 
       // get documents skew angle 
       double angle = skewChecker.GetSkewAngle(grayImage); 
       // create rotation filter 
       RotateBilinear rotationFilter = new RotateBilinear(-angle); 
       rotationFilter.FillColor = Color.White; 
       // rotate image applying the filter 
       Bitmap rotatedImage = rotationFilter.Apply(grayImage); 
       new ContrastStretch().ApplyInPlace(rotatedImage); 
       new Threshold(100).ApplyInPlace(rotatedImage); 
       BlobCounter bc = new BlobCounter(); 
       bc.FilterBlobs = true; 
       // bc.MinWidth = 500; 
       //bc.MinHeight = 500; 
       bc.ProcessImage(rotatedImage); 
       Rectangle[] rects = bc.GetObjectsRectangles(); 

       if (rects.Length == 0) 
       { 
        System.Windows.Forms.MessageBox.Show("No rectangle found in image "); 
       } 
       else if (rects.Length == 1) 
       { 
        autoCropImage = rotatedImage.Clone(rects[0], rotatedImage.PixelFormat); ; 
       } 
       else if (rects.Length > 1) 
       { 
        // get largets rect 
        Console.WriteLine("Using largest rectangle found in image "); 
        var r2 = rects.OrderByDescending(r => r.Height * r.Width).ToList(); 
        autoCropImage = rotatedImage.Clone(r2[1], rotatedImage.PixelFormat); 
       } 
       else 
       { 
        Console.WriteLine("Huh? on image "); 
       } 
      } 
      catch (Exception ex) 
      { 
       MessageBox.Show(ex.Message); 
      } 

      return autoCropImage; 
     } 
0

莫斯塔法香港的代碼爲我工作。我正在使用此功能預處理YouTube縮略圖(去除黑邊;這是一個常見問題),而且我確實需要對其代碼進行一些小修改:

1)擺脫了旋轉(不知道這是用於)

2)I降低從100閾值至25。

3)當克隆的最終圖像,我執行克隆關原autoCropImage而不是rotatedImage(再次,不知道旋轉是什麼)。

我認爲真正的祕訣就是降低門檻。這減少了代碼找到的矩形的數量,現在我正確地裁剪所有形式的縮略圖(頂部和底部爲黑色的寬屏以及左側和右側的黑色全屏)。

public static System.Drawing.Image AforgeAutoCrop(Bitmap selectedImage) 
    { 
     Bitmap autoCropImage = null; 
     try 
     { 

      autoCropImage = selectedImage; 
      // create grayscale filter (BT709) 
      Grayscale filter = new Grayscale(0.2125, 0.7154, 0.0721); 
      Bitmap grayImage = filter.Apply(autoCropImage); 
      // create instance of skew checker 
      DocumentSkewChecker skewChecker = new DocumentSkewChecker(); 
      // get documents skew angle 
      double angle = 0; // skewChecker.GetSkewAngle(grayImage); 
      // create rotation filter 
      RotateBilinear rotationFilter = new RotateBilinear(-angle); 
      rotationFilter.FillColor = Color.White; 
      // rotate image applying the filter 
      Bitmap rotatedImage = rotationFilter.Apply(grayImage); 
      new ContrastStretch().ApplyInPlace(rotatedImage); 
      new Threshold(25).ApplyInPlace(rotatedImage); 
      BlobCounter bc = new BlobCounter(); 
      bc.FilterBlobs = true; 
      // bc.MinWidth = 500; 
      //bc.MinHeight = 500; 
      bc.ProcessImage(rotatedImage); 
      Rectangle[] rects = bc.GetObjectsRectangles(); 

      if (rects.Length == 0) 
      { 
       // CAN'T CROP 
      } 
      else if (rects.Length == 1) 
      { 
       autoCropImage = autoCropImage.Clone(rects[0], autoCropImage.PixelFormat); ; 
      } 
      else if (rects.Length > 1) 
      { 
       // get largets rect 
       Console.WriteLine("Using largest rectangle found in image "); 
       var r2 = rects.OrderByDescending(r => r.Height * r.Width).ToList(); 
       autoCropImage = autoCropImage.Clone(r2[0], autoCropImage.PixelFormat); 
      } 
      else 
      { 
       Console.WriteLine("Huh? on image "); 
      } 
     } 
     catch (Exception ex) 
     { 
      //MessageBox.Show(ex.Message); 
      //CAN'T CROP 
     } 

     return autoCropImage; 
    } 

https://stackoverflow.com/search?q=youtube+thumbnail+crop