InitialCamerasEstimator.java
/*
* Copyright (C) 2017 Alberto Irurueta Carro (alberto@irurueta.com)
*
* 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 com.irurueta.ar.sfm;
import com.irurueta.ar.epipolar.FundamentalMatrix;
import com.irurueta.geometry.PinholeCamera;
import com.irurueta.geometry.estimators.LockedException;
import com.irurueta.geometry.estimators.NotReadyException;
/**
* Estimates initial cameras to initialize geometry in a metric stratum.
* This class uses provided fundamental matrix in order to obtain a pair of
* cameras and upgrade such cameras into a metric stratum.
* This class assumes that principal point of intrinsic camera parameters are
* located at the origin of coordinates, and also that skewness of such
* intrinsic parameters is zero.
* This class can upgrade cameras to a metric stratum by either estimating the
* Dual Absolute Quadric and its corresponding projective to metric
* transformation, or by solving the Kruppa equations to estimate the Dual
* Image of Absolute Conic to determine intrinsic parameters and then compute
* the essential matrix and use 2D point matches to triangulate them and find
* the initial cameras.
*/
@SuppressWarnings("DuplicatedCode")
public abstract class InitialCamerasEstimator {
/**
* Default method.
*/
public static final InitialCamerasEstimatorMethod DEFAULT_METHOD =
InitialCamerasEstimatorMethod.DUAL_ABSOLUTE_QUADRIC;
/**
* Fundamental matrix relating two views whose cameras need to be estimated.
*/
protected FundamentalMatrix fundamentalMatrix;
/**
* Indicates if this estimator is locked or not.
*/
protected boolean locked;
/**
* Estimated camera for left view.
*/
protected PinholeCamera estimatedLeftCamera;
/**
* Estimated camera for right view.
*/
protected PinholeCamera estimatedRightCamera;
/**
* Listener to handle events raised by this instance.
*/
protected InitialCamerasEstimatorListener listener;
/**
* Constructor.
*/
protected InitialCamerasEstimator() {
}
/**
* Constructor.
*
* @param fundamentalMatrix fundamental matrix relating two views.
*/
protected InitialCamerasEstimator(final FundamentalMatrix fundamentalMatrix) {
this.fundamentalMatrix = fundamentalMatrix;
}
/**
* Constructor.
*
* @param listener listener to handle events raised by this instance.
*/
protected InitialCamerasEstimator(final InitialCamerasEstimatorListener listener) {
this.listener = listener;
}
/**
* Constructor.
*
* @param fundamentalMatrix fundamental matrix relating two views.
* @param listener listener to handle events raised by this instance.
*/
protected InitialCamerasEstimator(final FundamentalMatrix fundamentalMatrix,
final InitialCamerasEstimatorListener listener) {
this.fundamentalMatrix = fundamentalMatrix;
this.listener = listener;
}
/**
* Gets fundamental matrix relating two views whose cameras need to be
* estimated.
*
* @return fundamental matrix relating two views.
*/
public FundamentalMatrix getFundamentalMatrix() {
return fundamentalMatrix;
}
/**
* Sets fundamental matrix relating two views whose cameras need to be
* estimated.
*
* @param fundamentalMatrix fundamental matrix relating two views.
* @throws LockedException if estimator is locked.
*/
public void setFundamentalMatrix(final FundamentalMatrix fundamentalMatrix) throws LockedException {
if (isLocked()) {
throw new LockedException();
}
this.fundamentalMatrix = fundamentalMatrix;
}
/**
* Gets listener to handle events raised by this instance.
*
* @return listener to handle events raised by this instance.
*/
public InitialCamerasEstimatorListener getListener() {
return listener;
}
/**
* Sets listener to handle events raised by this instance.
*
* @param listener listener to handle events raised by this instance.
*/
public void setListener(final InitialCamerasEstimatorListener listener) {
this.listener = listener;
}
/**
* Indicates if this estimator is locked or not.
*
* @return true if this estimator is locked, false otherwise.
*/
public boolean isLocked() {
return locked;
}
/**
* Gets estimated camera for left view.
*
* @return estimated camera for left view.
*/
public PinholeCamera getEstimatedLeftCamera() {
return estimatedLeftCamera;
}
/**
* Gets estimated camera for right view.
*
* @return estimated camera for right view.
*/
public PinholeCamera getEstimatedRightCamera() {
return estimatedRightCamera;
}
/**
* Returns method used by this estimator.
*
* @return method used by this estimator.
*/
public abstract InitialCamerasEstimatorMethod getMethod();
/**
* Indicates if estimator is ready.
*
* @return true if estimator is ready, false otherwise.
*/
public abstract boolean isReady();
/**
* Estimates cameras.
*
* @throws LockedException if estimator is locked.
* @throws NotReadyException if estimator is not ready.
* @throws InitialCamerasEstimationFailedException if estimation of cameras
* fails for some reason, typically due to numerical
* instabilities.
*/
public abstract void estimate() throws LockedException, NotReadyException, InitialCamerasEstimationFailedException;
/**
* Creates an instance of an initial cameras estimator using provided
* method.
*
* @param method method to estimate initial cameras.
* @return an estimator.
*/
public static InitialCamerasEstimator create(final InitialCamerasEstimatorMethod method) {
return switch (method) {
case ESSENTIAL_MATRIX -> new EssentialMatrixInitialCamerasEstimator();
case DUAL_IMAGE_OF_ABSOLUTE_CONIC -> new DualImageOfAbsoluteConicInitialCamerasEstimator();
default -> new DualAbsoluteQuadricInitialCamerasEstimator();
};
}
/**
* Creates an instance of an initial cameras estimator using provided
* fundamental matrix and provided method.
*
* @param fundamentalMatrix fundamental matrix relating two views.
* @param method method to estimate initial cameras.
* @return an estimator.
*/
public static InitialCamerasEstimator create(
final FundamentalMatrix fundamentalMatrix, final InitialCamerasEstimatorMethod method) {
return switch (method) {
case ESSENTIAL_MATRIX -> new EssentialMatrixInitialCamerasEstimator(fundamentalMatrix);
case DUAL_IMAGE_OF_ABSOLUTE_CONIC -> new DualImageOfAbsoluteConicInitialCamerasEstimator(fundamentalMatrix);
default -> new DualAbsoluteQuadricInitialCamerasEstimator(fundamentalMatrix);
};
}
/**
* Creates an instance of an initial cameras estimator using provided
* listener and method.
*
* @param listener listener to handle events.
* @param method method to estimate initial cameras.
* @return an estimator.
*/
public static InitialCamerasEstimator create(
final InitialCamerasEstimatorListener listener, final InitialCamerasEstimatorMethod method) {
return switch (method) {
case ESSENTIAL_MATRIX -> new EssentialMatrixInitialCamerasEstimator(listener);
case DUAL_IMAGE_OF_ABSOLUTE_CONIC -> new DualImageOfAbsoluteConicInitialCamerasEstimator(listener);
default -> new DualAbsoluteQuadricInitialCamerasEstimator(listener);
};
}
/**
* Creates an instance of an initial cameras estimator using provided
* fundamental matrix, listener and method.
*
* @param fundamentalMatrix fundamental matrix relating two views.
* @param listener listener to handle events.
* @param method method to estimate initial cameras.
* @return an estimator.
*/
public static InitialCamerasEstimator create(
final FundamentalMatrix fundamentalMatrix,
final InitialCamerasEstimatorListener listener,
final InitialCamerasEstimatorMethod method) {
return switch (method) {
case ESSENTIAL_MATRIX -> new EssentialMatrixInitialCamerasEstimator(fundamentalMatrix, listener);
case DUAL_IMAGE_OF_ABSOLUTE_CONIC -> new DualImageOfAbsoluteConicInitialCamerasEstimator(
fundamentalMatrix, listener);
default -> new DualAbsoluteQuadricInitialCamerasEstimator(fundamentalMatrix, listener);
};
}
/**
* Creates an instance of an initial cameras estimator using provided
* method.
*
* @return an estimator.
*/
public static InitialCamerasEstimator create() {
return create(DEFAULT_METHOD);
}
/**
* Creates an instance of an initial cameras estimator using provided
* fundamental matrix and provided method.
*
* @param fundamentalMatrix fundamental matrix relating two views.
* @return an estimator.
*/
public static InitialCamerasEstimator create(final FundamentalMatrix fundamentalMatrix) {
return create(fundamentalMatrix, DEFAULT_METHOD);
}
/**
* Creates an instance of an initial cameras estimator using provided
* listener and method.
*
* @param listener listener to handle events.
* @return an estimator.
*/
public static InitialCamerasEstimator create(final InitialCamerasEstimatorListener listener) {
return create(listener, DEFAULT_METHOD);
}
/**
* Creates an instance of an initial cameras estimator using provided
* fundamental matrix, listener and method.
*
* @param fundamentalMatrix fundamental matrix relating two views.
* @param listener listener to handle events.
* @return an estimator.
*/
public static InitialCamerasEstimator create(
final FundamentalMatrix fundamentalMatrix, final InitialCamerasEstimatorListener listener) {
return create(fundamentalMatrix, listener, DEFAULT_METHOD);
}
}