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

          Line data    Source code
       1             : /******************************************************************************
       2             :  * Project:  GDAL
       3             :  * Purpose:  Correlator
       4             :  * Author:   Andrew Migal, migal.drew@gmail.com
       5             :  *
       6             :  ******************************************************************************
       7             :  * Copyright (c) 2012, Andrew Migal
       8             :  *
       9             :  * SPDX-License-Identifier: MIT
      10             :  ****************************************************************************/
      11             : 
      12             : #include "gdal_simplesurf.h"
      13             : 
      14             : /************************************************************************/
      15             : /* ==================================================================== */
      16             : /*                          GDALIntegralImage                           */
      17             : /* ==================================================================== */
      18             : /************************************************************************/
      19             : 
      20             : GDALIntegralImage::GDALIntegralImage() = default;
      21             : 
      22           0 : int GDALIntegralImage::GetHeight()
      23             : {
      24           0 :     return nHeight;
      25             : }
      26             : 
      27           0 : int GDALIntegralImage::GetWidth()
      28             : {
      29           0 :     return nWidth;
      30             : }
      31             : 
      32           0 : void GDALIntegralImage::Initialize(const double **padfImg, int nHeightIn,
      33             :                                    int nWidthIn)
      34             : {
      35           0 :     if (pMatrix)
      36             :     {
      37           0 :         for (int i = 0; i < nHeight; i++)
      38           0 :             delete[] pMatrix[i];
      39           0 :         delete[] pMatrix;
      40             :     }
      41             : 
      42             :     // Memory allocation.
      43           0 :     pMatrix = new double *[nHeightIn];
      44           0 :     for (int i = 0; i < nHeightIn; i++)
      45           0 :         pMatrix[i] = new double[nWidthIn];
      46             : 
      47           0 :     nHeight = nHeightIn;
      48           0 :     nWidth = nWidthIn;
      49             : 
      50             :     // Integral image calculation.
      51           0 :     for (int i = 0; i < nHeight; i++)
      52           0 :         for (int j = 0; j < nWidth; j++)
      53             :         {
      54           0 :             const double val = padfImg[i][j];
      55           0 :             double a = 0.0;
      56           0 :             double b = 0.0;
      57           0 :             double c = 0.0;
      58             : 
      59           0 :             if (i - 1 >= 0 && j - 1 >= 0)
      60           0 :                 a = pMatrix[i - 1][j - 1];
      61           0 :             if (j - 1 >= 0)
      62           0 :                 b = pMatrix[i][j - 1];
      63           0 :             if (i - 1 >= 0)
      64           0 :                 c = pMatrix[i - 1][j];
      65             : 
      66             :             // New value based on previous calculations.
      67           0 :             pMatrix[i][j] = val - a + b + c;
      68             :         }
      69           0 : }
      70             : 
      71             : /*
      72             :  * Returns value of specified cell.
      73             :  */
      74           0 : double GDALIntegralImage::GetValue(int nRow, int nCol)
      75             : {
      76           0 :     if (!((nRow >= 0 && nRow < nHeight) && (nCol >= 0 && nCol < nWidth)))
      77           0 :         return 0;
      78             : 
      79           0 :     return pMatrix[nRow][nCol];
      80             : }
      81             : 
      82           0 : double GDALIntegralImage::GetRectangleSum(int nRow, int nCol, int nWidthIn,
      83             :                                           int nHeightIn)
      84             : {
      85             :     // Left top point of rectangle is first.
      86           0 :     const int w = nWidthIn - 1;
      87           0 :     const int h = nHeightIn - 1;
      88             : 
      89           0 :     const int row = nRow;
      90           0 :     const int col = nCol;
      91             : 
      92             :     // Left top point.
      93           0 :     const int lt_row = (row <= nHeight) ? (row - 1) : -1;
      94           0 :     const int lt_col = (col <= nWidth) ? (col - 1) : -1;
      95             :     // Right bottom point of the rectangle.
      96           0 :     const int rb_row = (row + h < nHeight) ? (row + h) : (nHeight - 1);
      97           0 :     const int rb_col = (col + w < nWidth) ? (col + w) : (nWidth - 1);
      98             : 
      99           0 :     double a = 0.0;
     100           0 :     double b = 0.0;
     101           0 :     double c = 0.0;
     102           0 :     double d = 0.0;
     103             : 
     104           0 :     if (lt_row >= 0 && lt_col >= 0)
     105           0 :         a = GetValue(lt_row, lt_col);
     106             : 
     107           0 :     if (lt_row >= 0 && rb_col >= 0)
     108           0 :         b = GetValue(lt_row, rb_col);
     109             : 
     110           0 :     if (rb_row >= 0 && rb_col >= 0)
     111           0 :         c = GetValue(rb_row, rb_col);
     112             : 
     113           0 :     if (rb_row >= 0 && lt_col >= 0)
     114           0 :         d = GetValue(rb_row, lt_col);
     115             : 
     116           0 :     const double res = a + c - b - d;
     117             : 
     118           0 :     return res > 0 ? res : 0;
     119             : }
     120             : 
     121           0 : double GDALIntegralImage::HaarWavelet_X(int nRow, int nCol, int nSize)
     122             : {
     123           0 :     return GetRectangleSum(nRow, nCol + nSize / 2, nSize / 2, nSize) -
     124           0 :            GetRectangleSum(nRow, nCol, nSize / 2, nSize);
     125             : }
     126             : 
     127           0 : double GDALIntegralImage::HaarWavelet_Y(int nRow, int nCol, int nSize)
     128             : {
     129           0 :     return GetRectangleSum(nRow + nSize / 2, nCol, nSize, nSize / 2) -
     130           0 :            GetRectangleSum(nRow, nCol, nSize, nSize / 2);
     131             : }
     132             : 
     133           0 : GDALIntegralImage::~GDALIntegralImage()
     134             : {
     135             :     // Clean up memory.
     136           0 :     for (int i = 0; i < nHeight; i++)
     137           0 :         delete[] pMatrix[i];
     138             : 
     139           0 :     delete[] pMatrix;
     140           0 : }
     141             : 
     142             : /************************************************************************/
     143             : /* ==================================================================== */
     144             : /*                           GDALOctaveLayer                            */
     145             : /* ==================================================================== */
     146             : /************************************************************************/
     147             : 
     148           0 : GDALOctaveLayer::GDALOctaveLayer(int nOctave, int nInterval)
     149             :     : octaveNum(nOctave),
     150           0 :       filterSize(3 * static_cast<int>(pow(2.0, nOctave)) * nInterval + 1),
     151           0 :       radius((filterSize - 1) / 2), scale(static_cast<int>(pow(2.0, nOctave))),
     152           0 :       width(0), height(0), detHessians(nullptr), signs(nullptr)
     153             : {
     154           0 : }
     155             : 
     156           0 : void GDALOctaveLayer::ComputeLayer(GDALIntegralImage *poImg)
     157             : {
     158           0 :     width = poImg->GetWidth();
     159           0 :     height = poImg->GetHeight();
     160             : 
     161             :     // Allocate memory for arrays.
     162           0 :     detHessians = new double *[height];
     163           0 :     signs = new int *[height];
     164             : 
     165           0 :     for (int i = 0; i < height; i++)
     166             :     {
     167           0 :         detHessians[i] = new double[width];
     168           0 :         signs[i] = new int[width];
     169             :     }
     170             : 
     171             :     // 1/3 of filter side.
     172           0 :     const int lobe = filterSize / 3;
     173             : 
     174             :     // Length of the longer side of the lobe in dxx and dyy filters.
     175           0 :     const int longPart = 2 * lobe - 1;
     176             : 
     177           0 :     const int normalization = filterSize * filterSize;
     178             : 
     179             :     // Loop over image pixels.
     180             :     // Filter should remain into image borders.
     181           0 :     for (int r = radius; r <= height - radius; r++)
     182           0 :         for (int c = radius; c <= width - radius; c++)
     183             :         {
     184             :             // Values of Fast Hessian filters.
     185             :             double dxx =
     186           0 :                 poImg->GetRectangleSum(r - lobe + 1, c - radius, filterSize,
     187             :                                        longPart) -
     188           0 :                 3 * poImg->GetRectangleSum(r - lobe + 1, c - (lobe - 1) / 2,
     189           0 :                                            lobe, longPart);
     190           0 :             double dyy = poImg->GetRectangleSum(r - radius, c - lobe - 1,
     191             :                                                 longPart, filterSize) -
     192           0 :                          3 * poImg->GetRectangleSum(r - lobe + 1, c - lobe + 1,
     193           0 :                                                     longPart, lobe);
     194             :             double dxy =
     195           0 :                 poImg->GetRectangleSum(r - lobe, c - lobe, lobe, lobe) +
     196           0 :                 poImg->GetRectangleSum(r + 1, c + 1, lobe, lobe) -
     197           0 :                 poImg->GetRectangleSum(r - lobe, c + 1, lobe, lobe) -
     198           0 :                 poImg->GetRectangleSum(r + 1, c - lobe, lobe, lobe);
     199             : 
     200           0 :             dxx /= normalization;
     201           0 :             dyy /= normalization;
     202           0 :             dxy /= normalization;
     203             : 
     204             :             // Memorize Hessian values and their signs.
     205           0 :             detHessians[r][c] = dxx * dyy - 0.9 * 0.9 * dxy * dxy;
     206           0 :             signs[r][c] = (dxx + dyy >= 0) ? 1 : -1;
     207             :         }
     208           0 : }
     209             : 
     210           0 : GDALOctaveLayer::~GDALOctaveLayer()
     211             : {
     212           0 :     for (int i = 0; i < height; i++)
     213             :     {
     214           0 :         delete[] detHessians[i];
     215           0 :         delete[] signs[i];
     216             :     }
     217             : 
     218           0 :     delete[] detHessians;
     219           0 :     delete[] signs;
     220           0 : }
     221             : 
     222             : /************************************************************************/
     223             : /* ==================================================================== */
     224             : /*                            GDALOctaveMap                             */
     225             : /* ==================================================================== */
     226             : /************************************************************************/
     227             : 
     228           0 : GDALOctaveMap::GDALOctaveMap(int nOctaveStartIn, int nOctaveEndIn)
     229           0 :     : pMap(new GDALOctaveLayer **[nOctaveEndIn]), octaveStart(nOctaveStartIn),
     230           0 :       octaveEnd(nOctaveEndIn)
     231             : {
     232           0 :     for (int i = 0; i < octaveEnd; i++)
     233           0 :         pMap[i] = new GDALOctaveLayer *[INTERVALS];
     234             : 
     235           0 :     for (int oct = octaveStart; oct <= octaveEnd; oct++)
     236           0 :         for (int i = 1; i <= INTERVALS; i++)
     237           0 :             pMap[oct - 1][i - 1] = new GDALOctaveLayer(oct, i);
     238           0 : }
     239             : 
     240           0 : void GDALOctaveMap::ComputeMap(GDALIntegralImage *poImg)
     241             : {
     242           0 :     for (int oct = octaveStart; oct <= octaveEnd; oct++)
     243           0 :         for (int i = 1; i <= INTERVALS; i++)
     244           0 :             pMap[oct - 1][i - 1]->ComputeLayer(poImg);
     245           0 : }
     246             : 
     247           0 : bool GDALOctaveMap::PointIsExtremum(int row, int col, GDALOctaveLayer *bot,
     248             :                                     GDALOctaveLayer *mid, GDALOctaveLayer *top,
     249             :                                     double threshold)
     250             : {
     251             :     // Check that point in middle layer has all neighbors.
     252           0 :     if (row <= top->radius || col <= top->radius ||
     253           0 :         row + top->radius >= top->height || col + top->radius >= top->width)
     254           0 :         return false;
     255             : 
     256           0 :     const double curPoint = mid->detHessians[row][col];
     257             : 
     258             :     // Hessian should be higher than threshold.
     259           0 :     if (curPoint < threshold)
     260           0 :         return false;
     261             : 
     262             :     // Hessian should be higher than Hessians of all neighbors.
     263           0 :     for (int i = -1; i <= 1; i++)
     264           0 :         for (int j = -1; j <= 1; j++)
     265             :         {
     266           0 :             const double topPoint = top->detHessians[row + i][col + j];
     267           0 :             const double midPoint = mid->detHessians[row + i][col + j];
     268           0 :             const double botPoint = bot->detHessians[row + i][col + j];
     269             : 
     270           0 :             if (topPoint >= curPoint || botPoint >= curPoint)
     271           0 :                 return false;
     272             : 
     273           0 :             if (i != 0 || j != 0)
     274           0 :                 if (midPoint >= curPoint)
     275           0 :                     return false;
     276             :         }
     277             : 
     278           0 :     return true;
     279             : }
     280             : 
     281           0 : GDALOctaveMap::~GDALOctaveMap()
     282             : {
     283             :     // Clean up Octave layers.
     284           0 :     for (int oct = octaveStart; oct <= octaveEnd; oct++)
     285           0 :         for (int i = 0; i < INTERVALS; i++)
     286           0 :             delete pMap[oct - 1][i];
     287             : 
     288             :     // Clean up allocated memory.
     289           0 :     for (int oct = 0; oct < octaveEnd; oct++)
     290           0 :         delete[] pMap[oct];
     291             : 
     292           0 :     delete[] pMap;
     293           0 : }

Generated by: LCOV version 1.14