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.fitting.line.LineFit;
013import imagingbook.common.geometry.fitting.line.OrthogonalLineFitEigen;
014import imagingbook.common.geometry.line.AlgebraicLine;
015import imagingbook.common.ij.DialogUtils;
016
017import static imagingbook.common.math.Arithmetic.sqr;
018
019/**
020 * <p>
021 * RANSAC detector for straight lines. See Sec. 12.1.2 - 12.1.3 of [1] for additional details.
022 * </p>
023 * <p>
024 * [1] W. Burger, M.J. Burge, <em>Digital Image Processing &ndash; An Algorithmic Introduction</em>, 3rd ed, Springer
025 * (2022).
026 * </p>
027 *
028 * @author WB
029 * @version 2022/11/19
030 * @see AlgebraicLine
031 * @see RansacDetector
032 */
033public class RansacLineDetector extends RansacDetector<AlgebraicLine>{
034        
035        private final Parameters params;
036        
037        /**
038         * Nested class extending {@link RansacDetector.RansacParameters} 
039         * to specify additional RANSAC parameters.
040         */
041        public static class Parameters extends RansacDetector.RansacParameters {
042                
043                /** The minimum distance between two random sample points. */
044                @DialogUtils.DialogLabel("Min. distance between sample points")
045                public int minPairDistance;
046                
047                /**
048                 * Constructor used to define default parameter values.
049                 */
050                public Parameters() {
051                        this.randomPointDraws = 1000;
052                        this.maxInlierDistance = 2.0;
053                        this.minInlierCount = 100;
054                        this.minPairDistance = 25;
055                }       
056        }
057        
058        // constructors ------------------------------------
059        
060        /**
061         * Constructor using specific parameters.
062         * @param params RANSAC parameters
063         */
064        public RansacLineDetector(Parameters params) {
065                super(2, params);
066                this.params = params;
067        }
068        
069        /**
070         * Constructor using default parameters.
071         */
072        public RansacLineDetector() {
073                this(new Parameters());
074        }
075        
076        // ----------------------------------------------------------------
077        
078        @Override // override default method to check for min pair distance
079        Pnt2d[] drawRandomPoints(Pnt2d[] points) {
080                final int MaxTries = 20;
081                int i = 0;
082                Pnt2d[] draw = super.drawRandomPoints(points);
083                while (draw[0].distanceSq(draw[1]) < sqr(params.minPairDistance) && i < MaxTries) {
084                        draw = super.drawRandomPoints(points);
085                        i++;
086                }
087                return (i < MaxTries) ? draw : null;
088        }
089
090        @Override
091        AlgebraicLine fitInitial(Pnt2d[] points) {
092                return AlgebraicLine.from(points[0], points[1]);
093        }
094        
095        @Override
096        AlgebraicLine fitFinal(Pnt2d[] inliers) {
097                LineFit fit = new OrthogonalLineFitEigen(inliers);
098                return fit.getLine();
099        }
100
101}