1 /**
2 * Copyright (c) 2011, The University of Southampton and the individual contributors.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * * Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * * Neither the name of the University of Southampton nor the names of its
16 * contributors may be used to endorse or promote products derived from this
17 * software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30 package org.openimaj.image.camera;
31
32 import org.openimaj.math.geometry.point.Point2d;
33 import org.openimaj.math.geometry.point.Point2dImpl;
34 import org.openimaj.math.geometry.point.Point3d;
35 import org.openimaj.math.matrix.MatrixUtils;
36
37 import Jama.Matrix;
38
39 /**
40 * A model of the extrinsic parameters of a pinhole (projective) camera
41 * (translation in 3d space, and 3d rotation matrix), coupled with the camera's
42 * intrinsic parameters.
43 *
44 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
45 */
46 public class Camera {
47 /**
48 * The intrinsic parameters of this camera
49 */
50 public CameraIntrinsics intrinsicParameters;
51
52 /**
53 * The rotation of this camera in world coordinates
54 */
55 public Matrix rotation;
56
57 /**
58 * The position of this camera in world coordinates
59 */
60 public Point3d translation;
61
62 /**
63 * Compute the homography of this camera to the z=0 plane based on it's
64 * parameters: H = KA, where A = [r1 r2 t] and r1 and r2 are the first and
65 * second columns of the rotation matrix, and K is the calibration matrix.
66 *
67 * @return the camera's homography
68 */
69 public Matrix computeHomography() {
70 final Matrix A = rotation.copy();
71 A.set(0, 2, translation.getX());
72 A.set(1, 2, translation.getY());
73 A.set(2, 2, translation.getZ());
74
75 final Matrix H = intrinsicParameters.calibrationMatrix.times(A);
76 MatrixUtils.times(H, 1.0 / H.get(2, 2));
77
78 return H;
79 }
80
81 /**
82 * Project a 2d point (technically a 3d point on the z=0 world plane)
83 *
84 * @param pt
85 * the point to project in world coordinates
86 * @return the image coordinates
87 */
88 public Point2d project(Point2d pt) {
89 final Matrix H = this.computeHomography();
90
91 final Point2d p = pt.transform(H);
92
93 return intrinsicParameters.applyDistortion(p);
94 }
95
96 /**
97 * Project a 3d point onto the image plane
98 *
99 * @param pt
100 * the point to project in world coordinates
101 * @return the image coordinates
102 */
103 public Point2d project(Point3d pt) {
104 final Matrix ptm = new Matrix(new double[][] { { pt.getX() }, { pt.getY() }, { pt.getZ() }, { 1 } });
105 final double[][] rv = rotation.getArray();
106 final Matrix Rt = new Matrix(new double[][] {
107 { rv[0][0], rv[0][1], rv[0][2], translation.getX() },
108 { rv[1][0], rv[1][1], rv[1][2], translation.getY() },
109 { rv[2][0], rv[2][1], rv[2][2], translation.getZ() },
110 });
111 final Matrix ARt = intrinsicParameters.calibrationMatrix.times(Rt);
112
113 final Matrix pr = ARt.times(ptm);
114
115 final Point2dImpl p = new Point2dImpl(pr.get(0, 0) / pr.get(2, 0), pr.get(1, 0) / pr.get(2, 0));
116
117 return intrinsicParameters.applyDistortion(p);
118 }
119 }