2012-08-02 104 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