/* * Copyright (c) 2011-2016, Peter Abeles. All Rights Reserved. * * This file is part of BoofCV (http://boofcv.org). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package boofcv.alg.distort; import boofcv.alg.distort.pinhole.LensDistortionPinhole; import boofcv.alg.distort.universal.LensDistortionUniversalOmni; import boofcv.struct.calib.CameraPinhole; import boofcv.struct.calib.CameraUniversalOmni; import boofcv.struct.distort.Point2Transform3_F32; import georegression.geometry.ConvertRotation3D_F32; import georegression.geometry.UtilVector3D_F32; import georegression.misc.GrlConstants; import georegression.struct.EulerType; import georegression.struct.point.Point2D_F32; import georegression.struct.point.Point3D_F32; import georegression.struct.point.Vector3D_F32; import org.ejml.data.DenseMatrix64F; import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; /** * @author Peter Abeles */ public class TestNarrowToWidePtoP_F32 { /** * With no translation request a point in the center. Should appear to be in the center in both views. */ @Test public void centerIsCenter() { NarrowToWidePtoP_F32 alg = createAlg(); Point2D_F32 found = new Point2D_F32(); alg.compute(250,250,found); assertEquals(480,found.x, GrlConstants.FLOAT_TEST_TOL_SQRT); assertEquals(480,found.y, GrlConstants.FLOAT_TEST_TOL_SQRT); } /** * Rotate the camera and see if the point moves in the expected way */ @Test public void rotateCamera() { NarrowToWidePtoP_F32 alg = createAlg(); Point2D_F32 found = new Point2D_F32(); DenseMatrix64F R = ConvertRotation3D_F32.eulerToMatrix(EulerType.YXZ,0.1f,0,0,null); alg.setRotationWideToNarrow(R); alg.compute(250,250,found); assertTrue(480<found.x - 5); R = ConvertRotation3D_F32.eulerToMatrix(EulerType.YXZ,-0.1f,0,0,null); alg.setRotationWideToNarrow(R); alg.compute(250,250,found); assertTrue(480>found.x + 5); R = ConvertRotation3D_F32.eulerToMatrix(EulerType.YXZ,0,-0.1f,0,null); alg.setRotationWideToNarrow(R); alg.compute(250,250,found); assertTrue(480<found.y - 5); R = ConvertRotation3D_F32.eulerToMatrix(EulerType.YXZ,0,0.1f,0,null); alg.setRotationWideToNarrow(R); alg.compute(250,250,found); assertTrue(480>found.y + 5); } /** * Request points at the border and see if it has the expected vertical and horizontal FOV */ @Test public void checkFOVBounds() { NarrowToWidePtoP_F32 alg = createAlg(); Point2D_F32 foundA = new Point2D_F32(); Point2D_F32 foundB = new Point2D_F32(); Point3D_F32 vA = new Point3D_F32(); Point3D_F32 vB = new Point3D_F32(); // Compute the horizontal FOV alg.compute(0,250,foundA); alg.compute(500,250,foundB); Point2Transform3_F32 wideToSphere = createModelWide().undistortPtoS_F32(); wideToSphere.compute(foundA.x,foundA.y,vA); wideToSphere.compute(foundB.x,foundB.y,vB); float found = UtilVector3D_F32.acute(new Vector3D_F32(vA),new Vector3D_F32(vB)); float expected = 2.0f * (float)Math.atan(250.0f/400.0f); assertEquals(expected,found,0.01f); // Compute the vertical FOV alg.compute(250,0,foundA); alg.compute(250,500,foundB); wideToSphere.compute(foundA.x,foundA.y,vA); wideToSphere.compute(foundB.x,foundB.y,vB); found = UtilVector3D_F32.acute(new Vector3D_F32(vA),new Vector3D_F32(vB)); expected = 2.0f * (float)Math.atan(250.0f/400.0f); assertEquals(expected,found,0.001f); } public static NarrowToWidePtoP_F32 createAlg() { return new NarrowToWidePtoP_F32(createModelNarrow(), createModelWide()); } public static LensDistortionWideFOV createModelWide() { CameraUniversalOmni model = new CameraUniversalOmni(2); model.fsetK(1.349e3f,1.343e3f,0,480,480,960,1080); model.fsetMirror(3.61f); model.fsetRadial(7.308e-1f,1.855e1f); model.fsetTangental(-1.288e-2f,-1.1342e-2f); return new LensDistortionUniversalOmni(model); } public static LensDistortionNarrowFOV createModelNarrow() { CameraPinhole model = new CameraPinhole(); model.fsetK(400,400,0,250,250,500,500); return new LensDistortionPinhole(model); } }