package edu.stanford.rsl.conrad.geometry.test;
import static org.junit.Assert.*;
//import org.junit.After;
//import org.junit.AfterClass;
//import org.junit.Before;
//import org.junit.BeforeClass;
import org.junit.Test;
import edu.stanford.rsl.conrad.geometry.General;
import edu.stanford.rsl.conrad.geometry.Projection;
import edu.stanford.rsl.conrad.geometry.Rotations;
import edu.stanford.rsl.conrad.geometry.Projection.CameraAxisDirection;
import edu.stanford.rsl.conrad.geometry.Rotations.BasicAxis;
import edu.stanford.rsl.conrad.numerics.SimpleMatrix;
import edu.stanford.rsl.conrad.numerics.SimpleOperators;
import edu.stanford.rsl.conrad.numerics.SimpleVector;
import static edu.stanford.rsl.conrad.utils.TestingTools.*;
public class ProjectionTest {
// scaling parameter
private static final double fs1 = randPositive();
private static final double fs2 = randPositive();
// intrinsic parameters
private static final double ffocalU1 = rand(500.0, 1500.0); // px
private static final double ffocalU2 = rand(500.0, 1500.0); // px
private static final double ffocalV1 = rand(500.0, 1500.0); // px
private static final double ffocalV2 = rand(500.0, 1500.0); // px
private static final double fcameraToImage1 = rand(500.0, 1500.0); // mm
private static final double fcameraToImage2 = rand(500.0, 1500.0); // mm
private static final double fspacingU1 = fcameraToImage1 / ffocalU1; // mm/px
private static final double fspacingU2 = fcameraToImage2 / ffocalU2; // mm/px
private static final double fspacingV1 = fcameraToImage1 / ffocalV1; // mm/px
private static final double fspacingV2 = fcameraToImage2 / ffocalV2; // mm/px
private static final SimpleVector fspacing1 = new SimpleVector(fspacingU1, fspacingV1);
private static final SimpleVector fspacing2 = new SimpleVector(fspacingU2, fspacingV2);
private static final double fskew1 = rand(-0.5, 0.5); // px
private static final double fskew2 = rand(-0.5, 0.5); // px
private static final double fppU1 = rand(200.0, 600.0); // px
private static final double fppU2 = rand(200.0, 600.0); // px
private static final double fppV1 = rand(200.0, 600.0); // px
private static final double fppV2 = rand(200.0, 600.0); // px
private static final SimpleVector fpp1 = new SimpleVector(fppU1, fppV1);
private static final SimpleVector fpp2 = new SimpleVector(fppU2, fppV2);
private static final double fsizeU1 = rand(400.0, 1200.0); // px
private static final double fsizeU2 = rand(400.0, 1200.0); // px
private static final double fsizeV1 = rand(400.0, 1200.0); // px
private static final double fsizeV2 = rand(400.0, 1200.0); // px
private static final SimpleVector fsize1 = new SimpleVector(fsizeU1, fsizeV1);
private static final SimpleVector fsize2 = new SimpleVector(fsizeU2, fsizeV2);
private static final SimpleVector foffset1 = SimpleOperators.subtract(fpp1, fsize1.multipliedBy(0.5));
private static final SimpleVector foffset2 = SimpleOperators.subtract(fpp2, fsize2.multipliedBy(0.5));
private static final double fdir1 = randPmOne(); // +/-z_C
private static final double fdir2 = randPmOne(); // +/-z_C
private static final SimpleMatrix fK1 = new SimpleMatrix(new double[][] {
{ffocalU1, fskew1, fppU1*fdir1},
{0.0, ffocalV1, fppV1*fdir1},
{0.0, 0.0, fdir1}
});
private static final SimpleMatrix fK2 = new SimpleMatrix(new double[][] {
{ffocalU2, fskew2, fppU2*fdir2},
{0.0, ffocalV2, fppV2*fdir2},
{0.0, 0.0, fdir2}
});
// extrinsic parameters
private static final double fcameraToOrigin1 = rand(0.0, 1.0) * fcameraToImage1; // [0, 1]*fcameraToImage
private static final double fcameraToOrigin2 = rand(0.0, 1.0) * fcameraToImage2; // [0, 1]*fcameraToImage
private static final SimpleVector ft1 = new SimpleVector(rand(-50.0, 50.0), rand(-50.0, 50.0), fdir1 * fcameraToOrigin1);
private static final SimpleVector ft2 = new SimpleVector(rand(-50.0, 50.0), rand(-50.0, 50.0), fdir2 * fcameraToOrigin2);
private static final SimpleMatrix tmpRx1 = Rotations.createBasicRotationMatrix(BasicAxis.X_AXIS, randAng());
private static final SimpleMatrix tmpRx2 = Rotations.createBasicRotationMatrix(BasicAxis.X_AXIS, randAng());
private static final SimpleMatrix tmpRy1 = Rotations.createBasicRotationMatrix(BasicAxis.Y_AXIS, randAng());
private static final SimpleMatrix tmpRy2 = Rotations.createBasicRotationMatrix(BasicAxis.Y_AXIS, randAng());
private static final SimpleMatrix tmpRz1 = Rotations.createBasicRotationMatrix(BasicAxis.Z_AXIS, randAng());
private static final SimpleMatrix tmpRz2 = Rotations.createBasicRotationMatrix(BasicAxis.Z_AXIS, randAng());
private static final SimpleMatrix fR1 = SimpleOperators.multiplyMatrixProd(SimpleOperators.multiplyMatrixProd(tmpRx1, tmpRy1), tmpRz1);
private static final SimpleMatrix fR2 = SimpleOperators.multiplyMatrixProd(SimpleOperators.multiplyMatrixProd(tmpRx2, tmpRy2), tmpRz2);
private static final SimpleMatrix fRt1 = General.createHomAffineMotionMatrix(fR1, ft1);
private static final SimpleMatrix fRt2 = General.createHomAffineMotionMatrix(fR2, ft2);
// complete matrix
private static final SimpleMatrix fP1 = (SimpleOperators.multiplyMatrixProd(fK1, fRt1.getSubMatrix(0, 0, 3, 4))).multipliedBy(fs1);
private static final SimpleMatrix fP2 = (SimpleOperators.multiplyMatrixProd(fK2, fRt2.getSubMatrix(0, 0, 3, 4))).multipliedBy(fs2);
// other
private static final double additionalScaling = 10.0*randPositive();
// @BeforeClass
// public static void setUpBeforeClass() throws Exception {
// }
// @AfterClass
// public static void tearDownAfterClass() throws Exception {
// }
// @Before
// public void setUp() throws Exception {
// }
// @After
// public void tearDown() throws Exception {
// }
@Test
public void testProjection() {
Projection proj = new Projection();
assertEquals(proj.getS(), 1.0, 0.0);
final SimpleVector v0 = new SimpleVector(3);
assertEqualElementWise(proj.getK(), SimpleMatrix.I_3, 0.0);
assertEqualElementWise(proj.getR(), SimpleMatrix.I_3, 0.0);
assertEqualElementWise(proj.getT(), v0, 0.0);
}
@Test
public void testProjectionAbstractMatrix() {
Projection proj = new Projection(fP1);
assertEqualElementWise(proj.computeP(), fP1, DELTA);
}
@Test
public void testProjectionDoubleArrayDoubleArrayIntArray() {
Projection projtmp = new Projection(fP1);
int[] glViewport = new int[] {(int)rand(-100.0, 100.0), (int)rand(-100.0, 100.0), (int)fsizeU1, (int)fsizeV1};
double[] glProjectionGlVec = new double[16];
double[] glModelviewGlVec = new double[16];
projtmp.computeGLMatrices(glViewport[0], glViewport[1], glViewport[2], glViewport[3], rand(100.0, 400.0), rand(800.0, 1200.0), glProjectionGlVec, glModelviewGlVec); // s is not transferred to the OpenGL representation
Projection proj = new Projection(glProjectionGlVec, glModelviewGlVec, glViewport);
assertEquals(proj.getS(), 1.0, DELTA); // s cannot be recovered since it's not been transferred to the OpenGL representation
assertEqualElementWise(proj.getK(), fK1, DELTA);
assertEqualElementWise(proj.getR(), fR1, DELTA);
assertEqualElementWise(proj.getT(), ft1, DELTA);
}
@Test
public void testSetToExampleCamera() {
Projection proj = new Projection();
proj.initToExampleCamera();
final SimpleMatrix Ktmp = new SimpleMatrix(new double[][] {
{1000.0, 0.0, 500.0},
{ 0.0, 1000.0, 500.0},
{ 0.0, 0.0, 1.0}
});
final SimpleVector ttmp = new SimpleVector(0.0, 0.0, 500.0);
assertEquals(proj.getS(), 1.0, 0.0);
assertEqualElementWise(proj.getK(), Ktmp, 0.0);
assertEqualElementWise(proj.getR(), SimpleMatrix.I_3, 0.0);
assertEqualElementWise(proj.getT(), ttmp, 0.0);
}
@Test
public void testSetFromP() {
Projection proj = new Projection();
// test with valid matrix
proj.initFromP(fP1.multipliedBy(additionalScaling));
assertEquals(proj.getS(), fs1*additionalScaling, DELTA);
assertEqualElementWise(proj.getK(), fK1, DELTA);
assertEqualElementWise(proj.getR(), fR1, DELTA);
assertEqualElementWise(proj.getT(), ft1, DELTA);
proj.initFromP(fP2.multipliedBy(additionalScaling));
assertEquals(proj.getS(), fs2*additionalScaling, DELTA);
assertEqualElementWise(proj.getK(), fK2, DELTA);
assertEqualElementWise(proj.getR(), fR2, DELTA);
assertEqualElementWise(proj.getT(), ft2, DELTA);
}
@Test(expected = IllegalArgumentException.class)
public void testSetFromPSingularMatrix() {
Projection proj = new Projection();
final SimpleMatrix fP_fail_sing = fP1.clone();
fP_fail_sing.setSubRowValue(1, 0, fP_fail_sing.getSubRow(0, 0, 3));
proj.initFromP(fP_fail_sing);
}
@Test(expected = IllegalArgumentException.class)
public void testSetFromPWrongSizeMatrix() {
Projection proj = new Projection();
final SimpleMatrix fP_fail_size = fP1.getSubMatrix(0, 0, 3, 3);
proj.initFromP(fP_fail_size);
}
@Test
public void testSetFromGL() {
Projection projtmp = new Projection(fP2);
int[] glViewport = new int[] {(int)rand(-100.0, 100.0), (int)rand(-100.0, 100.0), (int)fsizeU2, (int)fsizeV2};
double[] glProjectionGlVec = new double[16];
double[] glModelviewGlVec = new double[16];
projtmp.computeGLMatrices(glViewport[0], glViewport[1], glViewport[2], glViewport[3], rand(100.0, 400.0), rand(800.0, 1200.0), glProjectionGlVec, glModelviewGlVec); // s is not transferred to the OpenGL representation
Projection proj = new Projection();
proj.initFromGL(glProjectionGlVec, glModelviewGlVec, glViewport);
assertEquals(proj.getS(), 1.0, DELTA); // s cannot be recovered since it's not been transferred to the OpenGL representation
assertEqualElementWise(proj.getK(), fK2, DELTA);
assertEqualElementWise(proj.getR(), fR2, DELTA);
assertEqualElementWise(proj.getT(), ft2, DELTA);
}
@Test
public void testSetSKRT() {
Projection proj = new Projection();
proj.initFromSKRT(fs1*additionalScaling, fK1, fR1, ft1);
assertEqualElementWise(proj.computeP(), fP1.multipliedBy(additionalScaling), DELTA);
proj.initFromSKRT(fs2*additionalScaling, fK2, fR2, ft2);
assertEqualElementWise(proj.computeP(), fP2.multipliedBy(additionalScaling), DELTA);
}
@Test
public void testSetS() {
Projection proj = new Projection(fP1);
proj.setSValue(fs2);
assertEquals(proj.getS(), fs2, DELTA);
assertEqualElementWise(proj.getK(), fK1, DELTA);
assertEqualElementWise(proj.getR(), fR1, DELTA);
assertEqualElementWise(proj.getT(), ft1, DELTA);
}
@Test(expected = IllegalArgumentException.class)
public void testSetSNonPositive() {
Projection proj = new Projection(fP1);
proj.setSValue(randNonPositive());
}
@Test
public void testSetK() {
Projection proj = new Projection(fP1);
proj.setKValue(fK2);
assertEquals(proj.getS(), fs1, DELTA);
assertEqualElementWise(proj.getK(), fK2, DELTA);
assertEqualElementWise(proj.getR(), fR1, DELTA);
assertEqualElementWise(proj.getT(), ft1, DELTA);
}
@Test(expected = IllegalArgumentException.class)
public void testSetKWrongSize() {
Projection proj = new Projection();
SimpleMatrix K_wrongsize = fK1.getSubMatrix(0, 0, 3, 2);
proj.setKValue(K_wrongsize);
}
@Test(expected = IllegalArgumentException.class)
public void testSetKNonTriangular10() {
Projection proj = new Projection();
SimpleMatrix K_nontriang = fK1.clone();
K_nontriang.setElementValue(1, 0, randNonZero());
proj.setKValue(K_nontriang);
}
@Test(expected = IllegalArgumentException.class)
public void testSetKNonTriangular20() {
Projection proj = new Projection();
SimpleMatrix K_nontriang = fK1.clone();
K_nontriang.setElementValue(2, 0, randNonZero());
proj.setKValue(K_nontriang);
}
@Test(expected = IllegalArgumentException.class)
public void testSetKNonTriangular21() {
Projection proj = new Projection();
SimpleMatrix K_nontriang = fK1.clone();
K_nontriang.setElementValue(2, 1, randNonZero());
proj.setKValue(K_nontriang);
}
@Test(expected = IllegalArgumentException.class)
public void testSetKWrongDiag0() {
Projection proj = new Projection();
SimpleMatrix K_wrongdiag = fK1.clone();
K_wrongdiag.setElementValue(0, 0, randNonPositive());
proj.setKValue(K_wrongdiag);
}
@Test(expected = IllegalArgumentException.class)
public void testSetKWrongDiag1() {
Projection proj = new Projection();
SimpleMatrix K_wrongdiag = fK1.clone();
K_wrongdiag.setElementValue(1, 1, randNonPositive());
proj.setKValue(K_wrongdiag);
}
@Test(expected = IllegalArgumentException.class)
public void testSetKWrongDiag2() {
Projection proj = new Projection();
SimpleMatrix K_wrongdiag = fK1.clone();
K_wrongdiag.setElementValue(2, 2, randNotPmOne());
proj.setKValue(K_wrongdiag);
}
@Test
public void testSetR() {
Projection proj = new Projection(fP1);
proj.setRValue(fR2);
assertEquals(proj.getS(), fs1, DELTA);
assertEqualElementWise(proj.getK(), fK1, DELTA);
assertEqualElementWise(proj.getR(), fR2, DELTA);
assertEqualElementWise(proj.getT(), ft1, DELTA);
}
@Test(expected = IllegalArgumentException.class)
public void testSetRWrongSize() {
Projection proj = new Projection();
SimpleMatrix R_wrongsize = fR1.getSubMatrix(0, 0, 3, 2);
proj.setRValue(R_wrongsize);
}
@Test(expected = IllegalArgumentException.class)
public void testSetRNonSOButO() {
Projection proj = new Projection();
SimpleMatrix R_nonSO = fR1.negated();
proj.setRValue(R_nonSO);
}
@Test
public void testSetT() {
Projection proj = new Projection(fP1);
proj.setTVector(ft2);
assertEquals(proj.getS(), fs1, DELTA);
assertEqualElementWise(proj.getK(), fK1, DELTA);
assertEqualElementWise(proj.getR(), fR1, DELTA);
assertEqualElementWise(proj.getT(), ft2, DELTA);
}
@Test(expected = IllegalArgumentException.class)
public void testSetTWrongSize() {
Projection proj = new Projection();
SimpleVector t_wrongsize = ft1.getSubVec(0, 2);
proj.setTVector(t_wrongsize);
}
@Test
public void testSetRt() {
Projection proj = new Projection(fP1);
proj.setRtValue(fRt2);
assertEquals(proj.getS(), fs1, DELTA);
assertEqualElementWise(proj.getK(), fK1, DELTA);
assertEqualElementWise(proj.getR(), fR2, DELTA);
assertEqualElementWise(proj.getT(), ft2, DELTA);
}
@Test(expected = IllegalArgumentException.class)
public void testSetRtNonSOButO() {
Projection proj = new Projection();
SimpleMatrix Rt_nonso = fRt1.clone();
Rt_nonso.setSubMatrixValue(0, 0, Rt_nonso.getSubMatrix(0, 0, 3, 3).negated());
proj.setRtValue(Rt_nonso);
}
@Test(expected = IllegalArgumentException.class)
public void testSetRtWrongLastRow0() {
Projection proj = new Projection();
SimpleMatrix Rt_wronglastrow = fRt1.clone();
Rt_wronglastrow.setElementValue(3, 0, randNonZero());
proj.setRtValue(Rt_wronglastrow);
}
@Test(expected = IllegalArgumentException.class)
public void testSetRtWrongLastRow1() {
Projection proj = new Projection();
SimpleMatrix Rt_wronglastrow = fRt1.clone();
Rt_wronglastrow.setElementValue(3, 1, randNonZero());
proj.setRtValue(Rt_wronglastrow);
}
@Test(expected = IllegalArgumentException.class)
public void testSetRtWrongLastRow2() {
Projection proj = new Projection();
SimpleMatrix Rt_wronglastrow = fRt1.clone();
Rt_wronglastrow.setElementValue(3, 2, randNonZero());
proj.setRtValue(Rt_wronglastrow);
}
@Test(expected = IllegalArgumentException.class)
public void testSetRtWrongLastRow3() {
Projection proj = new Projection();
SimpleMatrix Rt_wronglastrow = fRt1.clone();
Rt_wronglastrow.setElementValue(3, 3, randNonZero() + 1.0);
proj.setRtValue(Rt_wronglastrow);
}
@Test
public void testSetPrincipalPoint() {
Projection proj = new Projection(fP1);
proj.setPrincipalPointValue(fpp2);
assertEqualElementWise(proj.getPrincipalPoint(), fpp2, DELTA);
proj.setPrincipalPointValue(fpp1);
assertEquals(proj.getS(), fs1, DELTA);
assertEqualElementWise(proj.getK(), fK1, DELTA);
assertEqualElementWise(proj.getR(), fR1, DELTA);
assertEqualElementWise(proj.getT(), ft1, DELTA);
}
@Test(expected = IllegalArgumentException.class)
public void testSetPrincipalPointWrongSize() {
Projection proj = new Projection();
SimpleVector pp_wrongsize = fpp1.getSubVec(0, 1);
proj.setTVector(pp_wrongsize);
}
@Test
public void testSetViewingDirection() {
Projection proj = new Projection(fP1);
proj.setViewingDirectionValue(fdir2);
assertEquals(proj.getViewingDirection(), fdir2, DELTA);
proj.setViewingDirectionValue(fdir1);
assertEquals(proj.getS(), fs1, DELTA);
assertEqualElementWise(proj.getK(), fK1, DELTA);
assertEqualElementWise(proj.getR(), fR1, DELTA);
assertEqualElementWise(proj.getT(), ft1, DELTA);
}
@Test(expected = IllegalArgumentException.class)
public void testSetViewingDirectionNotPmOne() {
Projection proj = new Projection();
proj.setViewingDirectionValue(randNotPmOne());
}
@Test
public void testGetRt() {
Projection proj = new Projection();
proj.setRtValue(fRt1);
assertEqualElementWise(proj.getRt(), fRt1, DELTA);
}
@Test
public void testGetPrincipalPoint() {
Projection proj = new Projection();
proj.setPrincipalPointValue(fpp1);
assertEqualElementWise(proj.getPrincipalPoint(), fpp1, DELTA);
}
@Test
public void testGetViewingDirection() {
Projection proj = new Projection();
proj.setViewingDirectionValue(fdir1);
assertEquals(proj.getViewingDirection(), fdir1, DELTA);
}
@Test
public void testComputeP() {
Projection proj = new Projection();
proj.initFromSKRT(fs1, fK1, fR1, ft1);
assertEqualElementWise(proj.computeP(), fP1, DELTA);
}
@Test
public void testComputeCameraCenter() {
Projection proj = new Projection(fP1.clone());
SimpleVector C_hom = General.augmentToHomgeneous(proj.computeCameraCenter());
SimpleVector zero4 = new SimpleVector(3);
assertEqualElementWise(SimpleOperators.multiply(fP1, C_hom), zero4, DELTA);
}
@Test
public void testComputePrincipalAxis() {
Projection proj = new Projection(fP1.clone());
SimpleVector pa = proj.computePrincipalAxis();
SimpleVector C = proj.computeCameraCenter();
double lambda = randPositive();
assertTrue(
General.areColinear(
SimpleOperators.multiply(
fP1, General.augmentToHomgeneous(SimpleOperators.add(C, pa.multipliedBy(lambda)))
),
General.augmentToHomgeneous(fpp1),
100.0*DELTA
)
);
}
@Test
public void testComputeRayDirection() {
Projection proj = new Projection(fP1.clone());
SimpleVector pixel = new SimpleVector(rand(0.0, fsizeU1), rand(0.0, fsizeU2));
SimpleVector raydir = proj.computeRayDirection(pixel);
SimpleVector C = proj.computeCameraCenter();
SimpleVector X = SimpleOperators.add(C, raydir.multipliedBy(100.0 * randPositive()));
SimpleVector X_hom = General.augmentToHomgeneous(X);
SimpleVector lhs = SimpleOperators.multiply(fP1.clone(), X_hom).normalizedL2();
SimpleVector rhs = General.augmentToHomgeneous(pixel).normalizedL2();
assertEqualElementWise(lhs.normalizedL2(), rhs.normalizedL2(), DELTA);
}
@Test
public void testComputeGLMatricesIntIntIntIntDoubleDoubleDoubleArrayDoubleArray() {
Projection projtmp = new Projection(fP1);
int[] glViewport = new int[] {(int)rand(-100.0, 100.0), (int)rand(-100.0, 100.0), (int)fsizeU1, (int)fsizeV1};
double[] glProjectionGlVec = new double[16];
double[] glModelviewGlVec = new double[16];
projtmp.computeGLMatrices(glViewport[0], glViewport[1], glViewport[2], glViewport[3], rand(100.0, 400.0), rand(800.0, 1200.0), glProjectionGlVec, glModelviewGlVec); // s is not transferred to the OpenGL representation
Projection proj = new Projection(glProjectionGlVec, glModelviewGlVec, glViewport);
assertEquals(proj.getS(), 1.0, DELTA); // s cannot be recovered since it's not been transferred to the OpenGL representation
assertEqualElementWise(proj.getK(), fK1, DELTA);
assertEqualElementWise(proj.getR(), fR1, DELTA);
assertEqualElementWise(proj.getT(), ft1, DELTA);
}
@Test
public void testComputeGLMatricesIntIntIntIntAbstractVectorAbstractVectorDoubleArrayDoubleArray() {
Projection projtmp = new Projection(fP2);
int[] glViewport = new int[] {(int)rand(-100.0, 100.0), (int)rand(-100.0, 100.0), (int)fsizeU1, (int)fsizeV1};
double[] glProjectionGlVec = new double[16];
double[] glModelviewGlVec = new double[16];
SimpleVector cubmin = new SimpleVector(rand(-200.0, 0.0), rand(-200.0, 0.0), rand(-200.0, 0.0));
SimpleVector cubmax = new SimpleVector(rand(0.0, 200.0), rand(0.0, 200.0), rand(0.0, 200.0));
projtmp.computeGLMatrices(glViewport[0], glViewport[1], glViewport[2], glViewport[3], cubmin, cubmax, glProjectionGlVec, glModelviewGlVec); // s is not transferred to the OpenGL representation
Projection proj = new Projection(glProjectionGlVec, glModelviewGlVec, glViewport);
assertEquals(proj.getS(), 1.0, DELTA); // s cannot be recovered since it's not been transferred to the OpenGL representation
assertEqualElementWise(proj.getK(), fK2, DELTA);
assertEqualElementWise(proj.getR(), fR2, DELTA);
assertEqualElementWise(proj.getT(), ft2, DELTA);
}
@Test
public void testComputeDepth() {
Projection proj = new Projection(fP1);
SimpleVector C = proj.computeCameraCenter();
SimpleVector pa = proj.computePrincipalAxis();
double dist = fcameraToImage1 * randPositive();
SimpleVector v = SimpleOperators.add(C, pa.multipliedBy(dist));
assertEquals(proj.computeDepth(v), dist, DELTA);
v = SimpleOperators.add(C, pa.multipliedBy(-dist));
assertEquals(proj.computeDepth(v), -dist, DELTA);
}
@Test
public void testProject() {
// initialize projection and test variables
final Projection proj = new Projection(fP1);
final SimpleVector pixel = new SimpleVector(rand(0.0, fsizeU1), rand(0.0, fsizeV1));
final SimpleVector ray = proj.computeRayDirection(pixel);
// construct a visible and an invisible point
final SimpleVector C = proj.computeCameraCenter();
final SimpleVector Xvis = SimpleOperators.add(C, ray.multipliedBy(fcameraToImage1*randPositive()));
final SimpleVector Xnonvis = SimpleOperators.add(C, ray.multipliedBy(-fcameraToImage1*randPositive()));
// test projecting both, the visible and the invisible, points
final SimpleVector pixel_proj = new SimpleVector(2);
double depth;
depth = proj.project(Xvis, pixel_proj);
assertEqualElementWise(pixel_proj, pixel, DELTA);
assertTrue(depth > 0.0);
assertEquals(proj.project(Xvis, pixel_proj), proj.computeDepth(Xvis), DELTA);
depth = proj.project(Xnonvis, pixel_proj);
assertEqualElementWise(pixel_proj, pixel, DELTA);
assertTrue(depth < 0.0);
assertEquals(proj.project(Xnonvis, pixel_proj), proj.computeDepth(Xnonvis), DELTA);
}
@Test
public void testIntersectRayWithCuboid() {
Projection proj = new Projection(fP1);
final SimpleVector cubmin = new SimpleVector(rand(-200.0, 0.0), rand(-200.0, 0.0), rand(-200.0, 0.0));
final SimpleVector cubmax = new SimpleVector(rand(0.0, 200.0), rand(0.0, 200.0), rand(0.0, 200.0));
final SimpleVector p = new SimpleVector(rand(0.0, 1000.0), rand(0.0, 1000.0));
final double[] tntf = new double[2];
final SimpleVector C = new SimpleVector(3);
final SimpleVector d = new SimpleVector(3);
boolean cubeHit = proj.intersectRayWithCuboid(p, cubmin, cubmax, tntf, C, d);
if (cubeHit) {
final SimpleVector nearPoint = SimpleOperators.add(C, d.multipliedBy(tntf[0]));
final SimpleVector pixelNear = new SimpleVector(2);
double projectDepthNear = proj.project(nearPoint, pixelNear);
final SimpleVector farPoint = SimpleOperators.add(C, d.multipliedBy(tntf[1]));
final SimpleVector pixelFar = new SimpleVector(2);
double projectDepthFar = proj.project(farPoint, pixelFar);
assertEqualElementWise(p, pixelNear, DELTA);
assertEqualElementWise(p, pixelFar, DELTA);
assertEquals(tntf[0], projectDepthNear, DELTA);
assertEquals(tntf[1], projectDepthFar, DELTA);
assertTrue(tntf[1] > 0.0);
}
}
@Test
public void testSetKFromDistancesSpacingsSizeOffset() {
Projection proj = new Projection();
proj.setKFromDistancesSpacingsSizeOffset(fcameraToImage1, fspacing1, fsize1, foffset1, fdir1, fskew1);
assertEqualElementWise(proj.getK(), fK1, DELTA);
}
@Test(expected = IllegalArgumentException.class)
public void testSetKFromDistancesSpacingsSizeOffsetNonPosDist() {
Projection proj = new Projection();
proj.setKFromDistancesSpacingsSizeOffset(randNonPositive()*fcameraToImage1, fspacing1, fsize1, foffset1, fdir1, fskew1);
}
@Test(expected = IllegalArgumentException.class)
public void testSetKFromDistancesSpacingsSizeOffsetWrongSize1() {
Projection proj = new Projection();
proj.setKFromDistancesSpacingsSizeOffset(fcameraToImage1, new SimpleVector(3), fsize1, foffset1, fdir1, fskew1);
}
@Test(expected = IllegalArgumentException.class)
public void testSetKFromDistancesSpacingsSizeOffsetNonPosSpacingU() {
Projection proj = new Projection();
SimpleVector fspacing1_fail = fspacing1.clone();
fspacing1_fail.setElementValue(0, randNonPositive()*fspacing1.getElement(0));
proj.setKFromDistancesSpacingsSizeOffset(fcameraToImage1, fspacing1_fail, fsize1, foffset1, fdir1, fskew1);
}
@Test(expected = IllegalArgumentException.class)
public void testSetKFromDistancesSpacingsSizeOffsetNonPosSpacingV() {
Projection proj = new Projection();
SimpleVector fspacing1_fail = fspacing1.clone();
fspacing1_fail.setElementValue(1, randNonPositive()*fspacing1.getElement(1));
proj.setKFromDistancesSpacingsSizeOffset(fcameraToImage1, fspacing1_fail, fsize1, foffset1, fdir1, fskew1);
}
@Test(expected = IllegalArgumentException.class)
public void testSetKFromDistancesSpacingsSizeOffsetWrongSize2() {
Projection proj = new Projection();
proj.setKFromDistancesSpacingsSizeOffset(fcameraToImage1, fspacing1, new SimpleVector(3), foffset1, fdir1, fskew1);
}
@Test(expected = IllegalArgumentException.class)
public void testSetKFromDistancesSpacingsSizeOffsetWrongSize3() {
Projection proj = new Projection();
proj.setKFromDistancesSpacingsSizeOffset(fcameraToImage1, fspacing1, fsize1, new SimpleVector(3), fdir1, fskew1);
}
@Test(expected = IllegalArgumentException.class)
public void testSetKFromDistancesSpacingsSizeOffsetDirNotPmOne() {
Projection proj = new Projection();
proj.setKFromDistancesSpacingsSizeOffset(fcameraToImage1, fspacing1, fsize1, foffset1, randNotPmOne(), fskew1);
}
@Test
public void testSetRtFromCircularTrajectory1() {
// initialize parameters randomly
final SimpleVector rotationCenter = new SimpleVector(rand(-100.0, 100.0), rand(-100.0, 100.0), rand(-100.0, 100.0));
final SimpleVector rotationAxis = new SimpleVector(randNonZero(), randNonZero(), randNonZero());
final double sourceToAxisDistance = 100.0*randPositive();
// create centerToCameraAtZeroAngle vector and orthogonalize it w.r.t. the rotation axis
SimpleVector centerToCameraAtZeroAngle = new SimpleVector(rand(-100.0, 100.0), rand(-100.0, 100.0), rand(-100.0, 100.0));
SimpleVector rotationAxis_norm = rotationAxis.normalizedL2();
centerToCameraAtZeroAngle = SimpleOperators.subtract(centerToCameraAtZeroAngle, rotationAxis_norm.multipliedBy(SimpleOperators.multiplyInnerProd(centerToCameraAtZeroAngle, rotationAxis_norm)));
// initialize some more parameters randomly
// this axis definition yields a +z viewing direction
final CameraAxisDirection uDirection = CameraAxisDirection.DETECTORMOTION_PLUS;
final CameraAxisDirection vDirection = CameraAxisDirection.ROTATIONAXIS_PLUS;
final double rotationAngle = randAng();
// set up the projection
final Projection proj = new Projection();
final double dir = proj.setRtFromCircularTrajectory(rotationCenter, rotationAxis, sourceToAxisDistance, centerToCameraAtZeroAngle, uDirection, vDirection, rotationAngle);
proj.setKFromDistancesSpacingsSizeOffset(rand(1.5, 2.5)*sourceToAxisDistance, fspacing1, fsize1, foffset1, dir, fskew1);
// test projecting the center point
final SimpleVector pixel = new SimpleVector(2);
double depth = proj.project(rotationCenter, pixel);
assertEqualElementWise(pixel, fpp1, 10.0*DELTA);
assertTrue(depth > 0.0);
assertTrue(Math.abs(depth - sourceToAxisDistance) < DELTA);
// test projecting a point on the detector (at its current angulation)
SimpleVector v = centerToCameraAtZeroAngle.normalizedL2().negated().multipliedBy(sourceToAxisDistance);
SimpleMatrix rot = Rotations.createRotationMatrixAboutAxis(rotationAxis, rotationAngle);
v = SimpleOperators.add(SimpleOperators.multiply(rot, v), rotationCenter);
depth = proj.project(v, pixel);
assertEqualElementWise(pixel, fpp1, 10.0*DELTA);
assertTrue(depth > 0.0);
assertTrue(Math.abs(depth - 2.0*sourceToAxisDistance) < DELTA);
// test projecting a point behind the camera
v = centerToCameraAtZeroAngle.normalizedL2().multipliedBy(2.0*sourceToAxisDistance);
rot = Rotations.createRotationMatrixAboutAxis(rotationAxis, rotationAngle);
v = SimpleOperators.add(SimpleOperators.multiply(rot, v), rotationCenter);
depth = proj.project(v, pixel);
assertEqualElementWise(pixel, fpp1, 10.0*DELTA);
assertTrue(depth < 0.0);
assertTrue(Math.abs(depth + sourceToAxisDistance) < DELTA);
// test projecting a point next to the camera center, displaced in +u direction
final SimpleVector rotationAxisDirection = rotationAxis.normalizedL2();
final SimpleVector detectorMotionDirection = General.crossProduct(centerToCameraAtZeroAngle.normalizedL2(), rotationAxisDirection);
v = SimpleOperators.multiply(rot, detectorMotionDirection);
v.add(rotationCenter);
depth = proj.project(v, pixel);
assertTrue(depth > 0.0);
assertTrue(pixel.getElement(0) > fpp1.getElement(0));
assertTrue(Math.abs(pixel.getElement(1) - fpp1.getElement(1)) < DELTA);
}
@Test
public void testSetRtFromCircularTrajectory2() {
// initialize parameters randomly
final SimpleVector rotationCenter = new SimpleVector(rand(-100.0, 100.0), rand(-100.0, 100.0), rand(-100.0, 100.0));
final SimpleVector rotationAxis = new SimpleVector(randNonZero(), randNonZero(), randNonZero());
final double sourceToAxisDistance = 100.0*randPositive();
// create centerToCameraAtZeroAngle vector and orthogonalize it w.r.t. the rotation axis
SimpleVector centerToCameraAtZeroAngle = new SimpleVector(rand(-100.0, 100.0), rand(-100.0, 100.0), rand(-100.0, 100.0));
final SimpleVector rotationAxis_norm = rotationAxis.normalizedL2();
centerToCameraAtZeroAngle = SimpleOperators.subtract(centerToCameraAtZeroAngle, rotationAxis_norm.multipliedBy(SimpleOperators.multiplyInnerProd(centerToCameraAtZeroAngle, rotationAxis_norm)));
// initialize some more parameters randomly
// this axis definition yields a -z viewing direction
final double rotationAngle = randAng();
final CameraAxisDirection uDirection = CameraAxisDirection.ROTATIONAXIS_PLUS;
final CameraAxisDirection vDirection = CameraAxisDirection.DETECTORMOTION_PLUS;
// set up the projection
final Projection proj = new Projection();
final double dir = proj.setRtFromCircularTrajectory(rotationCenter, rotationAxis, sourceToAxisDistance, centerToCameraAtZeroAngle, uDirection, vDirection, rotationAngle);
proj.setKFromDistancesSpacingsSizeOffset(rand(1.5, 2.5)*sourceToAxisDistance, fspacing2, fsize2, foffset2, dir, fskew2);
// test projecting the center point
final SimpleVector pixel = new SimpleVector(2);
double depth = proj.project(rotationCenter, pixel);
assertEqualElementWise(pixel, fpp2, 10.0*DELTA);
assertTrue(depth > 0.0);
assertTrue(Math.abs(depth - sourceToAxisDistance) < DELTA);
// test projecting a point on the detector (at its current angulation)
SimpleVector v = centerToCameraAtZeroAngle.normalizedL2().negated().multipliedBy(sourceToAxisDistance);
SimpleMatrix rot = Rotations.createRotationMatrixAboutAxis(rotationAxis, rotationAngle);
v = SimpleOperators.add(SimpleOperators.multiply(rot, v), rotationCenter);
depth = proj.project(v, pixel);
assertEqualElementWise(pixel, fpp2, 10.0*DELTA);
assertTrue(depth > 0.0);
assertTrue(Math.abs(depth - 2.0*sourceToAxisDistance) < DELTA);
// test projecting a point behind the camera
v = centerToCameraAtZeroAngle.normalizedL2().multipliedBy(2.0*sourceToAxisDistance);
rot = Rotations.createRotationMatrixAboutAxis(rotationAxis, rotationAngle);
v = SimpleOperators.add(SimpleOperators.multiply(rot, v), rotationCenter);
depth = proj.project(v, pixel);
assertEqualElementWise(pixel, fpp2, 10.0*DELTA);
assertTrue(depth < 0.0);
assertTrue(Math.abs(depth + sourceToAxisDistance) < DELTA);
// test projecting a point next to the camera center, displaced in +u direction
final SimpleVector rotationAxisDirection = rotationAxis.normalizedL2();
v = SimpleOperators.multiply(rot, rotationAxisDirection);
v.add(rotationCenter);
depth = proj.project(v, pixel);
assertTrue(depth > 0.0);
assertTrue(pixel.getElement(0) > fpp2.getElement(0));
assertTrue(Math.abs(pixel.getElement(1) - fpp2.getElement(1)) < DELTA);
}
@Test(expected = IllegalArgumentException.class)
public void testSetRtFromCircularTrajectoryRotationAxisNull() {
Projection proj = new Projection();
SimpleVector rotationCenter = new SimpleVector(0.0, 0.0, 0.0);
SimpleVector rotationAxis = new SimpleVector(0.0, 0.0, 0.0);
double sourceToAxisDistance = rand(300.0, 700.0);
SimpleVector centerToCameraAtZeroAngle = new SimpleVector(0.0, 0.0, 500.0);
CameraAxisDirection uDirection = CameraAxisDirection.DETECTORMOTION_MINUS;
CameraAxisDirection vDirection = CameraAxisDirection.ROTATIONAXIS_MINUS;
double rotationAngle = 0.0;
proj.setRtFromCircularTrajectory(rotationCenter, rotationAxis, sourceToAxisDistance, centerToCameraAtZeroAngle, uDirection, vDirection, rotationAngle);
}
@Test(expected = IllegalArgumentException.class)
public void testSetRtFromCircularTrajectoryNonPosRadius() {
Projection proj = new Projection();
SimpleVector rotationCenter = new SimpleVector(0.0, 0.0, 0.0);
SimpleVector rotationAxis = new SimpleVector(1.0, 0.0, 0.0);
double sourceToAxisDistance = 500.0*randNonPositive();
SimpleVector centerToCameraAtZeroAngle = new SimpleVector(0.0, 0.0, 500.0);
CameraAxisDirection uDirection = CameraAxisDirection.DETECTORMOTION_MINUS;
CameraAxisDirection vDirection = CameraAxisDirection.ROTATIONAXIS_MINUS;
double rotationAngle = 0.0;
proj.setRtFromCircularTrajectory(rotationCenter, rotationAxis, sourceToAxisDistance, centerToCameraAtZeroAngle, uDirection, vDirection, rotationAngle);
}
@Test(expected = IllegalArgumentException.class)
public void testSetRtFromCircularTrajectoryCenterToCameraAtZeroAngleNull() {
Projection proj = new Projection();
SimpleVector rotationCenter = new SimpleVector(0.0, 0.0, 0.0);
SimpleVector rotationAxis = new SimpleVector(1.0, 0.0, 0.0);
double sourceToAxisDistance = rand(300.0, 700.0);
SimpleVector centerToCameraAtZeroAngle = new SimpleVector(0.0, 0.0, 0.0);
CameraAxisDirection uDirection = CameraAxisDirection.DETECTORMOTION_MINUS;
CameraAxisDirection vDirection = CameraAxisDirection.ROTATIONAXIS_MINUS;
double rotationAngle = 0.0;
proj.setRtFromCircularTrajectory(rotationCenter, rotationAxis, sourceToAxisDistance, centerToCameraAtZeroAngle, uDirection, vDirection, rotationAngle);
}
@Test(expected = IllegalArgumentException.class)
public void testSetRtFromCircularTrajectoryUVDirection1() {
Projection proj = new Projection();
SimpleVector rotationCenter = new SimpleVector(0.0, 0.0, 0.0);
SimpleVector rotationAxis = new SimpleVector(1.0, 0.0, 0.0);
double sourceToAxisDistance = rand(300.0, 700.0);
SimpleVector centerToCameraAtZeroAngle = new SimpleVector(0.0, 0.0, 500.0);
CameraAxisDirection uDirection = CameraAxisDirection.DETECTORMOTION_MINUS;
CameraAxisDirection vDirection = CameraAxisDirection.DETECTORMOTION_PLUS;
double rotationAngle = 0.0;
proj.setRtFromCircularTrajectory(rotationCenter, rotationAxis, sourceToAxisDistance, centerToCameraAtZeroAngle, uDirection, vDirection, rotationAngle);
}
@Test(expected = IllegalArgumentException.class)
public void testSetRtFromCircularTrajectoryUVDirection2() {
Projection proj = new Projection();
SimpleVector rotationCenter = new SimpleVector(0.0, 0.0, 0.0);
SimpleVector rotationAxis = new SimpleVector(1.0, 0.0, 0.0);
double sourceToAxisDistance = rand(300.0, 700.0);
SimpleVector centerToCameraAtZeroAngle = new SimpleVector(0.0, 0.0, 500.0);
CameraAxisDirection uDirection = CameraAxisDirection.ROTATIONAXIS_PLUS;
CameraAxisDirection vDirection = CameraAxisDirection.ROTATIONAXIS_MINUS;
double rotationAngle = 0.0;
proj.setRtFromCircularTrajectory(rotationCenter, rotationAxis, sourceToAxisDistance, centerToCameraAtZeroAngle, uDirection, vDirection, rotationAngle);
}
@Test
public void testComputeSourceToDetectorDistance() {
Projection proj = new Projection();
proj.setKFromDistancesSpacingsSizeOffset(fcameraToImage1, fspacing1, fsize1, foffset1, fdir1, fskew1);
double[] dist = proj.computeSourceToDetectorDistance(fspacing1);
assertEquals(dist[0], fcameraToImage1, DELTA);
assertEquals(dist[1], fcameraToImage1, DELTA);
}
@Test
public void testComputeOffset() {
Projection proj = new Projection();
proj.setKFromDistancesSpacingsSizeOffset(fcameraToImage1, fspacing1, fsize1, foffset1, fdir1, fskew1);
SimpleVector offset = proj.computeOffset(fsize1);
assertEqualElementWise(offset, foffset1, DELTA);
}
}
/*
* Copyright (C) 2010-2014 Andreas Maier
* CONRAD is developed as an Open Source project under the GNU General Public License (GPL).
*/