LCOV - code coverage report
Current view: top level - include/improc - sourceFinder.hpp (source / functions) Coverage Total Hit
Test: mxlib Lines: 0.0 % 62 0
Test Date: 2026-08-30 22:23:37 Functions: 0.0 % 10 0

            Line data    Source code
       1              : /** \file sourceFinder.hpp
       2              :  * \brief Declares and defines a class for finding sources in images
       3              :  * \ingroup image_processing_files
       4              :  * \author Jared R. Males (jaredmales@gmail.com)
       5              :  *
       6              :  */
       7              : 
       8              : //***********************************************************************//
       9              : // Copyright 2021 Jared R. Males (jaredmales@gmail.com)
      10              : //
      11              : // This file is part of mxlib.
      12              : //
      13              : // mxlib is free software: you can redistribute it and/or modify
      14              : // it under the terms of the GNU General Public License as published by
      15              : // the Free Software Foundation, either version 3 of the License, or
      16              : // (at your option) any later version.
      17              : //
      18              : // mxlib is distributed in the hope that it will be useful,
      19              : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      20              : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      21              : // GNU General Public License for more details.
      22              : //
      23              : // You should have received a copy of the GNU General Public License
      24              : // along with mxlib.  If not, see <http://www.gnu.org/licenses/>.
      25              : //***********************************************************************//
      26              : 
      27              : #ifndef improc_sourceFinder_hpp
      28              : #define improc_sourceFinder_hpp
      29              : 
      30              : #include "eigenImage.hpp"
      31              : 
      32              : #include "../math/vectorUtils.hpp"
      33              : 
      34              : namespace mx
      35              : {
      36              : namespace improc
      37              : {
      38              : 
      39              : /// Find stars in an image by SNR thresholding
      40              : /**
      41              :  * \ingroup image_utils
      42              :  */
      43              : template <typename _realT>
      44              : class sourceFinder
      45              : {
      46              : 
      47              :   public:
      48              :     typedef _realT realT; ///< The real valued type in which to do calculations
      49              : 
      50              :     typedef std::pair<int, int> pixelT; ///< Pixel coordinates
      51              : 
      52              :   protected:
      53              :     realT m_threshold{ 5 }; ///< The SNR threshold to use
      54              : 
      55              :     realT m_minsep{ 2 }; ///< The minimum separation between stars.  Closer SNR detections are treated as the same star.
      56              : 
      57              :     bool m_useMedian{
      58              :         true }; ///< If true, then the median is used for standard deviation calculation. The mean is used otherwise.
      59              : 
      60              :     // Working memory, retained to help with repeated calls.
      61              :     std::vector<float> m_vals;
      62              :     std::vector<pixelT> m_pixs;
      63              :     std::vector<size_t> m_snr;
      64              : 
      65              :   public:
      66              :     /// Default c'tor
      67              :     sourceFinder();
      68              : 
      69              :     /// Constructor to set up the algorithm
      70              :     sourceFinder( realT thresh, ///< [in]
      71              :                   realT minsep  ///< [in]
      72              :     );
      73              : 
      74              :     /// Clear the working memory
      75              :     void clear();
      76              : 
      77              :     /// Set the SNR threshold
      78              :     void treshold( const realT &thresh /**< [in] the new threshold*/ );
      79              : 
      80              :     /// Get the SNR threshold
      81              :     /** \returns the current value of m_threshold;
      82              :      */
      83              :     realT threshold();
      84              : 
      85              :     /// Set the minimum separation
      86              :     void minsep( const realT &msep /**< [in] the new minimum separation*/ );
      87              : 
      88              :     /// Get the minimum separation between stars
      89              :     /** \returns the current value of m_minsep;
      90              :      */
      91              :     realT minsep();
      92              : 
      93              :     /// Set the useMedian flag
      94              :     void useMedian( const bool &useMed /**< [in] the new useMedian flag value*/ );
      95              : 
      96              :     /// Get the useMedian flag
      97              :     /** \returns the current value of m_useMedian;
      98              :      */
      99              :     bool useMedian();
     100              : 
     101              :     /// Find stars in an image
     102              :     /** Returns the coordinates as (row, col) of the highest SNR pixel in each unique star.
     103              :      *
     104              :      * \returns a vector of pixel coordinates
     105              :      */
     106              :     std::vector<pixelT> operator()( const eigenImage<realT> &im /**< [in] the image to search for stars*/ );
     107              : };
     108              : 
     109              : template <typename realT>
     110            0 : sourceFinder<realT>::sourceFinder()
     111              : {
     112            0 : }
     113              : 
     114              : template <typename realT>
     115            0 : sourceFinder<realT>::sourceFinder( realT thresh, realT minsep ) : m_threshold( thresh ), m_minsep( minsep )
     116              : {
     117            0 : }
     118              : 
     119              : template <typename realT>
     120            0 : void sourceFinder<realT>::treshold( const realT &thresh )
     121              : {
     122            0 :     m_threshold = thresh;
     123            0 : }
     124              : 
     125              : template <typename realT>
     126            0 : void sourceFinder<realT>::clear()
     127              : {
     128            0 :     m_vals.clear();
     129            0 :     m_pixs.clear();
     130            0 :     m_snr.clear();
     131            0 : }
     132              : 
     133              : template <typename realT>
     134            0 : realT sourceFinder<realT>::threshold()
     135              : {
     136            0 :     return m_threshold;
     137              : }
     138              : 
     139              : template <typename realT>
     140            0 : void sourceFinder<realT>::minsep( const realT &msep )
     141              : {
     142            0 :     m_minsep = msep;
     143            0 : }
     144              : 
     145              : template <typename realT>
     146            0 : realT sourceFinder<realT>::minsep()
     147              : {
     148            0 :     return m_minsep;
     149              : }
     150              : 
     151              : template <typename realT>
     152            0 : void sourceFinder<realT>::useMedian( const bool &useMed )
     153              : {
     154            0 :     m_useMedian = useMed;
     155            0 : }
     156              : 
     157              : template <typename realT>
     158            0 : bool sourceFinder<realT>::useMedian()
     159              : {
     160            0 :     return m_useMedian;
     161              : }
     162              : 
     163              : template <typename realT>
     164            0 : std::vector<typename sourceFinder<realT>::pixelT> sourceFinder<realT>::operator()( const eigenImage<realT> &im )
     165              : {
     166            0 :     m_vals.resize( im.rows() * im.cols() );
     167            0 :     m_pixs.resize( im.rows() * im.cols() );
     168              : 
     169            0 :     int p = 0;
     170            0 :     for( int cc = 0; cc < im.cols(); ++cc )
     171              :     {
     172            0 :         for( int rr = 0; rr < im.rows(); ++rr )
     173              :         {
     174            0 :             m_vals[p] = im( rr, cc );
     175            0 :             m_pixs[p] = { rr, cc };
     176            0 :             ++p;
     177              :         }
     178              :     }
     179              : 
     180              :     realT mm;
     181              : 
     182            0 :     if( m_useMedian )
     183            0 :         mm = math::vectorMedian( m_vals );
     184              :     else
     185            0 :         mm = math::vectorMean( m_vals );
     186            0 :     realT std = sqrt( math::vectorVariance( m_vals, mm ) );
     187              : 
     188              :     // Get the SNR for any pixels above the threshold
     189            0 :     m_snr.clear();
     190            0 :     for( size_t n = 0; n < m_vals.size(); ++n )
     191              :     {
     192            0 :         if( ( m_vals[n] - mm ) / std >= m_threshold )
     193              :         {
     194            0 :             m_snr.push_back( n );
     195              :         }
     196              :     }
     197              : 
     198              :     // Delete the pixels above threshold which are with minsep of a higher pixel
     199            0 :     realT mms2 = m_minsep * m_minsep; // save an op
     200            0 :     for( long n = 0; n < m_snr.size(); ++n )
     201              :     {
     202            0 :         for( long m = 0; m < m_snr.size(); ++m )
     203              :         {
     204            0 :             if( m == n )
     205            0 :                 continue;
     206              : 
     207              :             // Squared distance:
     208            0 :             realT d2 = pow( m_pixs[m_snr[n]].first - m_pixs[m_snr[m]].first, 2 ) +
     209            0 :                        pow( m_pixs[m_snr[n]].second - m_pixs[m_snr[m]].second, 2 );
     210              : 
     211            0 :             if( d2 < mms2 )
     212              :             {
     213            0 :                 if( m_vals[m_snr[n]] < m_vals[m_snr[m]] ) // If this is the higher pixel, delete the lower
     214              :                 {
     215            0 :                     m_snr.erase( m_snr.begin() + n );
     216            0 :                     --n;
     217            0 :                     break; // So we're done comparing to the one we just deleted.
     218              :                 }
     219              :                 else // This is lower, so delete it.
     220              :                 {
     221            0 :                     m_snr.erase( m_snr.begin() + m );
     222            0 :                     if( m < n )
     223            0 :                         --n; // changing size behind
     224            0 :                     --m;
     225            0 :                     continue;
     226              :                 }
     227              :             }
     228              :         }
     229              :     }
     230              : 
     231            0 :     std::vector<pixelT> found( m_snr.size() );
     232              : 
     233            0 :     for( size_t n = 0; n < m_snr.size(); ++n )
     234              :     {
     235            0 :         found[n] = m_pixs[m_snr[n]];
     236              :     }
     237              : 
     238            0 :     return found;
     239              : }
     240              : 
     241              : } // namespace improc
     242              : } // namespace mx
     243              : 
     244              : #endif // improc_sourceFinder_hpp
        

Generated by: LCOV version 2.0-1