找到要裁剪的图像的矩形区域
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),我要裁剪的区域也在这个位置!以上是关于找到要裁剪的图像的矩形区域的主要内容,如果未能解决你的问题,请参考以下文章