1 /* 2 * Copyright (C) 2015 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.ar.calibration.estimators; 17 18 import com.irurueta.ar.calibration.ImageOfAbsoluteConic; 19 import com.irurueta.geometry.Transformation2D; 20 import com.irurueta.geometry.estimators.LockedException; 21 import com.irurueta.geometry.estimators.NotReadyException; 22 23 import java.util.Arrays; 24 import java.util.List; 25 26 /** 27 * This class defines the interface for an estimator of the Image of Absolute 28 * Conic (IAC). The IAC is directly related to pinhole camera intrinsic 29 * parameters, implementations of this estimator can be used for camera 30 * calibration purposes. 31 * Depending on the constraints imposed on the intrinsic parameters of the 32 * camera, some parameters of the IAC will be known in advance and fewer 33 * equations will be needed. 34 * If no constraints are imposed, then at least 5 equations will be needed to 35 * estimate the DIAC, and hence 3 homographies will be required (2 equations can 36 * be obtained for each homography). 2*n <= 5 ==< n <= 5/2 ==< n <= 2.5 ==< 37 * n <= 3 38 * If skewness is assumed to be known and zero, then one less homography is 39 * required, hence only 2 homographies will be needed. 40 * 2*n + 1 <= 5 ==< n <= 4 / 2 ==< n <= 2 41 * If also principal point is assumed to be known and located at image center 42 * (origin of coordinates), then 2 fewer equations are needed, and hence only 43 * 1 homography is needed: 44 * 2n + 1 + 2 <= 5 ==< n <= 2 / 2 ==< n <= 1 45 * By enabling constraints, results are guaranteed to be more stable (estimation 46 * fails fewer times with an exception) and more accurate, so whenever possible 47 * constraints should be enabled. The principal point at origin introduces more 48 * stability and accuracy than the skewness constraint, but if possible both 49 * should be enabled. By default, both constraints are enable. 50 */ 51 public abstract class ImageOfAbsoluteConicEstimator { 52 53 /** 54 * Minimum number of required equations to solve the IAC linear system of 55 * equations. 56 */ 57 protected static final int MIN_REQUIRED_EQUATIONS = 5; 58 59 /** 60 * Constant defining whether zero skewness is assumed. 61 */ 62 public static final boolean DEFAULT_ZERO_SKEWNESS = true; 63 64 /** 65 * Constant defining whether principal point is assumed to be at origin of 66 * coordinates. 67 */ 68 public static final boolean DEFAULT_PRINCIPAL_POINT_AT_ORIGIN = true; 69 70 /** 71 * Constant defining whether aspect ratio of focal distances (i.e. vertical 72 * focal distance divided by horizontal focal distance) is known or not. 73 * Notice that focal distance aspect ratio is not related to image size 74 * aspect ratio. Typically, LCD sensor cells are square and hence aspect 75 * ratio of focal distances is known and equal to 1. 76 */ 77 public static final boolean DEFAULT_FOCAL_DISTANCE_ASPECT_RATIO_KNOWN = true; 78 79 /** 80 * Constant defining default aspect ratio of focal distances. This constant 81 * takes into account that typically LCD sensor cells are square and hence 82 * aspect ratio of focal distances is known and equal to 1. 83 */ 84 public static final double DEFAULT_FOCAL_DISTANCE_ASPECT_RATIO = 1.0; 85 86 /** 87 * Minimum absolute value allowed for aspect ratio of focal distances. 88 */ 89 public static final double MIN_ABS_FOCAL_DISTANCE_ASPECT_RATIO = 1e-6; 90 91 /** 92 * Default estimator type. 93 */ 94 public static final ImageOfAbsoluteConicEstimatorType DEFAULT_ESTIMATOR_TYPE = 95 ImageOfAbsoluteConicEstimatorType.LMSE_IAC_ESTIMATOR; 96 97 /** 98 * Indicates whether camera skewness is assumed to be zero or not. 99 */ 100 protected boolean zeroSkewness; 101 102 /** 103 * Indicates whether principal point is assumed to be at origin of 104 * coordinates or not. 105 * If false, the principal point will be estimated, otherwise it will be 106 * assumed to be at image center (i.e. origin of coordinates). 107 */ 108 protected boolean principalPointAtOrigin; 109 110 /** 111 * Indicates whether aspect ratio of focal distances (i.e. vertical focal 112 * distance divided by horizontal focal distance) is known or not. 113 * Notice that focal distance aspect ratio is not related to image size 114 * aspect ratio. Typically, LCD sensor cells are square and hence aspect 115 * ratio of focal distances is known and equal to 1. 116 * This value is only taken into account if skewness is assumed to be 117 * zero, otherwise it is ignored. 118 */ 119 protected boolean focalDistanceAspectRatioKnown; 120 121 /** 122 * Contains aspect ratio of focal distances (i.e. vertical focal distance 123 * divided by horizontal focal distance). 124 * This value is only taken into account if skewness is assumed to be zero 125 * and focal distance aspect ratio is marked as known, otherwise it is 126 * ignored. 127 * By default, this is 1.0, since it is taken into account that typically 128 * LCD sensor cells are square and hence aspect ratio focal distances is 129 * known and equal to 1. 130 * Notice that focal distance aspect ratio is not related to image size 131 * aspect ratio. 132 */ 133 protected double focalDistanceAspectRatio; 134 135 /** 136 * True when estimator is estimating IAC. 137 */ 138 protected boolean locked; 139 140 /** 141 * Listener to be notified of events such as when estimation starts, ends or 142 * estimation progress changes. 143 */ 144 protected ImageOfAbsoluteConicEstimatorListener listener; 145 146 /** 147 * List of homographies (2D transformations) used to estimate the image 148 * of absolute conic (IAC), which can be used to obtain pinhole camera 149 * intrinsic parameters. 150 */ 151 protected List<Transformation2D> homographies; 152 153 /** 154 * Constructor. 155 */ 156 protected ImageOfAbsoluteConicEstimator() { 157 zeroSkewness = DEFAULT_ZERO_SKEWNESS; 158 principalPointAtOrigin = DEFAULT_PRINCIPAL_POINT_AT_ORIGIN; 159 focalDistanceAspectRatioKnown = DEFAULT_FOCAL_DISTANCE_ASPECT_RATIO_KNOWN; 160 focalDistanceAspectRatio = DEFAULT_FOCAL_DISTANCE_ASPECT_RATIO; 161 162 locked = false; 163 listener = null; 164 homographies = null; 165 } 166 167 /** 168 * Constructor with listener. 169 * 170 * @param listener listener to be notified of events such as when estimation 171 * starts, ends or estimation progress changes. 172 */ 173 protected ImageOfAbsoluteConicEstimator(final ImageOfAbsoluteConicEstimatorListener listener) { 174 this(); 175 this.listener = listener; 176 } 177 178 /** 179 * Constructor. 180 * 181 * @param homographies list of homographies (2D transformations) used to 182 * estimate the image of absolute conic (IAC), which can be used to obtain 183 * pinhole camera intrinsic parameters. 184 * @throws IllegalArgumentException if not enough homographies are provided 185 * for default settings. Hence, at least 1 homography must be provided. 186 */ 187 protected ImageOfAbsoluteConicEstimator(final List<Transformation2D> homographies) { 188 this(); 189 internalSetHomographies(homographies); 190 } 191 192 /** 193 * Constructor. 194 * 195 * @param homographies list of homographies (2D transformations) used to 196 * estimate the image of absolute conic (IAC), which can be used to obtain 197 * pinhole camera intrinsic parameters. 198 * @param listener listener to be notified of events such as when estimation 199 * starts, ends or estimation progress changes. 200 * @throws IllegalArgumentException if not enough homographies are provided 201 * for default settings. Hence, at least 1 homography must be provided. 202 */ 203 protected ImageOfAbsoluteConicEstimator( 204 final List<Transformation2D> homographies, final ImageOfAbsoluteConicEstimatorListener listener) { 205 this(listener); 206 internalSetHomographies(homographies); 207 } 208 209 /** 210 * Returns boolean indicating whether camera skewness is assumed to be zero 211 * or not. 212 * Skewness determines whether LCD sensor cells are properly aligned or not, 213 * where zero indicates perfect alignment. 214 * Typically, skewness is a value equal or very close to zero. 215 * 216 * @return true if camera skewness is assumed to be zero, otherwise camera 217 * skewness is estimated. 218 */ 219 public boolean isZeroSkewness() { 220 return zeroSkewness; 221 } 222 223 /** 224 * Sets boolean indicating whether camera skewness is assumed to be zero or 225 * not. 226 * Skewness determines whether LCD sensor cells are properly aligned or not, 227 * where zero indicates perfect alignment. 228 * Typically, skewness is a value equal or very close to zero. 229 * 230 * @param zeroSkewness true if camera skewness is assumed to be zero, 231 * otherwise camera skewness is estimated. 232 * @throws LockedException if estimator is locked. 233 */ 234 public void setZeroSkewness(final boolean zeroSkewness) throws LockedException { 235 if (isLocked()) { 236 throw new LockedException(); 237 } 238 239 this.zeroSkewness = zeroSkewness; 240 } 241 242 /** 243 * Returns boolean indicating whether principal point is assumed to be at 244 * origin of coordinates or not. 245 * Typically principal point is located at image center (origin of 246 * coordinates), and usually matches the center of radial distortion if 247 * it is taken into account. 248 * 249 * @return true if principal point is assumed to be at origin of 250 * coordinates, false if principal point must be estimated. 251 */ 252 public boolean isPrincipalPointAtOrigin() { 253 return principalPointAtOrigin; 254 } 255 256 /** 257 * Sets boolean indicating whether principal point is assumed to be at 258 * origin of coordinates or not. 259 * Typically principal point is located at image center (origin of 260 * coordinates), and usually matches the center of radial distortion if it 261 * is taken into account. 262 * 263 * @param principalPointAtOrigin true if principal point is assumed to be at 264 * origin of coordinates, false if principal point must be estimated. 265 * @throws LockedException if estimator is locked. 266 */ 267 public void setPrincipalPointAtOrigin(final boolean principalPointAtOrigin) throws LockedException { 268 if (isLocked()) { 269 throw new LockedException(); 270 } 271 272 this.principalPointAtOrigin = principalPointAtOrigin; 273 } 274 275 /** 276 * Returns boolean indicating whether aspect ratio of focal distances (i.e. 277 * vertical focal distance divided by horizontal focal distance) is known or 278 * not. 279 * Notice that focal distance aspect ratio is not related to image size 280 * aspect ratio. Typically, LCD sensor cells are square and hence aspect 281 * ratio of focal distances is known and equal to 1. 282 * This value is only taken into account if skewness is assumed to be zero, 283 * otherwise it is ignored. 284 * 285 * @return true if focal distance aspect ratio is known, false otherwise. 286 */ 287 public boolean isFocalDistanceAspectRatioKnown() { 288 return focalDistanceAspectRatioKnown; 289 } 290 291 /** 292 * Sets value indicating whether aspect ratio of focal distances (i.e. 293 * vertical focal distance divided by horizontal focal distance) is known or 294 * not. 295 * Notice that focal distance aspect ratio is not related to image size 296 * aspect ratio. Typically, LCD sensor cells are square and hence aspect 297 * ratio of focal distances is known and equal to 1. 298 * This value is only taken into account if skewness is assumed to be zero, 299 * otherwise it is ignored. 300 * 301 * @param focalDistanceAspectRatioKnown true if focal distance aspect ratio 302 * is known, false otherwise. 303 * @throws LockedException if estimator is locked. 304 */ 305 public void setFocalDistanceAspectRatioKnown(final boolean focalDistanceAspectRatioKnown) throws LockedException { 306 if (isLocked()) { 307 throw new LockedException(); 308 } 309 310 this.focalDistanceAspectRatioKnown = focalDistanceAspectRatioKnown; 311 } 312 313 /** 314 * Returns aspect ratio of focal distances (i.e. vertical focal distance 315 * divided by horizontal focal distance). 316 * This value is only taken into account if skewness is assumed to be zero 317 * and focal distance aspect ratio is marked as known, otherwise it is 318 * ignored. 319 * By default, this is 1.0, since it is taken into account that typically 320 * LCD sensor cells are square and hence aspect ratio focal distances is 321 * known and equal to 1. 322 * Notice that focal distance aspect ratio is not related to image size 323 * aspect ratio 324 * Notice that a negative aspect ratio indicates that vertical axis is 325 * reversed. This can be useful in some situations where image vertical 326 * coordinates are reversed respect to the physical world (i.e. in computer 327 * graphics typically image vertical coordinates go downwards, while in 328 * physical world they go upwards). 329 * 330 * @return aspect ratio of focal distances. 331 */ 332 public double getFocalDistanceAspectRatio() { 333 return focalDistanceAspectRatio; 334 } 335 336 /** 337 * Sets aspect ratio of focal distances (i.e. vertical focal distance 338 * divided by horizontal focal distance). 339 * This value is only taken into account if skewness is assumed to be zero 340 * and focal distance aspect ratio is marked as known, otherwise it is 341 * ignored. 342 * By default, this is 1.0, since it is taken into account that typically 343 * LCD sensor cells are square and hence aspect ratio focal distances is 344 * known and equal to 1. 345 * Notice that focal distance aspect ratio is not related to image size 346 * aspect ratio. 347 * Notice that a negative aspect ratio indicates that vertical axis is 348 * reversed. This can be useful in some situations where image vertical 349 * coordinates are reversed respect to the physical world (i.e. in computer 350 * graphics typically image vertical coordinates go downwards, while in 351 * physical world they go upwards). 352 * 353 * @param focalDistanceAspectRatio aspect ratio of focal distances to be 354 * set. 355 * @throws LockedException if estimator is locked. 356 * @throws IllegalArgumentException if focal distance aspect ratio is too 357 * close to zero, as it might produce numerical instabilities. 358 */ 359 public void setFocalDistanceAspectRatio(final double focalDistanceAspectRatio) throws LockedException { 360 if (isLocked()) { 361 throw new LockedException(); 362 } 363 if (Math.abs(focalDistanceAspectRatio) < MIN_ABS_FOCAL_DISTANCE_ASPECT_RATIO) { 364 throw new IllegalArgumentException(); 365 } 366 367 this.focalDistanceAspectRatio = focalDistanceAspectRatio; 368 } 369 370 /** 371 * Indicates whether this instance is locked. 372 * 373 * @return true if this estimator is busy estimating an IAC, false 374 * otherwise. 375 */ 376 public boolean isLocked() { 377 return locked; 378 } 379 380 /** 381 * Returns listener to be notified of events such as when estimation starts, 382 * ends or estimation progress changes. 383 * 384 * @return listener to be notified of events. 385 */ 386 public ImageOfAbsoluteConicEstimatorListener getListener() { 387 return listener; 388 } 389 390 /** 391 * Sets listener to be notified of events such as when estimation starts, 392 * ends or estimation progress changes. 393 * 394 * @param listener listener to be notified of events. 395 * @throws LockedException if estimator is locked. 396 */ 397 public void setListener(final ImageOfAbsoluteConicEstimatorListener listener) throws LockedException { 398 if (isLocked()) { 399 throw new LockedException(); 400 } 401 this.listener = listener; 402 } 403 404 /** 405 * Gets list of homographies to estimate IAC. 406 * 407 * @return list of homographies to estimate IAC. 408 */ 409 public List<Transformation2D> getHomographies() { 410 return homographies; 411 } 412 413 /** 414 * Sets list of homographies to estimate IAC. 415 * 416 * @param homographies list of homographies to estimate IAC. 417 * @throws LockedException if estimator is locked. 418 * @throws IllegalArgumentException if provided list of homographies does not 419 * contain enough elements to estimate the IAC using current settings. 420 */ 421 public void setHomographies(final List<Transformation2D> homographies) throws LockedException { 422 if (isLocked()) { 423 throw new LockedException(); 424 } 425 internalSetHomographies(homographies); 426 } 427 428 /** 429 * Returns minimum number of required homographies needed to estimate the 430 * Image of Absolute Conic (IAC). 431 * If no constraints are imposed, then at least 3 homographies are required. 432 * For each constraint imposed, one less equation will be required, hence 433 * if skewness is assumed to be known (by using its typical value of zero), 434 * then only 4 equations will be needed (2 homographies). 435 * If also the horizontal and vertical coordinates of the principal point 436 * are assumed to be known (by being placed at the 2D origin of coordinates, 437 * which is a typical value), then only 2 equations will be needed 438 * (1 homography). 439 * 440 * @return minimum number of required homographies required to estimate the 441 * IAC 442 */ 443 public int getMinNumberOfRequiredHomographies() { 444 var numEquations = MIN_REQUIRED_EQUATIONS; 445 if (zeroSkewness) { 446 if (focalDistanceAspectRatioKnown) { 447 numEquations--; 448 } 449 numEquations--; 450 } 451 if (principalPointAtOrigin) { 452 numEquations -= 2; 453 } 454 455 return (numEquations / 2) + (numEquations % 2); 456 } 457 458 /** 459 * Returns value indicating whether required data has been provided so that 460 * IAC estimation can start. 461 * If true, estimator is ready to compute the IAC, otherwise more data needs 462 * to be provided. 463 * 464 * @return true if estimator is ready, false otherwise. 465 */ 466 public boolean isReady() { 467 return homographies != null && homographies.size() >= getMinNumberOfRequiredHomographies(); 468 } 469 470 /** 471 * Estimates Image of Absolute Conic (IAC). 472 * 473 * @return estimated IAC. 474 * @throws LockedException if estimator is locked. 475 * @throws NotReadyException if input has not yet been provided. 476 * @throws ImageOfAbsoluteConicEstimatorException if an error occurs during 477 * estimation, usually because repeated homographies are 478 * provided, or homographies corresponding to degenerate 479 * camera movements such as pure parallel translations 480 * where no additional data is really provided. Indeed, 481 * if provided homographies belong to the group of affine 482 * transformations (or other groups contained within such 483 * as metric or Euclidean ones), this exception will 484 * raise because camera movements will be degenerate. To 485 * avoid this exception, homographies must be purely 486 * projective. 487 */ 488 public abstract ImageOfAbsoluteConic estimate() throws LockedException, NotReadyException, 489 ImageOfAbsoluteConicEstimatorException; 490 491 /** 492 * Returns type of IAC estimator. 493 * 494 * @return type of IAC estimator. 495 */ 496 public abstract ImageOfAbsoluteConicEstimatorType getType(); 497 498 /** 499 * Creates an instance of an IAC estimator using provided default type. 500 * 501 * @return an instance of an IAC estimator. 502 */ 503 public static ImageOfAbsoluteConicEstimator create() { 504 return create(DEFAULT_ESTIMATOR_TYPE); 505 } 506 507 /** 508 * Creates an instance of an IAC estimator using provided listener and 509 * default type. 510 * 511 * @param listener listener to be notified of events such as when estimation 512 * starts, ends or estimation progress changes. 513 * @return an instance of an IAC estimator. 514 */ 515 public static ImageOfAbsoluteConicEstimator create(final ImageOfAbsoluteConicEstimatorListener listener) { 516 return create(listener, DEFAULT_ESTIMATOR_TYPE); 517 } 518 519 /** 520 * Creates an instance of an IAC estimator using provided homographies 521 * 522 * @param homographies list of homographies (2D transformations) used to 523 * estimate the image of absolute conic (IAC), which can be used to obtain 524 * pinhole camera intrinsic parameters. 525 * @return an instance of an IAC estimator. 526 * @throws IllegalArgumentException if not enough homographies are provided 527 * for default IAC estimation constraints. 528 */ 529 public static ImageOfAbsoluteConicEstimator create(final List<Transformation2D> homographies) { 530 return create(homographies, DEFAULT_ESTIMATOR_TYPE); 531 } 532 533 /** 534 * Creates an instance of an IAC estimator using provided homographies and 535 * listener. 536 * 537 * @param homographies list of homographies (2D transformations) used to 538 * estimate the image of absolute conic (IAC), which can be used to obtain 539 * pinhole camera intrinsic parameters. 540 * @param listener listener to be notified of events such as when estimation 541 * starts, ends or estimation progress changes. 542 * @return an instance of an IAC estimator. 543 * @throws IllegalArgumentException if not enough homographies are provided 544 * for default IAC estimation constraints. 545 */ 546 public static ImageOfAbsoluteConicEstimator create( 547 final List<Transformation2D> homographies, final ImageOfAbsoluteConicEstimatorListener listener) { 548 return create(homographies, listener, DEFAULT_ESTIMATOR_TYPE); 549 } 550 551 552 /** 553 * Creates an instance of an IAC estimator using provided type. 554 * 555 * @param type type of IAC estimator to create. 556 * @return an instance of an IAC estimator. 557 */ 558 public static ImageOfAbsoluteConicEstimator create(final ImageOfAbsoluteConicEstimatorType type) { 559 return type == ImageOfAbsoluteConicEstimatorType.WEIGHTED_IAC_ESTIMATOR 560 ? new WeightedImageOfAbsoluteConicEstimator() : new LMSEImageOfAbsoluteConicEstimator(); 561 } 562 563 /** 564 * Creates an instance of an IAC estimator using provided listener and 565 * type. 566 * 567 * @param listener listener to be notified of events such as when estimation 568 * starts, ends or estimation progress changes. 569 * @param type type of IAC estimator to create. 570 * @return an instance of an IAC estimator. 571 */ 572 public static ImageOfAbsoluteConicEstimator create( 573 final ImageOfAbsoluteConicEstimatorListener listener, final ImageOfAbsoluteConicEstimatorType type) { 574 return type == ImageOfAbsoluteConicEstimatorType.WEIGHTED_IAC_ESTIMATOR 575 ? new WeightedImageOfAbsoluteConicEstimator(listener) 576 : new LMSEImageOfAbsoluteConicEstimator(listener); 577 } 578 579 /** 580 * Creates an instance of an IAC estimator using provided homographies 581 * and type. 582 * 583 * @param homographies list of homographies (2D transformations) used to 584 * estimate the image of absolute conic (IAC), which can be used to obtain 585 * pinhole camera intrinsic parameters. 586 * @param type type of IAC estimator to create. 587 * @return an instance of an IAC estimator. 588 * @throws IllegalArgumentException if not enough homographies are provided 589 * for default IAC estimation constraints. 590 */ 591 public static ImageOfAbsoluteConicEstimator create( 592 final List<Transformation2D> homographies, final ImageOfAbsoluteConicEstimatorType type) { 593 switch (type) { 594 case WEIGHTED_IAC_ESTIMATOR: 595 final var weights = new double[homographies.size()]; 596 Arrays.fill(weights, 1.0); 597 return new WeightedImageOfAbsoluteConicEstimator(homographies, weights); 598 case LMSE_IAC_ESTIMATOR: 599 default: 600 return new LMSEImageOfAbsoluteConicEstimator(homographies); 601 } 602 } 603 604 /** 605 * Creates an instance of an IAC estimator using provided homographies, 606 * listener and type. 607 * 608 * @param homographies list of homographies (2D transformations) used to 609 * estimate the image of absolute conic (IAC), which can be used to obtain 610 * pinhole camera intrinsic parameters. 611 * @param listener listener to be notified of events such as when estimation 612 * starts, ends or estimation progress changes. 613 * @param type type of IAC estimator to create. 614 * @return an instance of an IAC estimator. 615 * @throws IllegalArgumentException if not enough homographies are provided 616 * for default IAC estimation constraints. 617 */ 618 public static ImageOfAbsoluteConicEstimator create( 619 final List<Transformation2D> homographies, final ImageOfAbsoluteConicEstimatorListener listener, 620 final ImageOfAbsoluteConicEstimatorType type) { 621 switch (type) { 622 case WEIGHTED_IAC_ESTIMATOR: 623 final var weights = new double[homographies.size()]; 624 Arrays.fill(weights, 1.0); 625 return new WeightedImageOfAbsoluteConicEstimator(homographies, weights, listener); 626 case LMSE_IAC_ESTIMATOR: 627 default: 628 return new LMSEImageOfAbsoluteConicEstimator(homographies, listener); 629 } 630 } 631 632 /** 633 * Sets list of homographies to estimate IAC. 634 * This method does not check whether estimator is locked. 635 * 636 * @param homographies list of homographies to estimate IAC. 637 * @throws IllegalArgumentException if provided list of homographies does not 638 * contain enough elements to estimate the DIAC using current settings. 639 */ 640 protected final void internalSetHomographies(final List<Transformation2D> homographies) { 641 if (homographies == null || homographies.size() < getMinNumberOfRequiredHomographies()) { 642 throw new IllegalArgumentException(); 643 } 644 this.homographies = homographies; 645 } 646 }