给定任意像素的连续绘图(例如在 HTML5 画布上),是否有任何算法可以找到比简单地查看每个像素并记录最小/最大 x/y 值更有效的轴对齐边界框?
问问题
2350 次
3 回答
11
只需从左上角到右下角扫描线即可得到 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
为了好玩,这里是这个算法如何工作的可视化表示:
选择以什么顺序进行边角处理并不重要,您只需要确保将先前的结果考虑在内,这样您就不会重复扫描角落。
于 2012-06-12T10:08:18.687 回答
1
您可能可以使用某种二进制搜索,或者在粗网格上采样,然后再在更细的网格上采样。此方法的正确性取决于您的绘图中是否允许“孔”。
于 2012-03-24T13:36:48.343 回答
0
我不喜欢当前的答案。这是我插入 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};
}
于 2020-03-26T04:04:23.933 回答