193 lines
6.2 KiB
C++
193 lines
6.2 KiB
C++
//=============================================================================
|
|
//
|
|
// fed.cpp
|
|
// Authors: Pablo F. Alcantarilla (1), Jesus Nuevo (2)
|
|
// Institutions: Georgia Institute of Technology (1)
|
|
// TrueVision Solutions (2)
|
|
// Date: 15/09/2013
|
|
// Email: pablofdezalc@gmail.com
|
|
//
|
|
// AKAZE Features Copyright 2013, Pablo F. Alcantarilla, Jesus Nuevo
|
|
// All Rights Reserved
|
|
// See LICENSE for the license information
|
|
//=============================================================================
|
|
|
|
/**
|
|
* @file fed.cpp
|
|
* @brief Functions for performing Fast Explicit Diffusion and building the
|
|
* nonlinear scale space
|
|
* @date Sep 15, 2013
|
|
* @author Pablo F. Alcantarilla, Jesus Nuevo
|
|
* @note This code is derived from FED/FJ library from Grewenig et al.,
|
|
* The FED/FJ library allows solving more advanced problems
|
|
* Please look at the following papers for more information about FED:
|
|
* [1] S. Grewenig, J. Weickert, C. Schroers, A. Bruhn. Cyclic Schemes for
|
|
* PDE-Based Image Analysis. Technical Report No. 327, Department of Mathematics,
|
|
* Saarland University, Saarbrücken, Germany, March 2013
|
|
* [2] S. Grewenig, J. Weickert, A. Bruhn. From box filtering to fast explicit diffusion.
|
|
* DAGM, 2010
|
|
*
|
|
*/
|
|
#include "precomp.hpp"
|
|
#include "fed.h"
|
|
|
|
using namespace std;
|
|
|
|
//*************************************************************************************
|
|
//*************************************************************************************
|
|
|
|
/**
|
|
* @brief This function allocates an array of the least number of time steps such
|
|
* that a certain stopping time for the whole process can be obtained and fills
|
|
* it with the respective FED time step sizes for one cycle
|
|
* The function returns the number of time steps per cycle or 0 on failure
|
|
* @param T Desired process stopping time
|
|
* @param M Desired number of cycles
|
|
* @param tau_max Stability limit for the explicit scheme
|
|
* @param reordering Reordering flag
|
|
* @param tau The vector with the dynamic step sizes
|
|
*/
|
|
int fed_tau_by_process_time(const float& T, const int& M, const float& tau_max,
|
|
const bool& reordering, std::vector<float>& tau) {
|
|
// All cycles have the same fraction of the stopping time
|
|
return fed_tau_by_cycle_time(T/(float)M,tau_max,reordering,tau);
|
|
}
|
|
|
|
//*************************************************************************************
|
|
//*************************************************************************************
|
|
|
|
/**
|
|
* @brief This function allocates an array of the least number of time steps such
|
|
* that a certain stopping time for the whole process can be obtained and fills it
|
|
* it with the respective FED time step sizes for one cycle
|
|
* The function returns the number of time steps per cycle or 0 on failure
|
|
* @param t Desired cycle stopping time
|
|
* @param tau_max Stability limit for the explicit scheme
|
|
* @param reordering Reordering flag
|
|
* @param tau The vector with the dynamic step sizes
|
|
*/
|
|
int fed_tau_by_cycle_time(const float& t, const float& tau_max,
|
|
const bool& reordering, std::vector<float> &tau) {
|
|
int n = 0; // Number of time steps
|
|
float scale = 0.0; // Ratio of t we search to maximal t
|
|
|
|
// Compute necessary number of time steps
|
|
n = (int)(ceilf(sqrtf(3.0f*t/tau_max+0.25f)-0.5f-1.0e-8f)+ 0.5f);
|
|
scale = 3.0f*t/(tau_max*(float)(n*(n+1)));
|
|
|
|
// Call internal FED time step creation routine
|
|
return fed_tau_internal(n,scale,tau_max,reordering,tau);
|
|
}
|
|
|
|
//*************************************************************************************
|
|
//*************************************************************************************
|
|
|
|
/**
|
|
* @brief This function allocates an array of time steps and fills it with FED
|
|
* time step sizes
|
|
* The function returns the number of time steps per cycle or 0 on failure
|
|
* @param n Number of internal steps
|
|
* @param scale Ratio of t we search to maximal t
|
|
* @param tau_max Stability limit for the explicit scheme
|
|
* @param reordering Reordering flag
|
|
* @param tau The vector with the dynamic step sizes
|
|
*/
|
|
int fed_tau_internal(const int& n, const float& scale, const float& tau_max,
|
|
const bool& reordering, std::vector<float> &tau) {
|
|
float c = 0.0, d = 0.0; // Time savers
|
|
vector<float> tauh; // Helper vector for unsorted taus
|
|
|
|
if (n <= 0) {
|
|
return 0;
|
|
}
|
|
|
|
// Allocate memory for the time step size
|
|
tau = vector<float>(n);
|
|
|
|
if (reordering) {
|
|
tauh = vector<float>(n);
|
|
}
|
|
|
|
// Compute time saver
|
|
c = 1.0f / (4.0f * (float)n + 2.0f);
|
|
d = scale * tau_max / 2.0f;
|
|
|
|
// Set up originally ordered tau vector
|
|
for (int k = 0; k < n; ++k) {
|
|
float h = cosf((float)CV_PI * (2.0f * (float)k + 1.0f) * c);
|
|
|
|
if (reordering) {
|
|
tauh[k] = d / (h * h);
|
|
}
|
|
else {
|
|
tau[k] = d / (h * h);
|
|
}
|
|
}
|
|
|
|
// Permute list of time steps according to chosen reordering function
|
|
int kappa = 0, prime = 0;
|
|
|
|
if (reordering == true) {
|
|
// Choose kappa cycle with k = n/2
|
|
// This is a heuristic. We can use Leja ordering instead!!
|
|
kappa = n / 2;
|
|
|
|
// Get modulus for permutation
|
|
prime = n + 1;
|
|
|
|
while (!fed_is_prime_internal(prime)) {
|
|
prime++;
|
|
}
|
|
|
|
// Perform permutation
|
|
for (int k = 0, l = 0; l < n; ++k, ++l) {
|
|
int index = 0;
|
|
while ((index = ((k+1)*kappa) % prime - 1) >= n) {
|
|
k++;
|
|
}
|
|
|
|
tau[l] = tauh[index];
|
|
}
|
|
}
|
|
|
|
return n;
|
|
}
|
|
|
|
//*************************************************************************************
|
|
//*************************************************************************************
|
|
|
|
/**
|
|
* @brief This function checks if a number is prime or not
|
|
* @param number Number to check if it is prime or not
|
|
* @return true if the number is prime
|
|
*/
|
|
bool fed_is_prime_internal(const int& number) {
|
|
bool is_prime = false;
|
|
|
|
if (number <= 1) {
|
|
return false;
|
|
}
|
|
else if (number == 1 || number == 2 || number == 3 || number == 5 || number == 7) {
|
|
return true;
|
|
}
|
|
else if ((number % 2) == 0 || (number % 3) == 0 || (number % 5) == 0 || (number % 7) == 0) {
|
|
return false;
|
|
}
|
|
else {
|
|
is_prime = true;
|
|
int upperLimit = (int)sqrt(1.0f + number);
|
|
int divisor = 11;
|
|
|
|
while (divisor <= upperLimit ) {
|
|
if (number % divisor == 0)
|
|
{
|
|
is_prime = false;
|
|
}
|
|
|
|
divisor +=2;
|
|
}
|
|
|
|
return is_prime;
|
|
}
|
|
}
|