如何自动裁剪图像? [英] How to auto crop an image?

查看:423
本文介绍了如何自动裁剪图像?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图做一个扫描应用程序。该应用程序将扫描文档,将在图片框中显示图像。我现在面临的问题是图像(图像的文件其保存在扫描仪或说'真正的'形象)另一幅图像内的一些背景(这背景颜色也随之改变)显示的是它的外观像这样的形象。结果
结果
我已经试过很多东西,但没有给我一个完美的结果我用forge.net尝试过。这里是code我都试过了。

 公共静态System.Drawing.Image对象AforgeAutoCrop(位图​​selectedImage)
    {
        位图autoCropImage = NULL;
    尝试
    {        autoCropImage = selectedImage;
        //创建灰度滤镜(BT709)
        灰度滤镜=新的灰度(0.2125,0.7154,0.0721);
        位图grayImage = filter.Apply(autoCropImage);
        //创建歪斜检查实例
        DocumentSkewChecker skewChecker =新DocumentSkewChecker();
        //获取文件的倾斜角
        双角= skewChecker.GetSkewAngle(grayImage);
        //创建旋转滤波器
        RotateBilinear rotationFilter =新RotateBilinear(利用广角);
        rotationFilter.FillColor = Color.White;
        //旋转图像应用滤波器
        位图rotatedImage = rotationFilter.Apply(grayImage);
        新ContrastStretch()ApplyInPlace(grayImage)。
        新的阈值(100).ApplyInPlace(grayImage);
        BlobCounter BC =新BlobCounter();
        bc.FilterBlobs = TRUE;
        // bc.MinWidth = 500;
        //bc.MinHeight = 500;
        bc.ProcessImage(grayImage);
        矩形[] = rects bc.GetObjectsRectangles();
        MemoryStream的writeName =新的MemoryStream();
        如果(rects.Length == 0)
        {
            System.Windows.Forms.MessageBox.Show(无图像中找到矩形);
        }
        否则如果(rects.Length == 1)
        {
            位图裁剪=新作物(rects [0])应用(autoCropImage)。
            autoCropImage =裁剪;
           // pictureBox1.Image =裁剪;
        }
        否则如果(rects.Length→1)
        {
            //获取largets矩形
            Console.WriteLine(使用图像中发现最大的矩形);
            变种R2 = rects.OrderByDescending(R => r.Height * r.Width).ToList();
            //变种R2 = rects.OrderByDescending(R => r.Height&所述; 1500&放大器;&放大器; r.Width&下; 1000).ToList();
            位图裁剪=新作物(R2 [0])应用(autoCropImage)。            图形克= Graphics.FromImage(裁剪);
            gr.DrawRectangles(新笔(Color.Red),rects);
            autoCropImage =裁剪;
           // pictureBox1.Image =裁剪;        }
        其他
        {
            Console.WriteLine(咦上的形象?);
        }
    }
    赶上(异常前)
    {
        MessageBox.Show(ex.Message);
    }    返回autoCropImage;
    }


解决方案

我想你总是有一个形象具有鲜明的前景和背景,并且要像做背景的热心作物。

在这种情况下,我会做一些类似地区growning东西。开始在那里你可以保证一个背景像素点。

送另一图像(或矩阵或其他),初始化为零,以及相应的像素值设为1。如果任何相邻像素是原始图像中的一个阈值内时,递归移动到它们并设置其相应像素值0为好。

这就是:

 地图= 0,图像大小
函数f(X,Y,图像,地图)
    如果图(X,Y)不为0
        返回
    如果在图像的像素值(x,y)的&下;吨
        图(X,Y)= 1;
        为x的所有邻居,Y
           功能([坐标邻居],图像,图)
    其他
        图(X,Y)= 2;
 结束

现在图应该拥有所有背景像素为1,forground为2.您可以将其更改为允许多个对象和阈值等等。您可能需要的阈值是一个值的变化,而不是绝对值。

然后,只需找到最小和最大x和y,并在此范围内的像素存储到一个新的形象。

我希望这是沿着你所需要的行。

I am trying to make a scanning application. That application will scan the document and will display image in a picture box. The problem I am facing is image (Documents image which kept in the scanner or say ‘real ’image) is displaying inside another image with some background (That background color is also changing) its look like this image.

I have tried lot of things but nothing giving me a perfect result I tried it with a forge.net. Here is the code I have tried.

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

解决方案

I assume you always have an image with a distinct foreground and background, and you want to do something like a zealous crop of the background.

In this case I would do something similar to region growning. Start at a point where you can be guaranteed a background pixel.

Get another image (or matrix or whatever), initialized to zeros, and set the corresponding pixel value to 1. If any neighboring pixels are within a threshold value in the original image, move to them recursively and set their corresponding pixel values to 0 as well.

That is:

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

Now map should have all background pixels as 1 and forground as 2. You can change this to allow multiple objects and thresholds and so forth. You might want threshold to be a value change rather than an absolute value.

Then simply find the min and max x and y and store the pixels in that range to a new image.

I hope this was along the lines of what you need.

这篇关于如何自动裁剪图像?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆