找到要裁剪的图像的矩形区域

Posted

技术标签:

【中文标题】找到要裁剪的图像的矩形区域【英文标题】:Find the rectangle area of image to Crop 【发布时间】:2014-07-06 08:01:15 【问题描述】:

我的图片尺寸为 (352 x 240)

我想裁剪白色区域(所选区域如下图)。

我使用此代码裁剪图像,

private static Image cropImage(Image img, Rectangle cropArea)

   Bitmap bmpImage = new Bitmap(img);
   Bitmap bmpCrop = bmpImage.Clone(cropArea,
   bmpImage.PixelFormat);
   return (Image)(bmpCrop);

但我找不到适合我需要的确切矩形区域! 如何找到Rectangle所选区域的值? 我只想裁剪这个区域!谢谢!

【问题讨论】:

我认为你需要使用像 Aforge.NET 这样的包——它为这个问题提供了功能——还有更多 感谢@Yossico,但我不想使用任何第三方工具。我只想知道我的第二张图片的选定区域的Rectangle 值:)。 【参考方案1】:

如果你想自己做,你当然可以。但是如何做到最好的细节很大程度上取决于你对源图像的了解程度。

以下是一些需要考虑的问题和决定:

你知道图片的尺寸吗 你知道图片的位置吗,它总是在右下角吗? 您知道切角的大小吗? 你知道颜色吗? 您宁愿减少在内部丢失一些像素,还是在外部或中间包含一些像素?

看看你的例子,你可以试试这个策略:

首先,您以一定距离水平遍历图像,例如以 10 或 20 个切片。 在每条线的横向上,您观察并收集像素改变颜色的所有点 然后您比较结果列表,看看中间是否有一些(!)同意 这为您提供了左右边界 它还为您提供了一个可以进行垂直扫描的区域 然后重复垂直扫描以获得顶部和底部坐标。 垂直扫描不必搜索矩形,它们可以从水平扫描结果的中间开始工作

要使此功能起作用,您必须对您期望的颜色变化有所了解:会涉及平滑吗?如果是这样,您需要比较GetPixel 颜色的结果。

此外,尺寸应该是大致已知的,否则您可能需要使用更精细的网格重复整个过程..

编辑:使用您评论中的信息可以做出一些假设 (*) 并使用这段代码来确定目标矩形。这些假设用于:

确定两个扫描线范围,在这些范围内可以假定扫描会击中目标的身体 用内部和外部颜色确定两个像素

我使用颜色距离函数和 4 个点列表,并在几次点击中取平均值。变量 blur 适用于图像的值 2-6。

List<Point> xPoints1 = new List<Point>();
List<Point> xPoints2 = new List<Point>();
List<Point> yPoints1 = new List<Point>();
List<Point> yPoints2 = new List<Point>();

Rectangle findRectangle()

    int xMax = pictureBox1.Image.Width; 
    int yMax = pictureBox1.Image.Height;

    // * we can asume that these lines hit the body
    int x0 = xMax * 3 / 4;
    int y0 = yMax * 3 / 4;

    using (Bitmap bmp = new Bitmap(pictureBox1.Image) )
    
        // we can assume that these are the out- and inside colors
        Color col0 = bmp.GetPixel(9, 9);
        Color col1 = bmp.GetPixel(x0, y0);

        int blur = 4;
        int diff = colordistance(col0, col1) / blur;

        bool outside = true;
        // a few horizontal scans..
        for (int y = y0 - 20; y < y0 + 20; y += 4)
        
          outside = true;
          for (int x = 0; x < xMax; x++)
          
            Color c = bmp.GetPixel(x, y);

            if ( outside && colordistance(c, col0) > diff)
                outside = !outside; xPoints1.Add(new Point(x, y)); 
            else if (!outside && colordistance(c, col1) > diff) 
                outside = !outside; xPoints2.Add(new Point(x, y)); 
            
                      

        // a few vertical scans..
        for (int x = x0 - 20; x < x0 + 20; x += 4)
        
           outside = true;
           for (int y = 0; y < yMax; y++)
           
              Color c = bmp.GetPixel(x, y);
              if (outside && colordistance(c, col0) > diff) 
                   outside = !outside; yPoints1.Add(new Point(x, y)); 
              else if (!outside && colordistance(c, col1) > diff) 
                   outside = !outside; yPoints2.Add(new Point(x, y)); 
           
        

        int left   = (int)xPoints1.Average(p => p.X);
        int right  = (int)xPoints2.Average(p => p.X);
        int top    = (int)yPoints1.Average(p => p.Y);
        int bottom = (int)yPoints2.Average(p => p.Y);
        // if the target sits at the bottom we didn't find the edge
        if (bottom == 0) bottom = yMax;

        return = new Rectangle(left, top, right - left, bottom - top);

    


int colordistance(Color c1, Color c2)

    return (int) Math.Sqrt((c1.R - c2.R) * (c1.R - c2.R) +
        (c1.G - c2.G) * (c1.G - c2.G) +
        (c1.B - c2.B) * (c1.B - c2.B));


注意: top 和 left 值在 Target 内部。底部(也可能是底部)撞到外面。因此,您应该将前者或后者减少 1 个像素,具体取决于您的需要..!

编辑 第一个版本将outside 变量设置在错误的位置。已更正。

【讨论】:

是的,图像的尺寸总是(352 x 240),我要裁剪的区域也在这个位置!

以上是关于找到要裁剪的图像的矩形区域的主要内容,如果未能解决你的问题,请参考以下文章

裁剪图像包含在 4 边(非矩形)多边形中

需要圆形裁剪功能而不是矩形

从 WPF 中的图像裁剪对角线区域

从 WPF 中的图像裁剪对角线区域

如何在 iOS 中裁剪非矩形区域

使用python从二进制图像中裁剪感兴趣区域