001/*******************************************************************************
002 * This software is provided as a supplement to the authors' textbooks on digital
003 * image processing published by Springer-Verlag in various languages and editions.
004 * Permission to use and distribute this software is granted under the BSD 2-Clause
005 * "Simplified" License (see http://opensource.org/licenses/BSD-2-Clause).
006 * Copyright (c) 2006-2023 Wilhelm Burger, Mark J. Burge. All rights reserved.
007 * Visit https://imagingbook.com for additional details.
008 ******************************************************************************/
009package imagingbook.common.ransac;
010
011import imagingbook.common.geometry.basic.Pnt2d;
012import imagingbook.common.geometry.ellipse.AlgebraicEllipse;
013import imagingbook.common.geometry.ellipse.GeometricEllipse;
014import imagingbook.common.geometry.fitting.ellipse.algebraic.EllipseFit5Points;
015import imagingbook.common.geometry.fitting.ellipse.algebraic.EllipseFitAlgebraic;
016import imagingbook.common.geometry.fitting.ellipse.algebraic.EllipseFitFitzgibbonStable;
017
018/**
019 * <p>
020 * RANSAC detector for ellipses. See Sec. 12.1.5 of [1] for additional details.
021 * </p>
022 * <p>
023 * [1] W. Burger, M.J. Burge, <em>Digital Image Processing &ndash; An Algorithmic Introduction</em>, 3rd ed, Springer
024 * (2022).
025 * </p>
026 *
027 * @author WB
028 * @version 2022/11/19
029 * @see GeometricEllipse
030 * @see RansacDetector
031 */
032public class RansacEllipseDetector extends RansacDetector<GeometricEllipse> {
033        
034        /**
035         * Nested class extending {@link RansacDetector.RansacParameters} 
036         * to specify additional RANSAC parameters.
037         */
038        public static class Parameters extends RansacDetector.RansacParameters {
039                
040                /**
041                 * Constructor used to define default parameter values.
042                 */
043                public Parameters() {
044                        this.randomPointDraws = 1000;
045                        this.maxInlierDistance = 2.0;
046                        this.minInlierCount = 100;
047                }
048        }
049        
050        // constructors ------------------------------------
051        
052        /**
053         * Constructor using specific parameters.
054         * @param params RANSAC parameters
055         */
056        public RansacEllipseDetector(Parameters params) {
057                super(5, params);
058        }
059        
060        /**
061         * Constructor using default parameters.
062         */
063        public RansacEllipseDetector() {
064                this(new Parameters());
065        }
066        
067        // ----------------------------------------------------------------
068
069        @Override
070        GeometricEllipse fitInitial(Pnt2d[] points) {
071                EllipseFitAlgebraic fit = new EllipseFit5Points(points);
072                AlgebraicEllipse ellipse = fit.getEllipse();
073                return (ellipse == null) ?  null : new GeometricEllipse(ellipse);
074        }
075        
076        @Override
077        GeometricEllipse fitFinal(Pnt2d[] inliers) {
078                EllipseFitAlgebraic fit2 = new EllipseFitFitzgibbonStable(inliers);
079                AlgebraicEllipse ellipse = fit2.getEllipse();
080                return (ellipse == null) ?  null : new GeometricEllipse(ellipse);
081        }
082
083}