1

我正在做一些视频处理,对于每一帧我需要得到一个双变量函数的梯度。该函数表示为一个二维双精度数组。其中域是行和列索引,范围是相应索引值的双精度值。或者更简单地说,函数fdouble[][] matrix这样定义的:

f(x,y)=matrix[x][y]

我正在尝试使用 Apache Commons Math 库:

SmoothingPolynomialBicubicSplineInterpolator iterpolator = new SmoothingPolynomialBicubicSplineInterpolator();
BicubicSplineInterpolatingFunction f = iterpolator.interpolate(xs, ys, matrix.getData());
    for (int i = 0; i < ans.length; i++) {
        for (int j = 0; j < ans[0].length; j++) {
            ans[i][j] = f.partialDerivativeY(i, j); 
        }
    }
  • 使用 xs,作为 x 索引的排序数组(0,1,...,matrix.getRowDimension() - 1)
  • ys 在列维度上相同(0,1,...,matrix.getColumnDimension() - 1)

问题是,对于一个典型的矩阵,150X80它的大小需要1.4几秒钟的时间才能运行,这使得它与我的需求完全无关。所以,作为这个库的新手用户,以及一般的编程数值分析,我想知道:

  1. 难道我做错了什么?
  2. 有没有另一种更快的方法可以完成这项任务?
  3. 是否有另一个提供解决方案的开源库(最好是对 maven 友好的)?
4

1 回答 1

0

数值微分本身就是一个完整的主题,一个简单的谷歌应该提供足够的材料供您使用(仅 wiki 可能就足够了)。您的问题的某些参数我不知道,所以我只能在这里泛泛地说,但是有确定给定点的梯度的直接方法,即不需要插值的方法。请参阅维基百科的公式(范围从简单f(x+1)-f(x)的 whereh=1到更高阶的)。计算偏导数是一个简单的O(NM)循环,里面有一个超级简单的公式(不需要插值)。

细节可能会变得坚韧:

  1. 需要为边缘减少高阶公式,或完全丢弃。
  2. 您精确的速度要求可能会使更复杂的公式变得无用(取决于平台,有时高阶公式的查找时间会使它们太慢;同样,这取决于缓存等)。这很容易测试,公式很简单;对它们进行编码和基准测试。
  3. 具体实现还取决于您的错误要求。该理论提供了误差范围,因此它将在您需要的公式中发挥作用;但同样,需要权衡速度要求。如果你知道你将要处理的矩阵类型的细节,如果这样的事情是已知的,那么反过来实际上可以降低。

如果您有现有的卷积工具,则可以使实现变得更加容易(也许更快),因为这种方法实际上只是矩阵的卷积(注意;从技术上讲,它被称为互相关)。

于 2013-01-19T16:57:04.940 回答