/*
* 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.feature.associate;
import boofcv.abst.feature.associate.ScoreAssociateEuclidean_F64;
import boofcv.alg.sfm.SfmTestHelper;
import boofcv.struct.calib.CameraPinholeRadial;
import boofcv.struct.calib.StereoParameters;
import boofcv.struct.feature.AssociatedIndex;
import boofcv.struct.feature.TupleDesc_F64;
import georegression.geometry.ConvertRotation3D_F64;
import georegression.struct.EulerType;
import georegression.struct.point.Point2D_F64;
import georegression.struct.point.Point3D_F64;
import georegression.struct.se.Se3_F64;
import org.ddogleg.struct.FastQueue;
import org.ejml.ops.CommonOps;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
/**
* @author Peter Abeles
*/
public class TestAssociateStereo2D {
Se3_F64 leftToRight;
StereoParameters param;
Point2D_F64 leftP = new Point2D_F64();
Point2D_F64 rightP = new Point2D_F64();
FastQueue<Point2D_F64> pointsLeft = new FastQueue<>(Point2D_F64.class, true);
FastQueue<Point2D_F64> pointsRight = new FastQueue<>(Point2D_F64.class, true);
FastQueue<TupleDesc_F64> descLeft,descRight;
ScoreAssociateEuclidean_F64 scorer = new ScoreAssociateEuclidean_F64();
@Before
public void setup() {
leftToRight = new Se3_F64();
ConvertRotation3D_F64.eulerToMatrix(EulerType.XYZ,0.01, -0.001, 0.005, leftToRight.getR());
leftToRight.getT().set(-0.1,0,0);
param = new StereoParameters();
param.rightToLeft = leftToRight.invert(null);
param.left = new CameraPinholeRadial(400,500,0.1,160,120,320,240).fsetRadial(0,0);
param.right = new CameraPinholeRadial(380,505,0.05,165,115,320,240).fsetRadial(0,0);
descLeft = new FastQueue<TupleDesc_F64>(TupleDesc_F64.class,true) {
@Override
protected TupleDesc_F64 createInstance() {
return new TupleDesc_F64(10);
}
};
descRight = new FastQueue<TupleDesc_F64>(TupleDesc_F64.class,true) {
@Override
protected TupleDesc_F64 createInstance() {
return new TupleDesc_F64(10);
}
};
pointsLeft.reset();
pointsRight.reset();
}
/**
* Very simple positive case with only a perfect observation and descriptor
*/
@Test
public void positive() {
Point3D_F64 X = new Point3D_F64(0.02,-0.5,3);
SfmTestHelper.renderPointPixel(param, X, leftP, rightP);
pointsLeft.grow().set(leftP);
pointsRight.grow().set(rightP);
descLeft.grow();descRight.grow();
AssociateStereo2D<TupleDesc_F64> alg = new AssociateStereo2D<>(scorer, 0.5, TupleDesc_F64.class);
alg.setCalibration(param);
alg.setSource(pointsLeft,descLeft);
alg.setDestination(pointsRight, descRight);
alg.associate();
FastQueue<AssociatedIndex> matches = alg.getMatches();
assertEquals(1, matches.size);
}
/**
* Makes the observation in the left image > right image along x-axis
*/
@Test
public void constraintX() {
// zap the rotation so that no adjustment should need to be done
CommonOps.setIdentity(param.rightToLeft.getR());
Point3D_F64 X = new Point3D_F64(0.02,-0.5,3);
SfmTestHelper.renderPointPixel(param,X,leftP,rightP);
// mangle the x-axis
leftP.x = rightP.x - 0.25;
pointsLeft.grow().set(leftP);
pointsRight.grow().set(rightP);
descLeft.grow();descRight.grow();
AssociateStereo2D<TupleDesc_F64> alg = new AssociateStereo2D<>(scorer, 0.5, TupleDesc_F64.class);
alg.setCalibration(param);
alg.setSource(pointsLeft,descLeft);
alg.setDestination(pointsRight, descRight);
alg.associate();
// at the current tolerance they should still match
assertEquals(1,alg.getMatches().size);
// make the tolerance tighter
alg = new AssociateStereo2D<>(scorer, 0.01, TupleDesc_F64.class);
alg.setCalibration(param);
alg.setSource(pointsLeft,descLeft);
alg.setDestination(pointsRight, descRight);
alg.associate();
assertEquals(0,alg.getMatches().size);
}
/**
* Makes sure observations have the same y-axis
*/
@Test
public void constraintY() {
// zap the rotation so that no adjustment should need to be done
Point3D_F64 X = new Point3D_F64(0.02,-0.5,3);
SfmTestHelper.renderPointPixel(param,X,leftP,rightP);
// mangle the y-axis
leftP.y += 0.25;
pointsLeft.grow().set(leftP);
pointsRight.grow().set(rightP);
descLeft.grow();descRight.grow();
AssociateStereo2D<TupleDesc_F64> alg = new AssociateStereo2D<>(scorer, 0.5, TupleDesc_F64.class);
alg.setCalibration(param);
alg.setSource(pointsLeft,descLeft);
alg.setDestination(pointsRight, descRight);
alg.associate();
// at the current tolerance they should still match
assertEquals(1,alg.getMatches().size);
// make the tolerance tighter
alg = new AssociateStereo2D<>(scorer, 0.01, TupleDesc_F64.class);
alg.setCalibration(param);
alg.setSource(pointsLeft,descLeft);
alg.setDestination(pointsRight, descRight);
alg.associate();
assertEquals(0,alg.getMatches().size);
}
}