【问题标题】:Calculate bounding box of arbitrary pixel-based drawing计算任意基于像素的绘图的边界框
【发布时间】:2012-04-08 18:40:19
【问题描述】:

给定任意像素的连续绘图(例如在 HTML5 Canvas 上),是否有任何算法可以比简单的looking at every pixel and recording the min/max x/y values 更有效地找到轴对齐的边界框?

【问题讨论】:

标签: graphics pixels bounding-box aabb


【解决方案1】:

您也许可以使用某种二分搜索,或在粗网格上采样,然后再在更细的网格上采样。此方法的正确性取决于您的绘图中是否允许“孔”。

【讨论】:

  • 如果图形有任何凹入的边界部分,二分搜索很容易失败。
【解决方案2】:

只需从左上​​角到右下角扫描线得到y顶部,其余的方向类似的算法。


Phrogz 编辑:

这是一个伪代码实现。包含的优化可确保每条扫描线都不会查看先前通道覆盖的像素:

function boundingBox()
  w = getWidth()            # Assuming graphics address goes from [0,w)
  h = getHeight()           # Assuming graphics address goes from [0,h)
  for y=h-1 to 0 by -1      # Iterate from last row upwards
    for x=w-1 to 0 by -1    # Iterate across the entire row
      if pxAt(x,y) then
        maxY=y
        break               # Break out of both loops

  if maxY===undefined then  # No pixels, no bounding box
    return               

  for x=w-1 to 0 by -1      # Iterate from last column to first
    for y=0 to maxY         # Iterate down the column, up to maxY
      if pxAt(x,y) then
        maxX=x
        break               # Break out of both loops

  for x=0 to maxX           # Iterate from first column to maxX
    for y=0 to maxY         # Iterate down the column, up to maxY
      if pxAt(x,y) then
        minX=x
        break               # Break out of both loops

  for y=0 to maxY           # Iterate down the rows, up to maxY
    for x=0 to maxX         # Iterate across the row, up to maxX
      if pxAt(x,y) then
        minY=y
        break               # Break out of both loops

  return minX, minY, maxX, maxY

结果(在实践中)与单个像素的蛮力算法大致相同,并且随着对象变大而明显更好。

演示:http://phrogz.net/tmp/canvas_bounding_box2.html

为了好玩,下面是这个算法如何工作的直观表示:

     



选择边的顺序无关紧要,您只需确保将之前的结果考虑在内,以免重复扫描边角。

【讨论】:

    【解决方案3】:

    我不喜欢当前的答案。这是我插入 OP 网站的代码。在 Firefox 和 chrome 中速度要快得多。

    这个想法是检查 x 轴上的所有像素以查看 Y 轴上是否有命中。如果是这样,更新 Y 并增加 X,以便我们可以扫描最大 X

    function contextBoundingBox(ctx,alphaThreshold){
        if (alphaThreshold===undefined) alphaThreshold = 15;
        var w=ctx.canvas.width,h=ctx.canvas.height;
        var data = ctx.getImageData(0,0,w,h).data;
    
        let minX=w;
        let maxX=0
        let minY=h
        let maxY=0
        for(let y=0; y<h; y++)
        {
            for(let x=0; x<w; x++)
            {
                if (data[y*w*4 + x*4+3])
                {
                    minX = Math.min(minX, x);
                    maxX = Math.max(maxX, x);
                    minY = Math.min(minY, y);
                    maxY = y;
                    x=maxX
                }
            }
        }
    
        return {x:minX,y:minY,maxX:maxX,maxY:maxY,w:maxX-minX,h:maxY-minY};
    }
    

    【讨论】:

      猜你喜欢
      • 2010-12-19
      • 2019-09-19
      • 2017-11-30
      • 2013-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-02
      • 2018-11-26
      相关资源
      最近更新 更多