package photogrammetry.util; import java.util.Arrays; import java.util.List; import photogrammetry.util.model.HasCoordinates2d; import Jama.Matrix; /** * Class with methods for triangulation according to * http://www.comp.nus.edu.sg/~cs4243/lecture/multiview.pdf p. 33-35. * * @author johannes */ public class Triangulator { /** * Perform triangulation according to * http://www.comp.nus.edu.sg/~cs4243/lecture/multiview.pdf p. 33-35. * * @param intr the camera matrix * @param r the rotation matrices (3x3) * @param c the camera center points (3x1) * @param x the image coordinates (3x1), (xt, yt, 1)T * @return the triangulated 3d coordinate. */ public static Matrix triangulate(Matrix intr, List<Matrix> r, List<Matrix> c, List<Matrix> x) { Matrix intrInv = intr.inverse(); Matrix mtmSum = new Matrix(3, 3); Matrix mtmcSum = new Matrix(3, 1); Matrix id = Matrix.identity(3, 3); for (int k = 0; k < r.size(); k++) { Matrix xk = x.get(k); Matrix vk = r.get(k).inverse().times(intrInv).times(xk); vk = vk.times(1 / vk.normF()); Matrix mk = id.minus(vk.times(vk.transpose())); Matrix mktmk = mk.transpose().times(mk); mtmSum = mtmSum.plus(mktmk); mtmcSum = mtmcSum.plus(mktmk.times(c.get(k))); } return mtmSum.inverse().times(mtmcSum); } /** * Helper function for using * {@link Triangulator#triangulate(Matrix, List, List, List)} with just two * views and one point, where the first view's translation is 0, its * rotation matrix is I. * * @param c the camera to use for undistorting * @param r2 the second camera's rotation * @param c2 the second camera's center * @param x1 the coordinate of the feature in the first camera's image * @param x2 the coordinate of the feature in the second camera's image * @return the triangulated 3d coordinate. */ public static Matrix triangulate(Camera c, Matrix r2, Matrix c2, HasCoordinates2d x1, HasCoordinates2d x2) { HasCoordinates2d x1U = c.undistort(x1); HasCoordinates2d x2U = c.undistort(x2); return triangulate(c.getIntrinsics(), Arrays.asList(Matrix.identity(3, 3), r2), Arrays.asList(new Matrix(3, 1), c2), Arrays.asList(new Matrix(new double[]{x1U.getX(), x1U.getY(), 1}, 3), new Matrix(new double[]{x2U.getX(), x2U.getY(), 1}, 3))); } }