Yash Chainani | 5458dea | 2022-06-29 21:05:02 -0700 | [diff] [blame^] | 1 | //============================================================================= |
| 2 | // |
| 3 | // fed.cpp |
| 4 | // Authors: Pablo F. Alcantarilla (1), Jesus Nuevo (2) |
| 5 | // Institutions: Georgia Institute of Technology (1) |
| 6 | // TrueVision Solutions (2) |
| 7 | // Date: 15/09/2013 |
| 8 | // Email: pablofdezalc@gmail.com |
| 9 | // |
| 10 | // AKAZE Features Copyright 2013, Pablo F. Alcantarilla, Jesus Nuevo |
| 11 | // All Rights Reserved |
| 12 | // See LICENSE for the license information |
| 13 | //============================================================================= |
| 14 | |
| 15 | /** |
| 16 | * @file fed.cpp |
| 17 | * @brief Functions for performing Fast Explicit Diffusion and building the |
| 18 | * nonlinear scale space |
| 19 | * @date Sep 15, 2013 |
| 20 | * @author Pablo F. Alcantarilla, Jesus Nuevo |
| 21 | * @note This code is derived from FED/FJ library from Grewenig et al., |
| 22 | * The FED/FJ library allows solving more advanced problems |
| 23 | * Please look at the following papers for more information about FED: |
| 24 | * [1] S. Grewenig, J. Weickert, C. Schroers, A. Bruhn. Cyclic Schemes for |
| 25 | * PDE-Based Image Analysis. Technical Report No. 327, Department of |
| 26 | * Mathematics, Saarland University, Saarbrücken, Germany, March 2013 [2] S. |
| 27 | * Grewenig, J. Weickert, A. Bruhn. From box filtering to fast explicit |
| 28 | * diffusion. DAGM, 2010 |
| 29 | * |
| 30 | */ |
| 31 | #include "fed.h" |
| 32 | |
| 33 | #include <opencv2/core.hpp> |
| 34 | |
| 35 | using namespace std; |
| 36 | |
| 37 | //************************************************************************************* |
| 38 | //************************************************************************************* |
| 39 | |
| 40 | /** |
| 41 | * @brief This function allocates an array of the least number of time steps |
| 42 | * such that a certain stopping time for the whole process can be obtained and |
| 43 | * fills it with the respective FED time step sizes for one cycle The function |
| 44 | * returns the number of time steps per cycle or 0 on failure |
| 45 | * @param T Desired process stopping time |
| 46 | * @param M Desired number of cycles |
| 47 | * @param tau_max Stability limit for the explicit scheme |
| 48 | * @param reordering Reordering flag |
| 49 | * @param tau The vector with the dynamic step sizes |
| 50 | */ |
| 51 | int fed_tau_by_process_timeV2(const float& T, const int& M, |
| 52 | const float& tau_max, const bool& reordering, |
| 53 | std::vector<float>& tau) { |
| 54 | // All cycles have the same fraction of the stopping time |
| 55 | return fed_tau_by_cycle_timeV2(T / (float)M, tau_max, reordering, tau); |
| 56 | } |
| 57 | |
| 58 | //************************************************************************************* |
| 59 | //************************************************************************************* |
| 60 | |
| 61 | /** |
| 62 | * @brief This function allocates an array of the least number of time steps |
| 63 | * such that a certain stopping time for the whole process can be obtained and |
| 64 | * fills it it with the respective FED time step sizes for one cycle The |
| 65 | * function returns the number of time steps per cycle or 0 on failure |
| 66 | * @param t Desired cycle stopping time |
| 67 | * @param tau_max Stability limit for the explicit scheme |
| 68 | * @param reordering Reordering flag |
| 69 | * @param tau The vector with the dynamic step sizes |
| 70 | */ |
| 71 | inline int fed_tau_by_cycle_timeV2(const float& t, const float& tau_max, |
| 72 | const bool& reordering, |
| 73 | std::vector<float>& tau) { |
| 74 | int n = 0; // Number of time steps |
| 75 | float scale = 0.0; // Ratio of t we search to maximal t |
| 76 | |
| 77 | // Compute necessary number of time steps |
| 78 | n = (int)(ceilf(sqrtf(3.0f * t / tau_max + 0.25f) - 0.5f - 1.0e-8f) + 0.5f); |
| 79 | scale = 3.0f * t / (tau_max * (float)(n * (n + 1))); |
| 80 | |
| 81 | // Call internal FED time step creation routine |
| 82 | return fed_tau_internalV2(n, scale, tau_max, reordering, tau); |
| 83 | } |
| 84 | |
| 85 | //************************************************************************************* |
| 86 | //************************************************************************************* |
| 87 | |
| 88 | /** |
| 89 | * @brief This function allocates an array of time steps and fills it with FED |
| 90 | * time step sizes |
| 91 | * The function returns the number of time steps per cycle or 0 on failure |
| 92 | * @param n Number of internal steps |
| 93 | * @param scale Ratio of t we search to maximal t |
| 94 | * @param tau_max Stability limit for the explicit scheme |
| 95 | * @param reordering Reordering flag |
| 96 | * @param tau The vector with the dynamic step sizes |
| 97 | */ |
| 98 | inline int fed_tau_internalV2(const int& n, const float& scale, |
| 99 | const float& tau_max, const bool& reordering, |
| 100 | std::vector<float>& tau) { |
| 101 | if (n <= 0) { |
| 102 | return 0; |
| 103 | } |
| 104 | |
| 105 | // Allocate memory for the time step size (Helper vector for unsorted taus) |
| 106 | vector<float> tauh(n); |
| 107 | |
| 108 | // Compute time saver |
| 109 | float c = 1.0f / (4.0f * n + 2.0f); |
| 110 | float d = scale * tau_max / 2.0f; |
| 111 | |
| 112 | // Set up originally ordered tau vector |
| 113 | for (int k = 0; k < n; ++k) { |
| 114 | float h = cos((float)CV_PI * (2.0f * k + 1.0f) * c); |
| 115 | tauh[k] = d / (h * h); |
| 116 | } |
| 117 | |
| 118 | if (!reordering || n == 1) { |
| 119 | std::swap(tau, tauh); |
| 120 | } else { |
| 121 | // Permute list of time steps according to chosen reordering function |
| 122 | |
| 123 | // Choose kappa cycle with k = n/2 |
| 124 | // This is a heuristic. We can use Leja ordering instead!! |
| 125 | int kappa = n / 2; |
| 126 | |
| 127 | // Get modulus for permutation |
| 128 | int prime = n + 1; |
| 129 | |
| 130 | while (!fed_is_prime_internalV2(prime)) prime++; |
| 131 | |
| 132 | // Perform permutation |
| 133 | tau.resize(n); |
| 134 | for (int k = 0, l = 0; l < n; ++k, ++l) { |
| 135 | int index = 0; |
| 136 | while ((index = ((k + 1) * kappa) % prime - 1) >= n) { |
| 137 | k++; |
| 138 | } |
| 139 | |
| 140 | tau[l] = tauh[index]; |
| 141 | } |
| 142 | } |
| 143 | |
| 144 | return n; |
| 145 | } |
| 146 | |
| 147 | //************************************************************************************* |
| 148 | //************************************************************************************* |
| 149 | |
| 150 | /** |
| 151 | * @brief This function checks if a number is prime or not |
| 152 | * @param number Number to check if it is prime or not |
| 153 | * @return true if the number is prime |
| 154 | */ |
| 155 | inline bool fed_is_prime_internalV2(const int& number) { |
| 156 | bool is_prime = false; |
| 157 | |
| 158 | if (number <= 1) { |
| 159 | return false; |
| 160 | } else if (number == 1 || number == 2 || number == 3 || number == 5 || |
| 161 | number == 7) { |
| 162 | return true; |
| 163 | } else if ((number % 2) == 0 || (number % 3) == 0 || (number % 5) == 0 || |
| 164 | (number % 7) == 0) { |
| 165 | return false; |
| 166 | } else { |
| 167 | is_prime = true; |
| 168 | int upperLimit = (int)sqrt(1.0f + number); |
| 169 | int divisor = 11; |
| 170 | |
| 171 | while (divisor <= upperLimit) { |
| 172 | if (number % divisor == 0) { |
| 173 | is_prime = false; |
| 174 | } |
| 175 | |
| 176 | divisor += 2; |
| 177 | } |
| 178 | |
| 179 | return is_prime; |
| 180 | } |
| 181 | } |