如何自动裁剪图像?

我正在尝试制作扫描应用程序。 该应用程序将扫描文档并将图像显示在图片框中。 我面临的问题是图像(保存在扫描仪中的文档图像或说“真实”图像)显示在具有一些背景的另一个图像内(背景颜色也在变化),它看起来像这个图像。
在此处输入图像描述
我尝试了很多东西,但没有给我一个完美的结果我用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; } 

我假设你总是有一个具有独特前景和背景的图像,你想要做一些像背景的热情作物。

在这种情况下,我会做类似于区域成长的事情。 从可以保证背景像素的点开始。

获取另一个图像(或矩阵或其他),初始化为零,并将相应的像素值设置为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) 

现在,map应该将所有背景像素设置为1,将forground设置为2.您可以将其更改为允许多个对象和阈值等等。 您可能希望阈值是值更改而不是绝对值。

然后只需找到min和max x和y,并将该范围内的像素存储到新图像中。

我希望这与你所需要的一致。

我将您的代码更改为此并且运行良好。 谢谢

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

您可以使用AForge.NET图像处理
边缘检测器: http : //www.aforgenet.com/framework/features/edge_detectors_filters.html

Mostafa HK的代码对我有用。 我正在使用此function预处理YouTube缩略图(剥离黑边;常见问题),我确实需要对他的代码进行一些小修改:

1)摆脱旋转(不知道那是什么)

2)我将阈值从100降低到25。

3)克隆最终图像时,我从原始autoCropImage执行克隆而不是rotateImage(再次,不确定旋转的用途)。

我认为真正的秘诀是降低门槛。 这减少了代码找到的矩形数量,现在我正在裁剪所有forms的缩略图(宽屏,顶部和底部为黑色,全屏,左侧和右侧为黑色)。

  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