LinePlaneCorrespondencePinholeCameraRobustEstimator.java
/*
* Copyright (C) 2015 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.geometry.estimators;
import com.irurueta.geometry.Line2D;
import com.irurueta.geometry.PinholeCamera;
import com.irurueta.geometry.Plane;
import com.irurueta.geometry.refiners.DecomposedLinePlaneCorrespondencePinholeCameraRefiner;
import com.irurueta.geometry.refiners.NonDecomposedLinePlaneCorrespondencePinholeCameraRefiner;
import com.irurueta.numerical.robust.RobustEstimatorMethod;
import java.util.List;
/**
* This is an abstract class for algorithms to robustly find the best pinhole
* camera for collections of matched lines and planes.
* Implementations of this class should be able to detect and discard outliers
* in order to find the best solution.
*/
@SuppressWarnings("DuplicatedCode")
public abstract class LinePlaneCorrespondencePinholeCameraRobustEstimator extends PinholeCameraRobustEstimator {
/**
* Minimum number of required line/plane correspondences to estimate a
* camera.
*/
public static final int MIN_NUMBER_OF_LINE_PLANE_CORRESPONDENCES = 4;
/**
* Default robust estimator method when none is provided.
*/
public static final RobustEstimatorMethod DEFAULT_ROBUST_METHOD = RobustEstimatorMethod.PROMEDS;
/**
* List of matched planes.
*/
protected List<Plane> planes;
/**
* List of matched lines.
*/
protected List<Line2D> lines;
/**
* Plane to be reused when computing residuals.
*/
private final Plane residualTestPlane = new Plane();
/**
* Constructor.
*/
protected LinePlaneCorrespondencePinholeCameraRobustEstimator() {
super();
}
/**
* Constructor with lists of matched planes and 2D lines to estimate a
* pinhole camera.
* Points and lines in the lists located at the same position are considered
* to be matched. Hence, both lists must have the same size, and their size
* must be greater or equal than MIN_NUMBER_OF_LINE_PLANE_CORRESPONDENCES
* (4 matches).
*
* @param planes list of planes used to estimate a pinhole camera.
* @param lines list of corresponding projected 2D lines used to estimate
* a pinhole camera.
* @throws IllegalArgumentException if provided lists don't have the same
* size or their size is smaller than required minimum size (4 matches).
*/
protected LinePlaneCorrespondencePinholeCameraRobustEstimator(final List<Plane> planes, final List<Line2D> lines) {
super();
internalSetLinesAndPlanes(planes, lines);
}
/**
* Constructor with listener.
*
* @param listener listener to be notified of events such as when estimation
* starts, ends or its progress significantly changes.
*/
protected LinePlaneCorrespondencePinholeCameraRobustEstimator(final PinholeCameraRobustEstimatorListener listener) {
super(listener);
}
/**
* Constructor with listener and lists of matched planes and 2D lines to
* estimate a pinhole camera.
* Points and lines in the lists located at the same position are considered
* to be matched. Hence, both lists must have the same size, and their size
* must be greater or equal than MIN_NUMBER_OF_LINE_PLANE_CORRESPONDENCES
* (4 matches).
*
* @param listener listener to be notified of events such as when estimation
* starts, ends or its progress significantly changes.
* @param planes list of planes used to estimate a pinhole camera.
* @param lines list of corresponding projected 2D lines used to estimate
* a pinhole camera.
* @throws IllegalArgumentException if provided lists don't have the same
* size or their size is smaller than required minimum size (4 matches).
*/
protected LinePlaneCorrespondencePinholeCameraRobustEstimator(
final PinholeCameraRobustEstimatorListener listener, final List<Plane> planes, final List<Line2D> lines) {
super(listener);
internalSetLinesAndPlanes(planes, lines);
}
/**
* Returns list of 3D planes to be used to estimate a pinhole camera.
* Each plane in the list of 3D planes must be matched with a corresponding
* 2D line resulting from the projection of the 3D plane through the camera
* to be estimated. Matched lines and planes must be located on the same
* position in the lists, hence, both lists must have the same size, and
* their size must be greater or equal than
* MIN_NUMBER_OF_LINE_PLANE_CORRESPONDENCES.
*
* @return list of 3D planes to be used to estimate a pinhole camera.
*/
public List<Plane> getPlanes() {
return planes;
}
/**
* Returns list of 2D lines to be used to estimate a pinhole camera.
* Each line in the list is the result of the projection of a matched.
*
* @return list of 2D lines to be used to estimate a pinhole camera.
*/
public List<Line2D> getLines() {
return lines;
}
/**
* Sets list of matched 3D planes and 2D lines to be used to estimate a
* pinhole camera.
* Each plane in the list of 3D planes must be matched with a corresponding
* 2D line resulting from the projection of the 3D plane through the camera
* to be estimated. Matched lines and planes must be located on the same
* position in the lists, hence, both lists must have the same size, and
* their size must be greater or equal than
* MIN_NUMBER_OF_LINE_PLANE_CORRESPONDENCES.
*
* @param planes 3D planes to be used to estimate a pinhole camera.
* @param lines list of corresponding projected 2D lines used to estimate
* a pinhole camera.
* @throws IllegalArgumentException if provided lists don't have the same
* size or their size is smaller than required minimum size (4 matches).
* @throws LockedException if estimator is locked because a computation is
* already in progress.
*/
public final void setLinesAndPlanes(final List<Plane> planes, final List<Line2D> lines) throws LockedException {
if (isLocked()) {
throw new LockedException();
}
internalSetLinesAndPlanes(planes, lines);
}
/**
* Indicates if estimator is ready to start the pinhole camera estimation.
* This is true when input data (i.e. lists of matched planes and lines) are
* provided as a minimum of MIN_NUMBER_OF_LINE_PLANE_CORRESPONDENCES are
* available.
*
* @return true if estimator is ready, false otherwise.
*/
public boolean isReady() {
return planes != null && lines != null && planes.size() == lines.size()
&& planes.size() >= MIN_NUMBER_OF_LINE_PLANE_CORRESPONDENCES;
}
/**
* Returns quality scores corresponding to each pair of matched samples
* (plane and line).
* The larger the score value the better the quality of the matching.
* This implementation always returns null.
* Subclasses using quality scores must implement proper behaviour.
*
* @return quality scores corresponding to each pair of matched points.
*/
public double[] getQualityScores() {
return null;
}
/**
* Sets quality scores corresponding to each pair of matched points.
* The larger the score value the better the quality of the matching.
* This implementation makes no action.
* Subclasses using quality scores must implement proper behaviour.
*
* @param qualityScores quality scores corresponding to each pair of matched
* points.
* @throws LockedException if robust estimator is locked because an
* estimation is already in progress.
* @throws IllegalArgumentException if provided quality scores length is
* smaller than MIN_NUMBER_OF_LINE_PLANE_CORRESPONDENCES (i.e. 4 samples).
*/
public void setQualityScores(final double[] qualityScores) throws LockedException {
}
/**
* Creates a pinhole camera robust estimator based on plane/line
* correspondences and using provided robust estimator method.
*
* @param method method of a robust estimator algorithm to estimate the best
* pinhole camera.
* @return an instance of a pinhole camera robust estimator.
*/
public static LinePlaneCorrespondencePinholeCameraRobustEstimator create(final RobustEstimatorMethod method) {
return DLTLinePlaneCorrespondencePinholeCameraRobustEstimator.create(method);
}
/**
* Creates a pinhole camera robust estimator based on plane/line
* correspondences and using provided planes and lines and provided robust
* estimator method.
*
* @param planes list of 3D planes to estimate a pinhole camera.
* @param lines list of corresponding projected 2D lines used to estimate
* a pinhole camera.
* @param method method of a robust estimator algorithm to estimate the best
* pinhole camera.
* @return an instance of a pinhole camera robust estimator.
* @throws IllegalArgumentException if provided lists of planes and lines
* don't have the same size or their size is smaller than required minimum
* size (4 correspondences).
*/
public static LinePlaneCorrespondencePinholeCameraRobustEstimator create(
final List<Plane> planes, final List<Line2D> lines, final RobustEstimatorMethod method) {
return DLTLinePlaneCorrespondencePinholeCameraRobustEstimator.create(planes, lines, method);
}
/**
* Creates a pinhole camera robust estimator based on plane/line
* correspondences and using provided listener and robust estimator method.
*
* @param listener listener to be notified of events such as when estimation
* starts, ends or its progress significantly changes.
* @param method method of a robust estimator algorithm to estimate the best
* pinhole camera.
* @return an instance of a pinhole camera robust estimator.
*/
public static LinePlaneCorrespondencePinholeCameraRobustEstimator create(
final PinholeCameraRobustEstimatorListener listener, final RobustEstimatorMethod method) {
return DLTLinePlaneCorrespondencePinholeCameraRobustEstimator.create(listener, method);
}
/**
* Creates a pinhole camera robust estimator based on plane/line
* correspondences and using provided listener, planes and lines, and robust
* estimator method.
*
* @param listener listener to be notified of events such as when estimation
* starts, ends or its progress significantly changes.
* @param planes list of 3D planes to estimate a pinhole camera.
* @param lines list of corresponding projected 2D lines used to estimate
* a pinhole camera.
* @param method method of a robust estimator algorithm to estimate the best
* pinhole camera.
* @return an instance of a pinhole camera robust estimator.
* @throws IllegalArgumentException if provided lists of planes and lines
* don't have the same size or their size is smaller than required minimum
* size (4 correspondences).
*/
public static LinePlaneCorrespondencePinholeCameraRobustEstimator create(
final PinholeCameraRobustEstimatorListener listener, final List<Plane> planes, final List<Line2D> lines,
final RobustEstimatorMethod method) {
return DLTLinePlaneCorrespondencePinholeCameraRobustEstimator.create(listener, planes, lines, method);
}
/**
* Creates a pinhole camera robust estimator based on plane/line
* correspondences and using provided quality scores and robust estimator
* method.
*
* @param qualityScores quality scores corresponding to each pair of matched
* planes/lines.
* @param method method of a robust estimator algorithm to estimate the best
* pinhole camera.
* @return an instance of a pinhole camera robust estimator.
* @throws IllegalArgumentException if provided quality scores length is
* smaller than required minimum size (4 samples).
*/
public static LinePlaneCorrespondencePinholeCameraRobustEstimator create(
final double[] qualityScores, final RobustEstimatorMethod method) {
return DLTLinePlaneCorrespondencePinholeCameraRobustEstimator.create(qualityScores, method);
}
/**
* Creates a pinhole camera robust estimator based on plane/line
* correspondences and using provided planes and lines, quality scores and
* provided robust estimator method.
*
* @param planes list of 3D planes to estimate a pinhole camera.
* @param lines list of corresponding projected 2D lines used to estimate
* a pinhole camera.
* @param qualityScores quality scores corresponding to each pair of matched
* planes/lines.
* @param method method of a robust estimator algorithm to estimate the best
* pinhole camera.
* @return an instance of a pinhole camera robust estimator.
* @throws IllegalArgumentException if provided lists of planes and lines or
* quality scores don't have the same size or their size is smaller than
* required minimum size (4 correspondences).
*/
public static LinePlaneCorrespondencePinholeCameraRobustEstimator create(
final List<Plane> planes, final List<Line2D> lines, final double[] qualityScores,
final RobustEstimatorMethod method) {
return DLTLinePlaneCorrespondencePinholeCameraRobustEstimator.create(planes, lines, qualityScores, method);
}
/**
* Creates a pinhole camera robust estimator based on plane/line
* correspondences and using provided listener, quality scores and robust
* estimator method.
*
* @param listener listener to be notified of events such as when estimation
* starts, ends or its progress significantly changes.
* @param qualityScores quality scores corresponding to each pair of matched
* planes/lines.
* @param method method of a robust estimator algorithm to estimate the best
* pinhole camera.
* @return an instance of a pinhole camera robust estimator.
* @throws IllegalArgumentException if provided quality scores don't have
* the required minimum size (4 samples).
*/
public static LinePlaneCorrespondencePinholeCameraRobustEstimator create(
final PinholeCameraRobustEstimatorListener listener, final double[] qualityScores,
final RobustEstimatorMethod method) {
return DLTLinePlaneCorrespondencePinholeCameraRobustEstimator.create(listener, qualityScores, method);
}
/**
* Creates a pinhole camera robust estimator based on plane/line
* correspondences and using provided listener, planes and lines, and robust
* estimator method.
*
* @param listener listener to be notified of events such as when estimation
* starts, ends or its progress significantly changes.
* @param planes list of 3D planes to estimate a pinhole camera.
* @param lines list of corresponding projected 2D lines used to estimate
* a pinhole camera.
* @param qualityScores quality scores corresponding to each pair of matched
* planes/lines.
* @param method method of a robust estimator algorithm to estimate the best
* pinhole camera.
* @return an instance of a pinhole camera robust estimator.
* @throws IllegalArgumentException if provided lists of planes and lines or
* quality scores don't have the same size or their size is smaller than
* required minimum size (4 correspondences).
*/
public static LinePlaneCorrespondencePinholeCameraRobustEstimator create(
final PinholeCameraRobustEstimatorListener listener, final List<Plane> planes, final List<Line2D> lines,
final double[] qualityScores, final RobustEstimatorMethod method) {
return DLTLinePlaneCorrespondencePinholeCameraRobustEstimator.create(listener, planes, lines, qualityScores,
method);
}
/**
* Creates a pinhole camera robust estimator based on plane/line
* correspondences and using default robust estimator method.
*
* @return an instance of a pinhole camera robust estimator.
*/
public static LinePlaneCorrespondencePinholeCameraRobustEstimator create() {
return create(DEFAULT_ROBUST_METHOD);
}
/**
* Creates a pinhole camera robust estimator based on plane/line
* correspondences and using provided planes and lines and default robust
* estimator method.
*
* @param planes list of 3D planes to estimate a pinhole camera.
* @param lines list of corresponding projected 2D lines used to estimate
* a pinhole camera.
* @return an instance of a pinhole camera robust estimator.
* @throws IllegalArgumentException if provided lists of planes and lines
* don't have the same size or their size is smaller than required minimum
* size (4 correspondences).
*/
public static LinePlaneCorrespondencePinholeCameraRobustEstimator create(
final List<Plane> planes, final List<Line2D> lines) {
return create(planes, lines, DEFAULT_ROBUST_METHOD);
}
/**
* Creates a pinhole camera robust estimator based on plane/line
* correspondences and using provided listener and default estimator method.
*
* @param listener listener to be notified of events such as when estimation
* starts, ends or its progress significantly changes.
* @return an instance of a pinhole camera robust estimator.
*/
public static LinePlaneCorrespondencePinholeCameraRobustEstimator create(
final PinholeCameraRobustEstimatorListener listener) {
return create(listener, DEFAULT_ROBUST_METHOD);
}
/**
* Creates a pinhole camera robust estimator based on plane/line
* correspondences and using provided listener, planes and lines, and
* default robust estimator method.
*
* @param listener listener to be notified of events such as when estimation
* starts, ends or its progress significantly changes.
* @param planes list of 3D planes to estimate a pinhole camera.
* @param lines list of corresponding projected 2D lines used to estimate
* a pinhole camera.
* @return an instance of a pinhole camera robust estimator.
* @throws IllegalArgumentException if provided lists of planes and lines
* don't have the same size or their size is smaller than required minimum
* size (4 correspondences).
*/
public static LinePlaneCorrespondencePinholeCameraRobustEstimator create(
final PinholeCameraRobustEstimatorListener listener, final List<Plane> planes, final List<Line2D> lines) {
return create(listener, planes, lines, DEFAULT_ROBUST_METHOD);
}
/**
* Creates a pinhole camera robust estimator based on plane/line
* correspondences and using provided quality scores and default robust
* estimator method.
*
* @param qualityScores quality scores corresponding to each pair of matched
* planes/lines.
* @return an instance of a pinhole camera robust estimator.
* @throws IllegalArgumentException if provided quality scores length is
* smaller than required minimum size (4 samples).
*/
public static LinePlaneCorrespondencePinholeCameraRobustEstimator create(final double[] qualityScores) {
return create(qualityScores, DEFAULT_ROBUST_METHOD);
}
/**
* Creates a pinhole camera robust estimator based on plane/line
* correspondences and using provided planes and lines, quality scores and
* default robust estimator method.
*
* @param planes list of 3D planes to estimate a pinhole camera.
* @param lines list of corresponding projected 2D lines used to estimate
* a pinhole camera.
* @param qualityScores quality scores corresponding to each pair of matched
* planes/lines.
* @return an instance of a pinhole camera robust estimator.
* @throws IllegalArgumentException if provided lists of planes and lines or
* quality scores don't have the same size or their size is smaller than
* required minimum size (4 correspondences).
*/
public static LinePlaneCorrespondencePinholeCameraRobustEstimator create(
final List<Plane> planes, final List<Line2D> lines, final double[] qualityScores) {
return create(planes, lines, qualityScores, DEFAULT_ROBUST_METHOD);
}
/**
* Creates a pinhole camera robust estimator based on plane/line
* correspondences and using provided listener, quality scores and default
* robust estimator method.
*
* @param listener listener to be notified of events such as when estimation
* starts, ends or its progress significantly changes.
* @param qualityScores quality scores corresponding to each pair of matched
* planes/lines.
* @return an instance of a pinhole camera robust estimator.
* @throws IllegalArgumentException if provided quality scores don't have
* the required minimum size (4 samples).
*/
public static LinePlaneCorrespondencePinholeCameraRobustEstimator create(
final PinholeCameraRobustEstimatorListener listener, final double[] qualityScores) {
return create(listener, qualityScores, DEFAULT_ROBUST_METHOD);
}
/**
* Creates a pinhole camera robust estimator based on plane/line
* correspondences and using provided listener, planes and lines, and
* default robust estimator method.
*
* @param listener listener to be notified of events such as when estimation
* starts, ends or its progress significantly changes.
* @param planes list of 3D planes to estimate a pinhole camera.
* @param lines list of corresponding projected 2D lines used to estimate
* a pinhole camera.
* @param qualityScores quality scores corresponding to each pair of matched
* planes/lines.
* @return an instance of a pinhole camera robust estimator.
* @throws IllegalArgumentException if provided lists of planes and lines or
* quality scores don't have the same size or their size is smaller than
* required minimum size (4 correspondences).
*/
public static LinePlaneCorrespondencePinholeCameraRobustEstimator create(
final PinholeCameraRobustEstimatorListener listener, final List<Plane> planes, final List<Line2D> lines,
final double[] qualityScores) {
return create(listener, planes, lines, qualityScores, DEFAULT_ROBUST_METHOD);
}
/**
* Attempt sto refine provided camera.
*
* @param pinholeCamera camera to be refined.
* @param weight weight for suggestion residual.
* @return refined camera of provided camera if anything fails.
*/
protected PinholeCamera attemptRefine(final PinholeCamera pinholeCamera, final double weight) {
if (useFastRefinement) {
return attemptFastRefine(pinholeCamera, weight);
} else {
return attemptSlowRefine(pinholeCamera, weight);
}
}
/**
* Back-projection residual/error for a single line using provided camera.
*
* @param pinholeCamera camera ot be checked.
* @param line line to be back-projected.
* @param plane plane to check against.
* @return dot product distance between back-projected line and plane.
*/
protected double singleBackprojectionResidual(
final PinholeCamera pinholeCamera, final Line2D line, final Plane plane) {
// back-project line into test plane
pinholeCamera.backProject(line, residualTestPlane);
residualTestPlane.normalize();
final var dotProduct = Math.abs(plane.getA() * residualTestPlane.getA()
+ plane.getB() * residualTestPlane.getB() + plane.getC() * residualTestPlane.getC()
+ plane.getD() * residualTestPlane.getD());
return 1.0 - dotProduct;
}
/**
* Internal method to set lists of planes and lines to be used to estimate a
* pinhole camera.
* This method does not check whether estimator is locked or not.
*
* @param planes list of 3D planes used to estimate a pinhole camera.
* @param lines list of corresponding projected 2D lines used to estimate
* a pinhole camera.
* @throws IllegalArgumentException if provided lists of planes/lines don't
* have the same size or their size is smaller than required minimum size
* (4 samples).
*/
private void internalSetLinesAndPlanes(final List<Plane> planes, final List<Line2D> lines) {
if (planes.size() < MIN_NUMBER_OF_LINE_PLANE_CORRESPONDENCES) {
throw new IllegalArgumentException();
}
if (lines.size() != planes.size()) {
throw new IllegalArgumentException();
}
this.planes = planes;
this.lines = lines;
}
/**
* Attempts to refine provided camera using a slow but more accurate and
* stable algorithm by first doing a Powell optimization and then obtaining
* covariance using Levenberg/Marquardt if needed.
*
* @param pinholeCamera camera to be refined.
* @param weight weight for suggestion residual.
* @return refined camera or provided camera if anything fails.
*/
private PinholeCamera attemptSlowRefine(final PinholeCamera pinholeCamera, final double weight) {
final var inliersData = getInliersData();
if ((refineResult || keepCovariance) && inliersData != null) {
final var refiner = new DecomposedLinePlaneCorrespondencePinholeCameraRefiner(pinholeCamera,
keepCovariance, inliersData, planes, lines, getRefinementStandardDeviation());
try {
if (refineResult) {
refiner.setMinSuggestionWeight(weight);
refiner.setMaxSuggestionWeight(weight);
refiner.setSuggestSkewnessValueEnabled(suggestSkewnessValueEnabled);
refiner.setSuggestedSkewnessValue(suggestedSkewnessValue);
refiner.setSuggestHorizontalFocalLengthEnabled(suggestHorizontalFocalLengthEnabled);
refiner.setSuggestedHorizontalFocalLengthValue(suggestedHorizontalFocalLengthValue);
refiner.setSuggestVerticalFocalLengthEnabled(suggestVerticalFocalLengthEnabled);
refiner.setSuggestedVerticalFocalLengthValue(suggestedVerticalFocalLengthValue);
refiner.setSuggestAspectRatioEnabled(suggestAspectRatioEnabled);
refiner.setSuggestedAspectRatioValue(suggestedAspectRatioValue);
refiner.setSuggestPrincipalPointEnabled(suggestPrincipalPointEnabled);
refiner.setSuggestedPrincipalPointValue(suggestedPrincipalPointValue);
refiner.setSuggestRotationEnabled(suggestRotationEnabled);
refiner.setSuggestedRotationValue(suggestedRotationValue);
refiner.setSuggestCenterEnabled(suggestCenterEnabled);
refiner.setSuggestedCenterValue(suggestedCenterValue);
}
final var result = new PinholeCamera();
final var improved = refiner.refine(result);
if (keepCovariance) {
// keep covariance
covariance = refiner.getCovariance();
}
return improved ? result : pinholeCamera;
} catch (final Exception e) {
return pinholeCamera;
}
} else {
covariance = null;
return pinholeCamera;
}
}
/**
* Attempts to refine provided camera using a fast algorithm based on
* Levenberg/Marquardt.
*
* @param pinholeCamera camera to be refined.
* @param weight weight for suggestion residual.
* @return refined camera or provided camera if anything fails.
*/
private PinholeCamera attemptFastRefine(final PinholeCamera pinholeCamera, final double weight) {
final var inliersData = getInliersData();
if (refineResult && inliersData != null) {
final var refiner = new NonDecomposedLinePlaneCorrespondencePinholeCameraRefiner(pinholeCamera,
keepCovariance, inliersData, planes, lines, getRefinementStandardDeviation());
try {
refiner.setSuggestionErrorWeight(weight);
refiner.setSuggestSkewnessValueEnabled(suggestSkewnessValueEnabled);
refiner.setSuggestedSkewnessValue(suggestedSkewnessValue);
refiner.setSuggestHorizontalFocalLengthEnabled(suggestHorizontalFocalLengthEnabled);
refiner.setSuggestedHorizontalFocalLengthValue(suggestedHorizontalFocalLengthValue);
refiner.setSuggestVerticalFocalLengthEnabled(suggestVerticalFocalLengthEnabled);
refiner.setSuggestedVerticalFocalLengthValue(suggestedVerticalFocalLengthValue);
refiner.setSuggestAspectRatioEnabled(suggestAspectRatioEnabled);
refiner.setSuggestedAspectRatioValue(suggestedAspectRatioValue);
refiner.setSuggestPrincipalPointEnabled(suggestPrincipalPointEnabled);
refiner.setSuggestedPrincipalPointValue(suggestedPrincipalPointValue);
refiner.setSuggestRotationEnabled(suggestRotationEnabled);
refiner.setSuggestedRotationValue(suggestedRotationValue);
refiner.setSuggestCenterEnabled(suggestCenterEnabled);
refiner.setSuggestedCenterValue(suggestedCenterValue);
final var result = new PinholeCamera();
final var improved = refiner.refine(result);
if (keepCovariance) {
// keep covariance
covariance = refiner.getCovariance();
}
return improved ? result : pinholeCamera;
} catch (final Exception e) {
// refinement failed, so we return input value
return pinholeCamera;
}
} else {
return pinholeCamera;
}
}
}