/* * 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.app.calib; import boofcv.alg.geo.calibration.CalibrationObservation; import boofcv.alg.geo.calibration.Zhang99CalibrationMatrixFromHomographies; import boofcv.alg.geo.calibration.Zhang99ComputeTargetHomography; import georegression.struct.point.Point2D_F64; import org.ejml.data.DenseMatrix64F; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * Estimates if there is enough geometry diversity to compute an initial estimate of the camera calibration parameters * by computing a linear estimate and looking at its singular values. There should only be one null space. * * @author Peter Abeles */ public class ComputeGeometryScore { Zhang99ComputeTargetHomography computeHomography; Zhang99CalibrationMatrixFromHomographies computeCalib; List<DenseMatrix64F> homographies = new ArrayList<>(); double score = 0; public ComputeGeometryScore(boolean assumeZeroSkew, List<Point2D_F64> worldPoints) { computeCalib = new Zhang99CalibrationMatrixFromHomographies(assumeZeroSkew); computeHomography = new Zhang99ComputeTargetHomography(worldPoints); } public void addObservations( CalibrationObservation observations ) { computeHomography.computeHomography(observations); homographies.add( computeHomography.getHomography().copy() ); try { computeCalib.process(homographies); double values[] = computeCalib.getSvd().getSingularValues(); Arrays.sort(values,0,3); System.out.println("raw singularity score = "+(values[1]/values[2])); // 0.2 was a threshold that was emperically determined score = Math.min(1.0,(values[1]/values[2])/0.2 ); } catch( RuntimeException e ) { score = 0; } } /** * A number from 0 to 1.0 for how close to having the correct geometry it is. 1.0 = done */ public double getScore() { return score; } }