1 /*
2 * Copyright (C) 2017 Alberto Irurueta Carro (alberto@irurueta.com)
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package com.irurueta.geometry.refiners;
17
18 import com.irurueta.geometry.AffineTransformation3D;
19 import com.irurueta.geometry.estimators.LockedException;
20 import com.irurueta.geometry.estimators.NotReadyException;
21 import com.irurueta.numerical.robust.InliersData;
22
23 import java.util.BitSet;
24 import java.util.List;
25
26 /**
27 * Base class for AffineTransformation3D refiner.
28 * Implementations of this class refine a 3D affine transformation by taking
29 * into account an initial estimation, inlier point or plane matches and their
30 * residuals.
31 * This class can be used to find a solution that minimizes error of inliers in
32 * LMSE terms.
33 * Typically, a refiner is used by a robust estimator, however it can also be
34 * useful in some other situations.
35 *
36 * @param <S1> type of matched samples in 1st set.
37 * @param <S2> type of matched samples in 2nd set.
38 */
39 public abstract class AffineTransformation3DRefiner<S1, S2> extends
40 PairMatchesAndInliersDataRefiner<AffineTransformation3D, S1, S2> {
41
42 /**
43 * Standard deviation used for Levenberg-Marquardt fitting during
44 * refinement.
45 * Returned value gives an indication of how much variance each residual
46 * has.
47 * Typically, this value is related to the threshold used on each robust
48 * estimation, since residuals of found inliers are within the range of
49 * such threshold.
50 */
51 private double refinementStandardDeviation;
52
53 /**
54 * Constructor.
55 */
56 protected AffineTransformation3DRefiner() {
57 }
58
59 /**
60 * Constructor.
61 *
62 * @param initialEstimation initial estimation to be set.
63 * @param keepCovariance true if covariance of estimation must be kept after
64 * refinement, false otherwise.
65 * @param inliers set indicating which of the provided matches are inliers.
66 * @param residuals residuals for matched samples.
67 * @param numInliers number of inliers on initial estimation.
68 * @param samples1 1st set of paired samples.
69 * @param samples2 2nd set of paired samples.
70 * @param refinementStandardDeviation standard deviation used for
71 * Levenberg-Marquardt fitting.
72 */
73 protected AffineTransformation3DRefiner(
74 final AffineTransformation3D initialEstimation, final boolean keepCovariance, final BitSet inliers,
75 final double[] residuals, final int numInliers, final List<S1> samples1, final List<S2> samples2,
76 final double refinementStandardDeviation) {
77 super(initialEstimation, keepCovariance, inliers, residuals, numInliers, samples1, samples2);
78 this.refinementStandardDeviation = refinementStandardDeviation;
79 }
80
81 /**
82 * Constructor.
83 *
84 * @param initialEstimation initial estimation to be set.
85 * @param keepCovariance true if covariance of estimation must be kept after
86 * refinement, false otherwise.
87 * @param inliersData inlier data, typically obtained from a robust
88 * estimator.
89 * @param samples1 1st set of paired samples.
90 * @param samples2 2nd set of paired samples.
91 * @param refinementStandardDeviation standard deviation used for
92 * Levenberg-Marquardt fitting.
93 */
94 protected AffineTransformation3DRefiner(
95 final AffineTransformation3D initialEstimation, final boolean keepCovariance, final InliersData inliersData,
96 final List<S1> samples1, final List<S2> samples2, final double refinementStandardDeviation) {
97 super(initialEstimation, keepCovariance, inliersData, samples1, samples2);
98 this.refinementStandardDeviation = refinementStandardDeviation;
99 }
100
101 /**
102 * Gets standard deviation used for Levenberg-Marquardt fitting during
103 * refinement.
104 * Returned value gives an indication of how much variance each residual
105 * has.
106 * Typically, this value is related to the threshold used on each robust
107 * estimation, since residuals of found inliers are within the range of
108 * such threshold.
109 *
110 * @return standard deviation used for refinement.
111 */
112 public double getRefinementStandardDeviation() {
113 return refinementStandardDeviation;
114 }
115
116 /**
117 * Sets standard deviation used for Levenberg-Marquardt fitting during
118 * refinement.
119 * Returned value gives an indication of how much variance each residual
120 * has.
121 * Typically, this value is related to the threshold used on each robust
122 * estimation, since residuals of found inliers are within the range of such
123 * threshold.
124 *
125 * @param refinementStandardDeviation standard deviation used for
126 * refinement.
127 * @throws LockedException if estimator is locked.
128 */
129 public void setRefinementStandardDeviation(final double refinementStandardDeviation) throws LockedException {
130 if (isLocked()) {
131 throw new LockedException();
132 }
133 this.refinementStandardDeviation = refinementStandardDeviation;
134 }
135
136 /**
137 * Refines provided initial estimation.
138 *
139 * @return refines estimation.
140 * @throws NotReadyException if not enough input data has been provided.
141 * @throws LockedException if estimator is locked because refinement is
142 * already in progress.
143 * @throws RefinerException if refinement fails for some reason (e.g. unable
144 * to converge to a result).
145 */
146 @Override
147 public AffineTransformation3D refine() throws NotReadyException, LockedException, RefinerException {
148 final var result = new AffineTransformation3D();
149 refine(result);
150 return result;
151 }
152 }