【问题标题】:Faster way to perform rectangle merging based on their intersection基于交叉点执行矩形合并的更快方法
【发布时间】:2011-01-03 08:32:15
【问题描述】:

这被用于运动检测问题。 基本上,我对图像执行运动检测算法,并获得一个 blob 列表,其中每个 blob 希望对应于一个已移动的对象。但是,我们必须合并这些 blob,因为可能有许多相互接触的小 blob 应该是一个大 blob。

我使用此算法将 blob 合并在一起。

        //Expand all blobs by 1x1 to ensure that we can use intersection
        //blobs is a List<blob>
        foreach (Blob blob in blobs)
        {
            blob.BoundingBox.Inflate(1, 1);
        }

        bool needToRestartMerging = true;

        while (needToRestartMerging == true)
        {
            int count = blobs.Count;

            needToRestartMerging = false;
            for (int i = 0; i < count - 1; i++)
            {
                for (int j = i + 1; j < count; j++)
                {
                    //BoundingBox is a simple System.Drawing.Rectangle
                    if (blobs[i].BoundingBox.IntersectsWith(blobs[j].BoundingBox))
                    {
                        Blob newBlob = blobs[i].Merge(blobs[j]);
                        blobs.RemoveAt(i);
                        blobs.RemoveAt(j-1);
                        blobs.Add(newBlob);
                        needToRestartMerging = true;
                        count = blobs.Count;
                    }
                }
            }
        }

这就是我合并 blob 的方式:

    /// <summary>
    /// Given a Pixel Location, we resize the Blob so that it is included in the BoundingBox
    /// </summary>
    /// <param name="x">Pixel XCoordinate</param>
    /// <param name="y">Pixel YCoordinate</param>
    public void ResizeToPixelLocation(int x, int y)
    {           
        numPixels++;
        if (x >= _boundingBox.Right)
        {
            _boundingBox.Width = x - _boundingBox.X;
        }
        if (y >= _boundingBox.Bottom)
        {
            _boundingBox.Height = y - _boundingBox.Y;
        }
        if (x <= _boundingBox.Left)
        {
            int oldLeft = _boundingBox.Left;
            int xOffset = x - _boundingBox.Left;
            _boundingBox.Offset(xOffset, 0);
            _boundingBox.Width += (oldLeft - x);
        }
        if (y <= _boundingBox.Top)
        {
            int oldTop = _boundingBox.Top;
            int yOffset = y - _boundingBox.Top;
            _boundingBox.Offset(0, yOffset);
            _boundingBox.Height += (oldTop - y);

        }
    }

    /// <summary>
    /// Merge this blob with another blob
    /// </summary>
    /// <param name="blob2">The second blob</param>
    /// <returns></returns>
    public Blob Merge(Blob blob2)
    {
        Blob newBlob = new Blob(BoundingBox.X, BoundingBox.Y);
        newBlob.ThreadID = this.ThreadID;
        newBlob.numPixels = NumPixels + blob2.NumPixels;
        newBlob.BoundingBox = BoundingBox;
        newBlob.ResizeToPixelLocation(blob2.BoundingBox.X, blob2.BoundingBox.Y);
        newBlob.ResizeToPixelLocation(blob2.BoundingBox.Right, blob2.BoundingBox.Bottom);
        return newBlob;
    }

我总共可能有大约 0-150 个斑点。我想知道是否有更快的方法来进行 blob 合并。 谢谢

【问题讨论】:

    标签: c# bounding-box motion-detection


    【解决方案1】:

    我会建议一些类似的东西:

    mergeConnected(input):
      output = new RectangleSet
      while input.length > 0 do
        nextRect = input.pop()
        intersected = output.findIntersected(nextRect)
        if intersected then
          output.remove(intersected)
          input.push(nextRect.merge(intersected))
        else
          output.insert(nextRect)
      done
      return output
    

    每次循环迭代要么从output 中删除,要么添加到output 并从input 中删除,因此循环迭代的总数不大于输出矩形数的两倍。

    为了提高output.findIntersected 的性能,您可以将矩形集表示为针对交集搜索优化的数据结构(与普通列表相反)。例如,您可以保留按矩形的最大 X 排序的数据结构以剔除其中几个,然后插入按最小 X 排序的矩形。简单的经典解决方案,例如 kd-trees 或自适应二叉树,也可以工作,但插入/移除时间可能会对性能产生不利影响。

    【讨论】:

    • 感谢您的回答,我发现的唯一问题是表示您提到的数据结构。
    • 感谢您的评论,但最终我们并没有走那么远,因为它“够快”了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-26
    • 2011-08-03
    • 1970-01-01
    相关资源
    最近更新 更多