我在我的Android应用程序中使用双线性插值。它运行完美,但需要花费大量时间才能得到结果。
我在xi = 259,920时测试它,yi也是259,920。回应的时间是:Galaxy Note 4需要3秒, 和HTC One M8大约需要8秒!那么我可以改变或使用什么来减少时间?!
我用于双线性插值的代码:
public static double[] BiInterp(Mat z, ArrayList < Double > xi, ArrayList < Double > yi) {
// Declare matrix indeces
int xi_i, yi_i;
// Initialize output vector
double zi[] = new double[xi.size()];
double s00, s01, s10, s11;
for (int i = 0; i < xi.size(); i++) { // Note: xi.length = yi.length !
xi_i = xi.get(i).intValue(); // X index without round
yi_i = yi.get(i).intValue(); // Y index without round
if (xi_i < z.rows() - 1 && yi_i < z.cols() - 1 && xi_i >= 0 && yi_i >= 0) {
// Four neighbors of sample pixel
s00 = z.get(xi_i,yi_i)[0]; s01 = z.get(xi_i,yi_i + 1)[0];
s10 = z.get(xi_i + 1,yi_i)[0];s11 = z.get(xi_i + 1,yi_i + 1)[0];
int neighbor_no = 4; // As bilinear interpolation take 4 neighbors
double A[][] = new double[neighbor_no][neighbor_no];
A[0][0]=xi_i; A[0][1]=yi_i; A[0][2]=xi_i*yi_i; A[0][3]=1;
A[1][0]=xi_i; A[1][1]=yi_i+1; A[1][2]=xi_i*(yi_i+1); A[1][3]=1;
A[2][0]=xi_i+1; A[2][1]=yi_i; A[2][2]=(xi_i+1)*yi_i; A[2][3]=1;
A[3][0]=xi_i+1; A[3][1]=yi_i+1; A[3][2]=(xi_i+1)*(yi_i+1); A[3][3]=1;
GaussianElimination solveE = new GaussianElimination();
double b[] = {s00,s01,s10,s11};
double x[] = solveE.solve(A, b);
zi[i] = xi.get(i)*x[0] + yi.get(i)*x[1] + xi.get(i)*yi.get(i)*x[2] + x[3];
}
}
return zi;
}
我用高斯消元法求解4未知
的方程private static final double EPSILON = 1e-10;
// Gaussian elimination with partial pivoting
public static double[] solve(double[][] A, double[] b) {
int N = b.length;
for (int p = 0; p < N; p++) {
// find pivot row and swap
int max = p;
for (int i = p + 1; i < N; i++) {
if (Math.abs(A[i][p]) > Math.abs(A[max][p])) {
max = i;
}
}
double[] temp = A[p];
A[p] = A[max];
A[max] = temp;
double t = b[p];
b[p] = b[max];
b[max] = t;
// singular or nearly singular
if (Math.abs(A[p][p]) <= EPSILON) {
throw new RuntimeException("Matrix is singular or nearly singular");
}
// pivot within A and b
for (int i = p + 1; i < N; i++) {
double alpha = A[i][p] / A[p][p];
b[i] -= alpha * b[p];
for (int j = p; j < N; j++) {
A[i][j] -= alpha * A[p][j];
}
}
}
// back substitution
double[] x = new double[N];
for (int i = N - 1; i >= 0; i--) {
double sum = 0.0;
for (int j = i + 1; j < N; j++) {
sum += A[i][j] * x[j];
}
x[i] = (b[i] - sum) / A[i][i];
}
return x;
}
正如您在双线性代码中看到的那样,我立即从Mat对象中获取像素强度。然而,当我使用矩阵时,它花费的时间要少得多,例如注意4需要1秒。
但是从Mat图像转换为矩阵需要4秒。所以我更喜欢使用Mat。
答案 0 :(得分:1)
这是一个更简单的双线性插值算法:
基本上你将它分解为三个简单的线性插值。您可以将其可视化为H形状。首先,向下插入H的左右柱,以获得每个值的中间值。然后沿横梁进行插值,得到中间的最终值。
代码将是这样的:
xi_i = xi.get(i).intValue(); // X index without round
yi_i = yi.get(i).intValue(); // Y index without round
if (xi_i < z.rows() - 1 && yi_i < z.cols() - 1 && xi_i >= 0 && yi_i >= 0) {
// Four neighbors of sample pixel
s00 = z.get(xi_i,yi_i)[0]; s01 = z.get(xi_i,yi_i + 1)[0];
s10 = z.get(xi_i + 1,yi_i)[0];s11 = z.get(xi_i + 1,yi_i + 1)[0];
// find fractional part of yi:
double yi_frac = yi.get(i) - (double)yi_i;
// interpolate between s00 and s01 to find s0:
double s0 = s00 + ((s01 - s00) * yi_frac);
// interpolate between s10 and s11 to find s1:
double s1 = s10 + ((s11 - s10) * yi_frac);
// find fractional part of xi:
double xi_frac = xi.get(i) - (double)xi_i;
// interpolate between s0 and s1 to find zi:
zi[i] = s0 + ((s1 - s0) * xi_frac);
}
你也可以通过使用定点整数而不是双精度来加快整个过程(以牺牲准确性为代价)。