【问题标题】:Find the largest polygon as it is completed找到完成后最大的多边形
【发布时间】:2012-01-09 08:46:30
【问题描述】:

要求
我不知道如何描述,所以我举一个应该更容易解释的例子。

我有一个小的(最大 50x50 像素)1 位/像素位图(黑白)。
一次只添加一个像素。
使用黑色像素作为边缘找到存在的最大(按面积)多边形。

实际场景实际上与图形无关,并使用 2D 布尔数组,但逻辑与我想象的相同。

期望的行为

问题
我不确定如何在完成后获得最大的多边形。如果我能得到多边形,我可以做填充。在上图中,我突出显示了应选择的多边形。

【问题讨论】:

  • “按区域”是什么意思?函数应该返回什么?
  • 对不起,我不明白。你期待一个像素坐标数组,一个多边形角的列表,一个位图......
  • @Erno 数据的格式不重要,只要代表多边形即可。
  • 这并不像看起来那么容易。Google for:模式识别多边形给出了相当多的点击率。一种粗略的方法可能是(如果位图很小)填充多边形的外部(从左上角开始填充)并查看是否还有白色像素。如果是这样,就有一个多边形。

标签: c# polygon


【解决方案1】:

听起来您需要某种flood fill 算法,请参阅相关的 StackOverflow 问题:

Flood Fill Algorithms

您可以使用泛洪填充来执行分割,即将图像分割成由连接像素组成的离散“对象”。泛光填充还将为您提供每个对象内的像素数,让您找到最大的。另请参阅分段的维基百科页面,特别是区域增长方法:

http://en.wikipedia.org/wiki/Segmentation_(image_processing)#Region-growing_methods

【讨论】:

  • 问题不在于填充,而是知道多边形何时完成/关闭并获取我卡住的多边形。
  • 如果多边形没有闭合,洪水填充将从初始点“渗出”并填充整个图像。这应该很容易检测到!
  • 这很好,只是它们可能是任何坐标上的其他黑色像素,可能是也可能不是多边形的一部分。
【解决方案2】:

请注意,您需要确保多边形是“闭合的”。应该有个叫“snake”的算法对你有帮助,不过14年前就听说过这个,最好搜索一下……

【讨论】:

    【解决方案3】:

    事实证明它比我预期的要简单得多。我想我是想让事情变得过于复杂。由于尺寸小,而且它不会经常运行,因此速度并不是一个真正的问题。

    我无法确切了解我现在是如何做到的,但这是一般的想法。

    每个像素都存储为 SomePixelType 的一个实例。
    有一个 Stack 像素称为visitedPixels。 如果满足以下条件,则将像素视为可能的多边形边缘:

    • 它有 2 到 7 个(包括两者)黑色相邻像素。
    • 它不在visitedPixels 集合中。

    SomePixelType 有一个名为 GetNextPixel 的方法。

    当调用 GetNextPixel 时,它将搜索相邻像素(直接向上并顺时针方向)寻找可能的多边形边缘并将其返回。再次调用它将从最后一个匹配项继续搜索。一旦检查了所有相邻像素,它将返回 null。

    当一个像素被设置时,这个方法会被调用。

    public Stack<SomePixelType> GetPolygonEdges(SomePixelType justSetPixel)
    {
        visitedPixels.Clear();
    
        if(!justSetPixel.IsPossiblePolygon)
            return null; // Not a possible edge. No closed polygon could of been completed.
    
        visitedPixels.Push(justSetPixel);
    
        SomePixelType currentPixel = justSetPixel;
        while(visitedPixels.Count > 0)
        {
            currentPixel  = currentPixel.GetNextPixel();
            if(currentPixel == null) // No possible neighbouring polygon edges.
            {
                currentPixel = visitedPixels.Pop(); // Backtrack
                continue;
            }
            if(currentPixel == justSetPixel)
                return visitedPixels;
    
            visitedPixels.Push(currentPixel);
        }
        return null; // Not closed.
    }
    

    从这里开始填写起来相当容易。因为问题是关于找到多边形,所以我将在这一步停止。

    【讨论】:

      猜你喜欢
      • 2014-03-13
      • 2013-06-25
      • 2022-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-31
      • 2015-02-08
      相关资源
      最近更新 更多