给出x,y坐标列表和已知宽度&高度如何确定封闭区域的 NUMBER (在C#中)?
例如:
在此图片中,定义了5个 已确认区域 :
x,y点的列表将是黑色的任何像素,包括嘴。
答案 0 :(得分:2)
我使用OpenCV取得了巨大成功。有一个名为Emgu CV
的.net库这是一个涵盖Emgu CV替代品的问题:.Net (dotNet) wrappers for OpenCV?
该库包含用于识别轮廓和查找关于它们的属性的函数。您可以搜索cvContourArea以查找更多信息。
如果您正在寻找这个特定问题的快速解决方案,并且想要编写自己的代码而不是重复使用其他代码,那么我没有可以提供的算法。遗憾。
答案 1 :(得分:2)
你可以使用这个简单的算法,基于洪水填充和辅助位图的想法:
// backColor is an INT representation of color at fillPoint in the beginning.
// result in pixels of enclosed shape.
private int GetFillSize(Bitmap b, Point fillPoint)
{
int count = 0;
Point p;
Stack pixels = new Stack();
var backColor = b.GetPixel(fillPoint.X, fillPoint.Y);
pixels.Push(fillPoint);
while (pixels.Count != 0)
{
count++;
p = (Point)pixels.Pop();
b.SetPixel(p.X, p.Y, backColor);
if (b.GetPixel(p.X - 1, p.Y).ToArgb() == backColor)
pixels.Push(new Point(p.X - 1, p.Y));
if (b.GetPixel(p.X, p.Y - 1).ToArgb() == backColor)
pixels.Push(new Point(p.X, p.Y - 1));
if (b.GetPixel(p.X + 1, p.Y).ToArgb() == backColor)
pixels.Push(new Point(p.X + 1, p.Y));
if (b.GetPixel(p.X, p.Y + 1).ToArgb() == backColor)
pixels.Push(new Point(p.X, p.Y + 1));
}
return count;
}
<强>更新强>
上面的代码仅适用于此四重连接的封闭区域。以下代码适用于八度链接的封闭区域。
// offset points initialization.
Point[] Offsets = new Point[]
{
new Point(-1, -1),
new Point(-0, -1),
new Point(+1, -1),
new Point(+1, -0),
new Point(+1, +1),
new Point(+0, +1),
new Point(-1, +1),
new Point(-1, +0),
};
...
private int Fill(Bitmap b, Point fillPoint)
{
int count = 0;
Point p;
Stack<Point> pixels = new Stack<Point>();
var backColor = b.GetPixel(fillPoint.X, fillPoint.Y).ToArgb();
pixels.Push(fillPoint);
while (pixels.Count != 0)
{
count++;
p = (Point)pixels.Pop();
b.SetPixel(p.X, p.Y, Color.FromArgb(backColor));
foreach (var offset in Offsets)
if (b.GetPixel(p.X + offset.X, p.Y + offset.Y).ToArgb() == backColor)
pixels.Push(new Point(p.X + offset.X, p.Y + offset.Y));
}
return count;
}
下面的图片清楚地表明了我的意思。另外,可以为偏移数组添加更多的远点,以便能够填充具有间隙的区域。
答案 2 :(得分:1)
示例图像中有几个特殊情况。你必须决定如何处理它们。
通常,您将首先将光栅图像转换为一系列多边形。然后计算面积是一个相当微不足道的事情(参见Servy的评论)
特殊情况可能是面部和嘴部的一侧。两者都是开放的形状,没有封闭。你需要弄清楚如何关闭它们。
答案 3 :(得分:1)
我认为这归结为计算每个区域中(非黑色)像素的数量。如果您选择一个非黑色像素,请将其添加到HashSet<>
,查看所选像素左侧和右侧上方,下方的像素是否也为非黑色。
每当您找到新非黑色像素(通过上/下/左/右)时,请将它们添加到您的设置中。当你找到它们时,请计算它们。
您所在地区的区域count / (pixelWidthOfTotalDrawing * pixelHeightOfTotalDrawing)
乘以整个矩形的面积(取决于您想要的单位)。
评论:我不认为这看起来像一个多边形。这就是为什么我会想到简单绘图软件的“填充油漆”功能。