LCOV - code coverage report
Current view: top level - alg - gdal_simplesurf.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 0 4 0.0 %
Date: 2024-11-21 22:18:42 Functions: 0 2 0.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  * $Id$
       3             :  * Project:  GDAL
       4             :  * Purpose:  Correlator
       5             :  * Author:   Andrew Migal, migal.drew@gmail.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2012, Andrew Migal
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : /**
      14             :  * @file
      15             :  * @author Andrew Migal migal.drew@gmail.com
      16             :  * @brief Class for searching corresponding points on images.
      17             :  */
      18             : 
      19             : #ifndef GDALSIMPLESURF_H_
      20             : #define GDALSIMPLESURF_H_
      21             : 
      22             : #include "gdal_priv.h"
      23             : #include "cpl_conv.h"
      24             : #include <list>
      25             : 
      26             : /**
      27             :  * @brief Class of "feature point" in raster. Used by SURF-based algorithm.
      28             :  *
      29             :  * @details This point presents coordinates of distinctive pixel in image.
      30             :  * In computer vision, feature points - the most "strong" and "unique"
      31             :  * pixels (or areas) in picture, which can be distinguished from others.
      32             :  * For more details, see FAST corner detector, SIFT, SURF and similar
      33             :  * algorithms.
      34             :  */
      35             : class GDALFeaturePoint
      36             : {
      37             :   public:
      38             :     /**
      39             :      * Standard constructor. Initializes all parameters with negative numbers
      40             :      * and allocates memory for descriptor.
      41             :      */
      42             :     GDALFeaturePoint();
      43             : 
      44             :     /**
      45             :      * Copy constructor
      46             :      * @param fp Copied instance of GDALFeaturePoint class
      47             :      */
      48             :     GDALFeaturePoint(const GDALFeaturePoint &fp);
      49             : 
      50             :     /**
      51             :      * Create instance of GDALFeaturePoint class
      52             :      *
      53             :      * @param nX X-coordinate (pixel)
      54             :      * @param nY Y-coordinate (line)
      55             :      * @param nScale Scale which contains this point (2, 4, 8, 16 and so on)
      56             :      * @param nRadius Half of the side of descriptor area
      57             :      * @param nSign Sign of Hessian determinant for this point
      58             :      *
      59             :      * @note This constructor normally is invoked by SURF-based algorithm,
      60             :      * which provides all necessary parameters.
      61             :      */
      62             :     GDALFeaturePoint(int nX, int nY, int nScale, int nRadius, int nSign);
      63             :     virtual ~GDALFeaturePoint();
      64             : 
      65             :     /** Assignment operator */
      66             :     GDALFeaturePoint &operator=(const GDALFeaturePoint &point);
      67             : 
      68             :     /**
      69             :      * Provide access to point's descriptor.
      70             :      *
      71             :      * @param nIndex Position of descriptor's value.
      72             :      * nIndex should be within range from 0 to DESC_SIZE (in current version -
      73             :      * 64)
      74             :      *
      75             :      * @return Reference to value of descriptor in 'nIndex' position.
      76             :      * If index is out of range then behavior is undefined.
      77             :      */
      78             :     double &operator[](int nIndex);
      79             : 
      80             :     /**
      81             :      * Provide access to point's descriptor.
      82             :      *
      83             :      * @param nIndex Position of descriptor's value.
      84             :      * nIndex should be within range from 0 to DESC_SIZE (in current version -
      85             :      * 64)
      86             :      *
      87             :      * @return Reference to value of descriptor in 'nIndex' position.
      88             :      * If index is out of range then behavior is undefined.
      89             :      */
      90             :     double operator[](int nIndex) const;
      91             : 
      92             :     /** Descriptor length */
      93             :     static const int DESC_SIZE = 64;
      94             : 
      95             :     /**
      96             :      * Fetch X-coordinate (pixel) of point
      97             :      *
      98             :      * @return X-coordinate in pixels
      99             :      */
     100             :     int GetX() const;
     101             : 
     102             :     /**
     103             :      * Set X coordinate of point
     104             :      *
     105             :      * @param nX X coordinate in pixels
     106             :      */
     107             :     void SetX(int nX);
     108             : 
     109             :     /**
     110             :      * Fetch Y-coordinate (line) of point.
     111             :      *
     112             :      * @return Y-coordinate in pixels.
     113             :      */
     114             :     int GetY() const;
     115             : 
     116             :     /**
     117             :      * Set Y coordinate of point.
     118             :      *
     119             :      * @param nY Y coordinate in pixels.
     120             :      */
     121             :     void SetY(int nY);
     122             : 
     123             :     /**
     124             :      * Fetch scale of point.
     125             :      *
     126             :      * @return Scale for this point.
     127             :      */
     128             :     int GetScale() const;
     129             : 
     130             :     /**
     131             :      * Set scale of point.
     132             :      *
     133             :      * @param nScale Scale for this point.
     134             :      */
     135             :     void SetScale(int nScale);
     136             : 
     137             :     /**
     138             :      * Fetch radius of point.
     139             :      *
     140             :      * @return Radius for this point.
     141             :      */
     142             :     int GetRadius() const;
     143             : 
     144             :     /**
     145             :      * Set radius of point.
     146             :      *
     147             :      * @param nRadius Radius for this point.
     148             :      */
     149             :     void SetRadius(int nRadius);
     150             : 
     151             :     /**
     152             :      * Fetch sign of Hessian determinant of point.
     153             :      *
     154             :      * @return Sign for this point.
     155             :      */
     156             :     int GetSign() const;
     157             : 
     158             :     /**
     159             :      * Set sign of point.
     160             :      *
     161             :      * @param nSign Sign of Hessian determinant for this point.
     162             :      */
     163             :     void SetSign(int nSign);
     164             : 
     165             :   private:
     166             :     // Coordinates of point in image
     167             :     int nX;
     168             :     int nY;
     169             :     // --------------------
     170             :     int nScale;
     171             :     int nRadius;
     172             :     int nSign;
     173             :     // Descriptor array
     174             :     double *padfDescriptor;
     175             : };
     176             : 
     177             : /**
     178             :  * @author Andrew Migal migal.drew@gmail.com
     179             :  * @brief Integral image class (summed area table).
     180             :  * @details Integral image is a table for fast computing the sum of
     181             :  * values in rectangular subarea. In more detail, for 2-dimensional array
     182             :  * of numbers this class provides capability to get sum of values in
     183             :  * rectangular arbitrary area with any size in constant time.
     184             :  * Integral image is constructed from grayscale picture.
     185             :  */
     186           0 : class GDALIntegralImage
     187             : {
     188             :     CPL_DISALLOW_COPY_ASSIGN(GDALIntegralImage)
     189             : 
     190             :   public:
     191             :     GDALIntegralImage();
     192             :     virtual ~GDALIntegralImage();
     193             : 
     194             :     /**
     195             :      * Compute integral image for specified array. Result is stored internally.
     196             :      *
     197             :      * @param padfImg Pointer to 2-dimensional array of values
     198             :      * @param nHeight Number of rows in array
     199             :      * @param nWidth Number of columns in array
     200             :      */
     201             :     void Initialize(const double **padfImg, int nHeight, int nWidth);
     202             : 
     203             :     /**
     204             :      * Fetch value of specified position in integral image.
     205             :      *
     206             :      * @param nRow Row of this position
     207             :      * @param nCol Column of this position
     208             :      *
     209             :      * @return Value in specified position or zero if parameters are out of
     210             :      * range.
     211             :      */
     212             :     double GetValue(int nRow, int nCol);
     213             : 
     214             :     /**
     215             :      * Get sum of values in specified rectangular grid. Rectangle is constructed
     216             :      * from left top point.
     217             :      *
     218             :      * @param nRow Row of left top point of rectangle
     219             :      * @param nCol Column of left top point of rectangle
     220             :      * @param nWidth Width of rectangular area (number of columns)
     221             :      * @param nHeight Height of rectangular area (number of rows)
     222             :      *
     223             :      * @return Sum of values in specified grid.
     224             :      */
     225             :     double GetRectangleSum(int nRow, int nCol, int nWidth, int nHeight);
     226             : 
     227             :     /**
     228             :      * Get value of horizontal Haar wavelet in specified square grid.
     229             :      *
     230             :      * @param nRow Row of left top point of square
     231             :      * @param nCol Column of left top point of square
     232             :      * @param nSize Side of the square
     233             :      *
     234             :      * @return Value of horizontal Haar wavelet in specified square grid.
     235             :      */
     236             :     double HaarWavelet_X(int nRow, int nCol, int nSize);
     237             : 
     238             :     /**
     239             :      * Get value of vertical Haar wavelet in specified square grid.
     240             :      *
     241             :      * @param nRow Row of left top point of square
     242             :      * @param nCol Column of left top point of square
     243             :      * @param nSize Side of the square
     244             :      *
     245             :      * @return Value of vertical Haar wavelet in specified square grid.
     246             :      */
     247             :     double HaarWavelet_Y(int nRow, int nCol, int nSize);
     248             : 
     249             :     /**
     250             :      * Fetch height of integral image.
     251             :      *
     252             :      * @return Height of integral image (number of rows).
     253             :      */
     254             :     int GetHeight();
     255             : 
     256             :     /**
     257             :      * Fetch width of integral image.
     258             :      *
     259             :      * @return Width of integral image (number of columns).
     260             :      */
     261             :     int GetWidth();
     262             : 
     263             :   private:
     264             :     double **pMatrix = nullptr;
     265             :     int nWidth = 0;
     266             :     int nHeight = 0;
     267             : };
     268             : 
     269             : /**
     270             :  * @author Andrew Migal migal.drew@gmail.com
     271             :  * @brief Class for computation and storage of Hessian values in SURF-based
     272             :  * algorithm.
     273             :  *
     274             :  * @details SURF-based algorithm normally uses this class for searching
     275             :  * feature points on raster images. Class also contains traces of Hessian
     276             :  * matrices to provide fast computations.
     277             :  */
     278             : class GDALOctaveLayer
     279             : {
     280             :     CPL_DISALLOW_COPY_ASSIGN(GDALOctaveLayer)
     281             : 
     282             :   public:
     283             :     GDALOctaveLayer();
     284             : 
     285             :     /**
     286             :      * Create instance with provided parameters.
     287             :      *
     288             :      * @param nOctave Number of octave which contains this layer
     289             :      * @param nInterval Number of position in octave
     290             :      *
     291             :      * @note Normally constructor is invoked only by SURF-based algorithm.
     292             :      */
     293             :     GDALOctaveLayer(int nOctave, int nInterval);
     294             :     virtual ~GDALOctaveLayer();
     295             : 
     296             :     /**
     297             :      * Perform calculation of Hessian determinants and their signs
     298             :      * for specified integral image. Result is stored internally.
     299             :      *
     300             :      * @param poImg Integral image object, which provides all necessary
     301             :      * data for computation
     302             :      *
     303             :      * @note Normally method is invoked only by SURF-based algorithm.
     304             :      */
     305             :     void ComputeLayer(GDALIntegralImage *poImg);
     306             : 
     307             :     /**
     308             :      * Octave which contains this layer (1,2,3...)
     309             :      */
     310             :     int octaveNum;
     311             :     /**
     312             :      * Length of the side of filter
     313             :      */
     314             :     int filterSize;
     315             :     /**
     316             :      * Length of the border
     317             :      */
     318             :     int radius;
     319             :     /**
     320             :      * Scale for this layer
     321             :      */
     322             :     int scale;
     323             :     /**
     324             :      * Image width in pixels
     325             :      */
     326             :     int width;
     327             :     /**
     328             :      * Image height in pixels
     329             :      */
     330             :     int height;
     331             :     /**
     332             :      * Hessian values for image pixels
     333             :      */
     334             :     double **detHessians;
     335             :     /**
     336             :      * Hessian signs for speeded matching
     337             :      */
     338             :     int **signs;
     339             : };
     340             : 
     341             : /**
     342             :  * @author Andrew Migal migal.drew@gmail.com
     343             :  * @brief Class for handling octave layers in SURF-based algorithm.
     344             :  * @details Class contains OctaveLayers and provides capability to construct
     345             :  * octave space and distinguish feature points. Normally this class is used only
     346             :  * by SURF-based algorithm.
     347             :  */
     348             : class GDALOctaveMap
     349             : {
     350             :     CPL_DISALLOW_COPY_ASSIGN(GDALOctaveMap)
     351             : 
     352             :   public:
     353             :     /**
     354             :      * Create octave space. Octave numbers are start with one. (1, 2, 3, 4, ...
     355             :      * )
     356             :      *
     357             :      * @param nOctaveStart Number of bottom octave
     358             :      * @param nOctaveEnd Number of top octave. Should be equal or greater than
     359             :      * OctaveStart
     360             :      */
     361             :     GDALOctaveMap(int nOctaveStart, int nOctaveEnd);
     362             :     virtual ~GDALOctaveMap();
     363             : 
     364             :     /**
     365             :      * Calculate Hessian values for octave space
     366             :      * (for all stored octave layers) using specified integral image
     367             :      * @param poImg Integral image instance which provides necessary data
     368             :      * @see GDALOctaveLayer
     369             :      */
     370             :     void ComputeMap(GDALIntegralImage *poImg);
     371             : 
     372             :     /**
     373             :      * Method makes decision that specified point
     374             :      * in middle octave layer is maximum among all points
     375             :      * from 3x3x3 neighbourhood (surrounding points in
     376             :      * bottom, middle and top layers). Provided layers should be from the same
     377             :      * octave's interval. Detects feature points.
     378             :      *
     379             :      * @param row Row of point, which is candidate to be feature point
     380             :      * @param col Column of point, which is candidate to be feature point
     381             :      * @param bot Bottom octave layer
     382             :      * @param mid Middle octave layer
     383             :      * @param top Top octave layer
     384             :      * @param threshold Threshold for feature point recognition. Detected
     385             :      * feature point will have Hessian value greater than this provided
     386             :      * threshold.
     387             :      *
     388             :      * @return TRUE if candidate was evaluated as feature point or FALSE
     389             :      * otherwise.
     390             :      */
     391             :     static bool PointIsExtremum(int row, int col, GDALOctaveLayer *bot,
     392             :                                 GDALOctaveLayer *mid, GDALOctaveLayer *top,
     393             :                                 double threshold);
     394             : 
     395             :     /**
     396             :      * 2-dimensional array of octave layers
     397             :      */
     398             :     GDALOctaveLayer ***pMap;
     399             : 
     400             :     /**
     401             :      * Value for constructing internal octave space
     402             :      */
     403             :     static const int INTERVALS = 4;
     404             : 
     405             :     /**
     406             :      * Number of bottom octave
     407             :      */
     408             :     int octaveStart;
     409             : 
     410             :     /**
     411             :      * Number of top octave. Should be equal or greater than OctaveStart
     412             :      */
     413             :     int octaveEnd;
     414             : };
     415             : 
     416             : /**
     417             :  * @author Andrew Migal migal.drew@gmail.com
     418             :  * @brief Class for searching corresponding points on images.
     419             :  * @details Provides capability for detection feature points
     420             :  * and finding equal points on different images.
     421             :  * Class implements simplified version of SURF algorithm (Speeded Up Robust
     422             :  * Features). As original, this realization is scale invariant, but sensitive to
     423             :  * rotation. Images should have similar rotation angles (maximum difference is
     424             :  * up to 10-15 degrees), otherwise algorithm produces incorrect and very
     425             :  * unstable results.
     426             :  */
     427             : 
     428             : class GDALSimpleSURF
     429             : {
     430             :   private:
     431             :     /**
     432             :      * Class stores indexes of pair of point
     433             :      * and distance between them.
     434             :      */
     435             :     class MatchedPointPairInfo
     436             :     {
     437             :       public:
     438           0 :         MatchedPointPairInfo(int nInd_1, int nInd_2, double dfDist)
     439           0 :             : ind_1(nInd_1), ind_2(nInd_2), euclideanDist(dfDist)
     440             :         {
     441           0 :         }
     442             : 
     443             :         int ind_1;
     444             :         int ind_2;
     445             :         double euclideanDist;
     446             :     };
     447             : 
     448             :     CPL_DISALLOW_COPY_ASSIGN(GDALSimpleSURF)
     449             : 
     450             :   public:
     451             :     /**
     452             :      * Prepare class according to specified parameters. Octave numbers affects
     453             :      * to amount of detected points and their robustness.
     454             :      * Range between bottom and top octaves also affects to required time of
     455             :      * detection points (if range is large, algorithm should perform more
     456             :      * operations).
     457             :      * @param nOctaveStart Number of bottom octave. Octave numbers starts with
     458             :      * one
     459             :      * @param nOctaveEnd Number of top octave. Should be equal or greater than
     460             :      * OctaveStart
     461             :      *
     462             :      * @note
     463             :      * Every octave finds points with specific size. For small images
     464             :      * use small octave numbers, for high resolution - large.
     465             :      * For 1024x1024 images it's normal to use any octave numbers from range
     466             :      * 1-6. (for example, octave start - 1, octave end - 3, or octave start - 2,
     467             :      * octave end - 2.) For larger images, try 1-10 range or even higher. Pay
     468             :      * attention that number of detected point decreases quickly per octave for
     469             :      * particular image. Algorithm finds more points in case of small octave
     470             :      * numbers. If method detects nothing, reduce bottom bound of octave range.
     471             :      *
     472             :      * NOTICE that every octave requires time to compute. Use a little range
     473             :      * or only one octave if execution time is significant.
     474             :      */
     475             :     GDALSimpleSURF(int nOctaveStart, int nOctaveEnd);
     476             :     virtual ~GDALSimpleSURF();
     477             : 
     478             :     /**
     479             :      * Convert image with RGB channels to grayscale using "luminosity" method.
     480             :      * Result is used in SURF-based algorithm, but may be used anywhere where
     481             :      * grayscale images with nice contrast are required.
     482             :      *
     483             :      * @param red Image's red channel
     484             :      * @param green Image's green channel
     485             :      * @param blue Image's blue channel
     486             :      * @param nXSize Width of initial image
     487             :      * @param nYSize Height of initial image
     488             :      * @param padfImg Array for resulting grayscale image
     489             :      * @param nHeight Height of resulting image
     490             :      * @param nWidth Width of resulting image
     491             :      *
     492             :      * @return CE_None or CE_Failure if error occurs.
     493             :      */
     494             :     static CPLErr ConvertRGBToLuminosity(GDALRasterBand *red,
     495             :                                          GDALRasterBand *green,
     496             :                                          GDALRasterBand *blue, int nXSize,
     497             :                                          int nYSize, double **padfImg,
     498             :                                          int nHeight, int nWidth);
     499             : 
     500             :     /**
     501             :      * Find feature points using specified integral image.
     502             :      *
     503             :      * @param poImg Integral image to be used
     504             :      * @param dfThreshold Threshold for feature point recognition. Detected
     505             :      * feature point will have Hessian value greater than this provided
     506             :      * threshold.
     507             :      *
     508             :      * @note Typical threshold's value is 0,001. But this value
     509             :      * can be various in each case and depends on image's nature.
     510             :      * For example, value can be 0.002 or 0.005.
     511             :      * Fill free to experiment with it.
     512             :      * If threshold is high, than number of detected feature points is small,
     513             :      * and vice versa.
     514             :      */
     515             :     std::vector<GDALFeaturePoint> *
     516             :     ExtractFeaturePoints(GDALIntegralImage *poImg, double dfThreshold);
     517             : 
     518             :     /**
     519             :      * Find corresponding points (equal points in two collections).
     520             :      *
     521             :      * @param poMatchPairs Resulting collection for matched points
     522             :      * @param poFirstCollect Points on the first image
     523             :      * @param poSecondCollect Points on the second image
     524             :      * @param dfThreshold Value from 0 to 1. Threshold affects to number of
     525             :      * matched points. If threshold is higher, amount of corresponding
     526             :      * points is larger, and vice versa
     527             :      *
     528             :      * @note Typical threshold's value is 0,1. BUT it's a very approximate
     529             :      * guide. It can be 0,001 or even 1. This threshold provides direct
     530             :      * adjustment of point matching. NOTICE that if threshold is lower, matches
     531             :      * are more robust and correct, but number of matched points is smaller.
     532             :      * Therefore if algorithm performs many false detections and produces bad
     533             :      * results, reduce threshold.  Otherwise, if algorithm finds nothing,
     534             :      * increase threshold.
     535             :      *
     536             :      * @return CE_None or CE_Failure if error occurs.
     537             :      */
     538             :     static CPLErr
     539             :     MatchFeaturePoints(std::vector<GDALFeaturePoint *> *poMatchPairs,
     540             :                        std::vector<GDALFeaturePoint> *poFirstCollect,
     541             :                        std::vector<GDALFeaturePoint> *poSecondCollect,
     542             :                        double dfThreshold);
     543             : 
     544             :   private:
     545             :     /**
     546             :      * Compute euclidean distance between descriptors of two feature points.
     547             :      * It's used in comparison and matching of points.
     548             :      *
     549             :      * @param firstPoint First feature point to be compared
     550             :      * @param secondPoint Second feature point to be compared
     551             :      *
     552             :      * @return Euclidean distance between descriptors.
     553             :      */
     554             :     static double GetEuclideanDistance(const GDALFeaturePoint &firstPoint,
     555             :                                        const GDALFeaturePoint &secondPoint);
     556             : 
     557             :     /**
     558             :      * Set provided distance values to range from 0 to 1.
     559             :      *
     560             :      * @param poList List of distances to be normalized
     561             :      */
     562             :     static void NormalizeDistances(std::list<MatchedPointPairInfo> *poList);
     563             : 
     564             :     /**
     565             :      * Compute descriptor for specified feature point.
     566             :      *
     567             :      * @param poPoint Feature point instance
     568             :      * @param poImg image where feature point was found
     569             :      */
     570             :     static void SetDescriptor(GDALFeaturePoint *poPoint,
     571             :                               GDALIntegralImage *poImg);
     572             : 
     573             :   private:
     574             :     int octaveStart;
     575             :     int octaveEnd;
     576             :     GDALOctaveMap *poOctMap;
     577             : };
     578             : 
     579             : #endif /* GDALSIMPLESURF_H_ */

Generated by: LCOV version 1.14