2012-09-25 42 views
5

的给定的X名单,y坐标和已知宽度&高度怎能NUMBER的封闭区域的(在C#)来确定的?查找区域给定一组点

例如:

enter image description here

在该图像5 封闭区域被定义:

  1. 工作面(1)
  2. 眼睛(2)
  3. 鼻(1)的脸的
  4. 权(1)

x的列表,Y点将在黑色的任何像素,包括嘴。

+1

[与式开始查找多边形的面积](http://en.wikipedia.org/wiki/Polygon#Area_and_centroid) – Servy

+2

想到你的封闭区域为多边形的象素然后见http://stackoverflow.com/questions/2034540/calculating-area-of-irregular-polygon-in-c-sharp关于如何获得多边形区域 – m0s

+0

对不起,有些东西在翻译中丢失了......我需要弄清楚区域数量(5)而不是它们的面积。 – user873432

回答

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

UPDATE

上面的代码工作仅此四重联封闭区域。以下代码适用于八连式封闭区域。

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

下面的图片清楚地说明了我的意思。也可以添加更多的远点来抵消阵列,以便能够填补空白区域。

Connectedness

+0

很酷。这使我的模糊描述明确。我喜欢。 –

+0

不错,对于我正在研究的另一个领域很有用,但是想知道如何确定封闭区域的数量? – user873432

+1

您可以使用我的算法为每个非背景颜色(在您的示例图像上为黑色)像素区域检测。每次填充后,这些区域将不会被检测到(因为它们将被填满),您将不得不增加发现区域的数量。当然,这种方法适用于链接地区。因此,对于另一个案例使用OpenCV,@Jason Hermann如何回答。 –

1

样本图像中有几个特殊情况。你将不得不决定如何处理它们。

一般来说,你将通过光栅图像转换成一系列的多边形开始。然后,它是计算面积相当小事(见Servy的评论)

的特殊情况下,会在脸上和嘴角边。两者都是开放的形状,没有关闭。你需要弄清楚如何关闭它们。

2

我使用OpenCV取得了巨大的成功。有一个叫Emgu CV

这里.NET库涵盖替代Emgu CV一个问题:.Net (dotNet) wrappers for OpenCV?

这个库包含了功能识别轮廓和寻找关于他们的属性。您可以搜索cvContourArea以查找更多信息。

如果你正在寻找一个快速的解决这个特定的问题,并希望而不是重用他人编写自己的代码,我没有一个算法,我可以给那个做到这一点。抱歉。

1

我认为这归结为计算每个区域(非黑色)像素的数量。如果选择一个不是黑色的像素,请将其添加到HashSet<>,查看所选像素左上方和右下方的像素是否也是非黑色。

每当您发现新的非黑色像素(通过上/下/左/右),将它们添加到您的设置。当你找到他们全部时,数一数。

您所在地区的区域count/(pixelWidthOfTotalDrawing * pixelHeightOfTotalDrawing)乘以整个矩形(取决于你想要的单位)的区域。

评论:我不认为这看起来像一个多边形。这就是为什么我在我的脑海里充满了简单绘图软件的“充满油漆”功能。