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). */