2012-09-25 65 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)乘以整個矩形(取決於你想要的單位)的區域。

評論:我不認爲這看起來像一個多邊形。這就是爲什麼我在我的腦海裏充滿了簡單繪圖軟件的「充滿油漆」功能。