I am attempting to use hipparchus.org/hipparchus-optim/leastsquares.html to find the unknowns A, B, C, D, E, F for the coordinate transformation defined by the equations:
x’ = Ax + By + C
y’ = Dx + Ey + F
Where (x’,y’) are points from the reference image, and (x,y) are corresponding points in the target image that needs to be scaled, rotated and translated to match the reference.
I tried the following code, but it fails to calculate the correct results.
import org.hipparchus.geometry.euclidean.twod.Vector2D;
import org.hipparchus.linear.Array2DRowRealMatrix;
import org.hipparchus.linear.ArrayRealVector;
import org.hipparchus.linear.RealMatrix;
import org.hipparchus.linear.RealVector;
import org.hipparchus.optim.nonlinear.vector.leastsquares.*;
import org.hipparchus.util.Pair;
/**
* Determine scale, rotation and translation needed to transform the
* target image to match the reference image.
* To do this we need to solve:
* x' = Ax + By + C
* y' = Dx + Ey + F
* (x, y ) are from the target frame,
* (x',y') are from the reference
*/
public class TransformSolver {
final Vector2D[] refPoints;
final Vector2D[] tgtPoints;
MultivariateJacobianFunction model = new MultivariateJacobianFunction() {
public Pair<RealVector, RealMatrix> value(final RealVector constants) {
RealVector value = new ArrayRealVector(tgtPoints.length);
RealMatrix jacobian = new Array2DRowRealMatrix(tgtPoints.length, 3);
double A = constants.getEntry(0);
double B = constants.getEntry(1);
double C = constants.getEntry(2);
for (int i = 0; i < tgtPoints.length; ++i) {
Vector2D tgtPoint = tgtPoints[i];
double x = A * tgtPoint.getX() + B * tgtPoint.getY() + C;
value.setEntry(i, x);
// derivative with respect to x
jacobian.setEntry(i, 0, A);
// derivative with respect to y
jacobian.setEntry(i, 1, B);
// Constant
jacobian.setEntry(i, 1, 0.0);
}
return new Pair<>(value, jacobian);
}
};
/**
* @param refPoints reference points in the reference image
* @param tgtPoints corresponding target image positions
*/
TransformSolver(Vector2D[] refPoints, Vector2D[] tgtPoints, boolean fastCreate){
if (refPoints.length != tgtPoints.length)
throw new IllegalArgumentException("TransformSolver: input arrays have different lengths");
this.refPoints = refPoints;
this.tgtPoints = tgtPoints;
solveX();
solveY();
}
private void solveX(){
double[] refValues = new double[refPoints.length];
for (int i = 0; i < refPoints.length; i++){
refValues[i] = refPoints[i].getX();
}
// least squares problem to solve
LeastSquaresProblem problem = new LeastSquaresBuilder().
start(new double[]{1.0, 0.0, 0.0}).
model(model).
target(refValues).
lazyEvaluation(false).
maxEvaluations(1000).
maxIterations(1000).
build();
LeastSquaresOptimizer.Optimum optimum = new LevenbergMarquardtOptimizer().optimize(problem);
System.out.println("A=" + optimum.getPoint().getEntry(0));
System.out.println("B=" + optimum.getPoint().getEntry(1));
System.out.println("C=" + optimum.getPoint().getEntry(2));
}
private void solveY(){
double[] refValues = new double[refPoints.length];
for (int i = 0; i < refPoints.length; i++){
refValues[i] = refPoints[i].getY();
}
// least squares problem to solve
LeastSquaresProblem problem = new LeastSquaresBuilder().
start(new double[]{0.0, 1.0, 0.0}).
model(model).
target(refValues).
lazyEvaluation(false).
maxEvaluations(1000).
maxIterations(1000).
build();
LeastSquaresOptimizer.Optimum optimum = new LevenbergMarquardtOptimizer().optimize(problem);
System.out.println("D=" + optimum.getPoint().getEntry(0));
System.out.println("E=" + optimum.getPoint().getEntry(1));
System.out.println("F=" + optimum.getPoint().getEntry(2));
}
}
John is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.