View Javadoc
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.AffineTransformation2D;
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 AffineTransformation2D refiner.
28   * Implementations of this class refine a 2D affine transformation by taking
29   * into account an initial estimation, inlier point or line 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 AffineTransformation2DRefiner<S1, S2> extends
40          PairMatchesAndInliersDataRefiner<AffineTransformation2D, 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 AffineTransformation2DRefiner() {
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 AffineTransformation2DRefiner(
74              final AffineTransformation2D 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 AffineTransformation2DRefiner(
95              final AffineTransformation2D 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 AffineTransformation2D refine() throws NotReadyException, LockedException, RefinerException {
148         final var result = new AffineTransformation2D();
149         refine(result);
150         return result;
151     }
152 }