blob: 835441c9e580af114e783cb77a91bfbf797e3bf5 [file] [log] [blame]
Yash Chainani5458dea2022-06-29 21:05:02 -07001//=============================================================================
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
35using 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 */
51int 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 */
71inline 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 */
98inline 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 */
155inline 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}