定向边界框算法,需要一些 understanding/clarification 几行现有(工作)代码
Oriented Bounding Box algorithm, Need some understanding/clarification of a few lines of existing (working) code
我正在查看可在以下位置公开获得的一些 MATLAB 代码:
https://github.com/mattools/matGeom/blob/master/matGeom/geom2d/orientedBox.m
这是在一组点的凸包上实施旋转卡尺算法,以计算定向边界框。我的评论是为了直观地理解该算法是如何工作的,但是我寻求对文件中我感到困惑的某些行的澄清。
第 44 行:hull = bsxfun(@minus, hull, center);
。这似乎平移了凸包集中的所有点,因此计算出的质心位于 (0,0)。执行此操作有什么特别的原因吗?我唯一的猜测是它允许稍后在代码中进行直接的旋转变换,因为围绕真实原点旋转会导致严重问题。
第 71 和 74 行:indA2 = mod(indA, nV) + 1;
,indB2 = mod(indB, nV) + 1;
。这是为了防止访问索引越界的技巧吗?我的猜测是为了防止越界访问,它会在到达末尾时滚动索引。
第 125 行:y2 = - x * sit + y * cot;
。这是正确的转换,因为代码运行正常,但我不确定为什么实际使用它,并且与后来和之前完成的其他旋转转换不同(通过调用 rotateVector)。我最好的猜测是我根本没有在脑海中正确地想象出需要进行哪些旋转。
旁注:外部函数调用 vectorAngle
、rotateVector
、createLine
和 distancePointLine
都可以在同一个存储库下找到,在以函数名称(根据 MATLAB 标准)。它们相对无趣,除了正在进行矢量角归一化这一事实外,它们的作用与您期望的一样。
我没有真正看代码,这是对旋转卡尺工作原理的解释。
一个基本的 属性 是最紧密的边界框是这样的,它的一侧与船体的边缘重叠。所以你所做的基本上是
依次尝试每条边;
对于给定的一条边,被看作是水平的,南边的,找到最远的北边、西边和东边的顶点;
计算他们定义的矩形的面积或周长;
记住最好的区域。
需要注意的是,当你从一条边切换到下一条边时,N/W/E顶点只能向前移动,很容易找到相关坐标的下一个递减。这就是总处理时间如何与边数呈线性关系(搜索初始 N/E/W 顶点需要 3(N-3) 次比较,然后更新需要 3(N-1)+Nn+Nw+ Ne 比较,其中 Nn、Nw、Ne 是从一个顶点到下一个顶点的移动次数;显然总共 Nn+Nw+Ne = 3N)。
模数用于实现边和顶点的循环索引。
我是上面这段代码的作者,所以我可以给出一些解释:
首先,该算法确实是一个旋转卡尺算法。在当前的实现中,只测试了算法的宽度(我没有检查 west 和 est 顶点)。实际上,这两个结果似乎大部分时间是一致的。
第 44 行 -> 转换为原点的目的是提高数值精度。当多边形远离原点时,坐标可能很大,并且靠得很近。许多计算涉及坐标的乘积。通过围绕原点平移多边形,坐标更小,结果产品的精度有望提高。好吧,老实说,我没有直接证明这种效果,这是一种比修复更谨慎的编码方式......
第 71-74 行!是的。这个想法是沿着多边形找到下一个顶点的索引。如果当前顶点是多边形的最后一个顶点,那么下一个顶点索引应该是 1。在 0 和 N-1 之间使用模重新缩放。这两行确保正确的迭代。
第125行:涉及到几个转换。使用 rotateVector() 函数,可以简单地计算给定边的最小值。在第 125 行,旋转点(凸包的)以与“最佳”方向(宽度最小化的方向)对齐。最后一次坐标变化(第 132->140 行)是由于定向框的中心与多边形的质心不同。然后我们加一个shift,通过旋转修正。
我正在查看可在以下位置公开获得的一些 MATLAB 代码: https://github.com/mattools/matGeom/blob/master/matGeom/geom2d/orientedBox.m
这是在一组点的凸包上实施旋转卡尺算法,以计算定向边界框。我的评论是为了直观地理解该算法是如何工作的,但是我寻求对文件中我感到困惑的某些行的澄清。
第 44 行:hull = bsxfun(@minus, hull, center);
。这似乎平移了凸包集中的所有点,因此计算出的质心位于 (0,0)。执行此操作有什么特别的原因吗?我唯一的猜测是它允许稍后在代码中进行直接的旋转变换,因为围绕真实原点旋转会导致严重问题。
第 71 和 74 行:indA2 = mod(indA, nV) + 1;
,indB2 = mod(indB, nV) + 1;
。这是为了防止访问索引越界的技巧吗?我的猜测是为了防止越界访问,它会在到达末尾时滚动索引。
第 125 行:y2 = - x * sit + y * cot;
。这是正确的转换,因为代码运行正常,但我不确定为什么实际使用它,并且与后来和之前完成的其他旋转转换不同(通过调用 rotateVector)。我最好的猜测是我根本没有在脑海中正确地想象出需要进行哪些旋转。
旁注:外部函数调用 vectorAngle
、rotateVector
、createLine
和 distancePointLine
都可以在同一个存储库下找到,在以函数名称(根据 MATLAB 标准)。它们相对无趣,除了正在进行矢量角归一化这一事实外,它们的作用与您期望的一样。
我没有真正看代码,这是对旋转卡尺工作原理的解释。
一个基本的 属性 是最紧密的边界框是这样的,它的一侧与船体的边缘重叠。所以你所做的基本上是
依次尝试每条边;
对于给定的一条边,被看作是水平的,南边的,找到最远的北边、西边和东边的顶点;
计算他们定义的矩形的面积或周长;
记住最好的区域。
需要注意的是,当你从一条边切换到下一条边时,N/W/E顶点只能向前移动,很容易找到相关坐标的下一个递减。这就是总处理时间如何与边数呈线性关系(搜索初始 N/E/W 顶点需要 3(N-3) 次比较,然后更新需要 3(N-1)+Nn+Nw+ Ne 比较,其中 Nn、Nw、Ne 是从一个顶点到下一个顶点的移动次数;显然总共 Nn+Nw+Ne = 3N)。
模数用于实现边和顶点的循环索引。
我是上面这段代码的作者,所以我可以给出一些解释:
首先,该算法确实是一个旋转卡尺算法。在当前的实现中,只测试了算法的宽度(我没有检查 west 和 est 顶点)。实际上,这两个结果似乎大部分时间是一致的。
第 44 行 -> 转换为原点的目的是提高数值精度。当多边形远离原点时,坐标可能很大,并且靠得很近。许多计算涉及坐标的乘积。通过围绕原点平移多边形,坐标更小,结果产品的精度有望提高。好吧,老实说,我没有直接证明这种效果,这是一种比修复更谨慎的编码方式......
第 71-74 行!是的。这个想法是沿着多边形找到下一个顶点的索引。如果当前顶点是多边形的最后一个顶点,那么下一个顶点索引应该是 1。在 0 和 N-1 之间使用模重新缩放。这两行确保正确的迭代。
第125行:涉及到几个转换。使用 rotateVector() 函数,可以简单地计算给定边的最小值。在第 125 行,旋转点(凸包的)以与“最佳”方向(宽度最小化的方向)对齐。最后一次坐标变化(第 132->140 行)是由于定向框的中心与多边形的质心不同。然后我们加一个shift,通过旋转修正。