package edu.stanford.rsl.tutorial.motion.estimation;
import ij.ImageJ;
import java.util.ArrayList;
import edu.stanford.rsl.conrad.data.numeric.Grid2D;
import edu.stanford.rsl.conrad.geometry.shapes.simple.PointND;
import edu.stanford.rsl.conrad.numerics.SimpleMatrix;
import edu.stanford.rsl.conrad.numerics.SimpleOperators;
import edu.stanford.rsl.conrad.numerics.SimpleVector;
public class RadialBasisFunctionInterpolation {
private ArrayList<PointND> gridPoints;
private double[] values;
private int c;
private SimpleVector coefficients;
public static enum RBF {
MQ, TPS, GAUSS
};
private RBF type;
public RadialBasisFunctionInterpolation(RBF type, int c,
ArrayList<PointND> points, double[] values) {
this.gridPoints = points;
this.values = values;
this.c = c;
this.type = type;
estimateCoefficients();
}
private void estimateCoefficients() {
int n = gridPoints.size();
SimpleMatrix A = new SimpleMatrix(n, n);
SimpleVector rhs = new SimpleVector(values.length);
if (type == RBF.MQ) {
for (int j = 0; j < n; j++) {
rhs.setElementValue(j, values[j]);
for (int k = 0; k < n; k++) {
double val = Math.sqrt(c
* c
+ Math.pow(
gridPoints.get(j).euclideanDistance(
gridPoints.get(k)), 2));
A.setElementValue(j, k, val);
}
}
} else if (type == RBF.TPS) {
for (int j = 0; j < n; j++) {
rhs.setElementValue(j, values[j]);
for (int k = 0; k < n; k++) {
double r = gridPoints.get(j).euclideanDistance(
gridPoints.get(k));
double val = r > 0 ? r * r + Math.log(r + 0.000001) : 0;
A.setElementValue(j, k, val);
}
}
} else if (type == RBF.GAUSS) {
double sigmasquare = 100;
for (int j = 0; j < n; j++) {
rhs.setElementValue(j, values[j]);
for (int k = 0; k < n; k++) {
double r = gridPoints.get(j).euclideanDistance(
gridPoints.get(k));
double val = Math.exp((-r * r) / (sigmasquare));
A.setElementValue(j, k, val);
}
}
}
SimpleMatrix Ainv = A.inverse(SimpleMatrix.InversionType.INVERT_SVD);
coefficients = SimpleOperators.multiply(Ainv, rhs);
}
public double interpolate(PointND pt) {
double val = 0;
if (type == RBF.MQ) {
for (int i = 0; i < coefficients.getLen(); i++) {
val += coefficients.getElement(i)
* Math.sqrt(c
* c
+ Math.pow(
pt.euclideanDistance(gridPoints.get(i)),
2));
}
} else if (type == RBF.TPS) {
for (int i = 0; i < coefficients.getLen(); i++) {
double r = pt.euclideanDistance(gridPoints.get(i));
double tps = r > 0 ? r * r + Math.log(r + 0.000001) : 0;
val += coefficients.getElement(i) * (tps);
}
} else if (type == RBF.GAUSS) {
double sigmasquare = 100;
for (int i = 0; i < coefficients.getLen(); i++) {
double r = pt.euclideanDistance(gridPoints.get(i));
val += coefficients.getElement(i)
* Math.exp((-r * r) / sigmasquare);
}
}
return val;
}
public static void main(String args[]) {
new ImageJ();
ArrayList<PointND> points = new ArrayList<PointND>();
points.add(new PointND(30, 30));
points.add(new PointND(60, 60));
points.add(new PointND(90, 90));
points.add(new PointND(120, 120));
points.add(new PointND(90, 150));
points.add(new PointND(60, 180));
points.add(new PointND(30, 210));
double[] values = new double[7 + 500];
values[0] = 100;
values[1] = 200;
values[2] = 300;
values[3] = 400;
values[4] = 300;
values[5] = 200;
values[6] = 100;
for (int i = 0; i < 250; i++) {
points.add(new PointND(i * 2, 400));
values[i + 7] = 0;
}
for (int i = 0; i < 250; i++) {
points.add(new PointND(i * 2, 499));
values[i + 7 + 250] = 0;
}
RadialBasisFunctionInterpolation rad = new RadialBasisFunctionInterpolation(
RBF.MQ, 1, points, values);
Grid2D grid = new Grid2D(500, 500);
for (int i = 0; i < 500; i++) {
for (int j = 0; j < 500; j++) {
grid.setAtIndex(i, j,
(float) rad.interpolate(new PointND(i, j)));
}
}
grid.show();
RadialBasisFunctionInterpolation rad2 = new RadialBasisFunctionInterpolation(
RBF.TPS, 2, points, values);
Grid2D grid2 = new Grid2D(500, 500);
for (int i = 0; i < 500; i++) {
for (int j = 0; j < 500; j++) {
grid2.setAtIndex(i, j,
(float) rad2.interpolate(new PointND(i, j)));
}
}
grid2.show();
}
}
/*
* Copyright (C) 2010-2014 Marco B�gel
* CONRAD is developed as an Open Source project under the GNU General Public License (GPL).
*/