package edu.stanford.rsl.tutorial.dmip;
import edu.stanford.rsl.conrad.numerics.SimpleMatrix;
import edu.stanford.rsl.conrad.numerics.SimpleMatrix.InversionType;
import edu.stanford.rsl.conrad.numerics.SimpleOperators;
import edu.stanford.rsl.conrad.numerics.SimpleVector;
import ij.gui.Plot;
/**
* Exercise 7 of Diagnostic Medical Image Processing (DMIP)
* @author Bastian Bier
*
*/
public class Registration1 {
/**
* Registration method
* Point Correspondences are used to calculate the rotation and translation
* Transformation from p to q
* @param p reference point cloud
* @param q point cloud to be registered
* @return translation and rotation for the registration (phi, t1, t2)
*/
private SimpleVector registrationUsingPointCorrespondences(SimpleMatrix p, SimpleMatrix q){
int numPoints = p.getRows();
// Build up measurement matrix m
SimpleMatrix m = new SimpleMatrix(numPoints * 2, 4);
for(int i = 0; i < numPoints * 2; i++)
{
if(i < numPoints)
{
// TODO
// TODO
// TODO
// TODO
}
if(i >= numPoints)
{
// TODO
// TODO
// TODO
// TODO
}
}
// Build up solution vector b
SimpleVector b = new SimpleVector(2 * numPoints);
for(int i = 0; i < 2 * numPoints; i++)
{
if(i < numPoints)
{
// TODO
}
if(i >= numPoints)
{
// TODO
}
}
// Calculate Pseudo Inverse of m
SimpleMatrix m_inv;
m_inv = m.inverse(InversionType.INVERT_SVD);
// Calculate Parameters with the help of the Pseudo Inverse
SimpleVector x;
x = SimpleOperators.multiply(m_inv, b);
double r1 = x.getElement(0);
double r2 = x.getElement(1);
double t1 = x.getElement(2);
double t2 = x.getElement(3);
// TODO: normalize r
double phi = 0; // TODO
// Write the result for the translation and the rotation into the result vector
SimpleVector result = new SimpleVector(phi, t1, t2);
return result;
}
private SimpleMatrix applyTransform(SimpleMatrix points, double phi, SimpleVector translation){
SimpleMatrix r = new SimpleMatrix(2,2);
// TODO: fill the rotation matrix
// TODO
// TODO
// TODO
// TODO
SimpleMatrix transformedPoints = new SimpleMatrix(points.getRows(), points.getCols());
for(int i = 0; i < transformedPoints.getRows(); i++)
{
// TODO: transform points
}
return transformedPoints;
}
public static void main(String[] args){
// Define Point Cloud
SimpleMatrix p_k = new SimpleMatrix(4,2);
SimpleMatrix q_k = new SimpleMatrix(4,2);
p_k.setRowValue(0, new SimpleVector(1,2));
p_k.setRowValue(1, new SimpleVector(3,6));
p_k.setRowValue(2, new SimpleVector(4,6));
p_k.setRowValue(3, new SimpleVector(3,4));
q_k.setRowValue(0, new SimpleVector(-0.7, 2.1));
q_k.setRowValue(1, new SimpleVector(-2.1, 6.4));
q_k.setRowValue(2, new SimpleVector(-1.4, 7.1));
q_k.setRowValue(3, new SimpleVector(-0.7, 4.9));
// Plot Point Cloud
Plot plot = new Plot("Regression Line", "X", "Y", Plot.DEFAULT_FLAGS);
plot.setLimits(-10, 10, -10, 10);
plot.addPoints(p_k.getCol(0).copyAsDoubleArray(), p_k.getCol(1).copyAsDoubleArray(), Plot.BOX);
plot.addPoints(q_k.getCol(0).copyAsDoubleArray(), q_k.getCol(1).copyAsDoubleArray(), Plot.CIRCLE);
// Calculate registration parameter
Registration1 reg = new Registration1();
SimpleVector parameter = reg.registrationUsingPointCorrespondences(p_k, q_k);
// Rotation and translation
double phi = parameter.getElement(0);
SimpleVector translation = new SimpleVector(parameter.getElement(1), parameter.getElement(2));
// Transform points
SimpleMatrix transformedPoints = reg.applyTransform(q_k, phi, translation);
// Add transformed point cloud to the plot
plot.addPoints(transformedPoints.getCol(0).copyAsDoubleArray(), transformedPoints.getCol(1).copyAsDoubleArray(), Plot.CROSS);
plot.show();
}
}