Commit 9fc90f40 authored by Ievgen Khvedchenia's avatar Ievgen Khvedchenia

Merged nldiffusion functions into one module with removal of duplicate functions

parent 2df72426
...@@ -8,11 +8,11 @@ ...@@ -8,11 +8,11 @@
#include "AKAZEFeatures.h" #include "AKAZEFeatures.h"
#include "../kaze/fed.h" #include "../kaze/fed.h"
#include "nldiffusion_functions.h" #include "../kaze/nldiffusion_functions.h"
using namespace std; using namespace std;
using namespace cv; using namespace cv;
using namespace cv::details::akaze; using namespace cv::details::kaze;
/* ************************************************************************* */ /* ************************************************************************* */
/** /**
...@@ -154,7 +154,7 @@ int AKAZEFeatures::Create_Nonlinear_Scale_Space(const cv::Mat& img) { ...@@ -154,7 +154,7 @@ int AKAZEFeatures::Create_Nonlinear_Scale_Space(const cv::Mat& img) {
// Perform FED n inner steps // Perform FED n inner steps
for (int j = 0; j < nsteps_[i - 1]; j++) { for (int j = 0; j < nsteps_[i - 1]; j++) {
nld_step_scalar(evolution_[i].Lt, evolution_[i].Lflow, evolution_[i].Lstep, tsteps_[i - 1][j]); cv::details::kaze::nld_step_scalar(evolution_[i].Lt, evolution_[i].Lflow, evolution_[i].Lstep, tsteps_[i - 1][j]);
} }
} }
......
This diff is collapsed.
/**
* @file nldiffusion_functions.h
* @brief Functions for nonlinear diffusion filtering applications
* @date Sep 15, 2013
* @author Pablo F. Alcantarilla, Jesus Nuevo
*/
#ifndef AKAZE_NLDIFFUSION_FUNCTIONS_H
#define AKAZE_NLDIFFUSION_FUNCTIONS_H
/* ************************************************************************* */
// Includes
#include "precomp.hpp"
/* ************************************************************************* */
// Declaration of functions
namespace cv {
namespace details {
namespace akaze {
void gaussian_2D_convolution(const cv::Mat& src, cv::Mat& dst, int ksize_x, int ksize_y, float sigma);
void image_derivatives_scharr(const cv::Mat& src, cv::Mat& dst, int xorder, int yorder);
void pm_g1(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, const float& k);
void pm_g2(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, const float& k);
void weickert_diffusivity(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, const float& k);
void charbonnier_diffusivity(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, const float& k);
float compute_k_percentile(const cv::Mat& img, float perc, float gscale, int nbins, int ksize_x, int ksize_y);
void compute_scharr_derivatives(const cv::Mat& src, cv::Mat& dst, int xorder, int, int scale);
void nld_step_scalar(cv::Mat& Ld, const cv::Mat& c, cv::Mat& Lstep, const float& stepsize);
void halfsample_image(const cv::Mat& src, cv::Mat& dst);
void compute_derivative_kernels(cv::OutputArray kx_, cv::OutputArray ky_, int dx, int dy, int scale);
bool check_maximum_neighbourhood(const cv::Mat& img, int dsize, float value, int row, int col, bool same_img);
}
}
}
#endif
//============================================================================= //=============================================================================
// //
// nldiffusion_functions.cpp // nldiffusion_functions.cpp
...@@ -64,7 +63,23 @@ namespace cv { ...@@ -64,7 +63,23 @@ namespace cv {
} }
// Perform the Gaussian Smoothing with border replication // Perform the Gaussian Smoothing with border replication
GaussianBlur(src, dst, Size(ksize_x_, ksize_y_), sigma, sigma, cv::BORDER_REPLICATE); GaussianBlur(src, dst, Size(ksize_x_, ksize_y_), sigma, sigma, BORDER_REPLICATE);
}
/* ************************************************************************* */
/**
* @brief This function computes image derivatives with Scharr kernel
* @param src Input image
* @param dst Output image
* @param xorder Derivative order in X-direction (horizontal)
* @param yorder Derivative order in Y-direction (vertical)
* @note Scharr operator approximates better rotation invariance than
* other stencils such as Sobel. See Weickert and Scharr,
* A Scheme for Coherence-Enhancing Diffusion Filtering with Optimized Rotation Invariance,
* Journal of Visual Communication and Image Representation 2002
*/
void image_derivatives_scharr(const cv::Mat& src, cv::Mat& dst, int xorder, int yorder) {
Scharr(src, dst, CV_32F, xorder, yorder, 1.0, 0, BORDER_DEFAULT);
} }
/* ************************************************************************* */ /* ************************************************************************* */
...@@ -90,12 +105,12 @@ namespace cv { ...@@ -90,12 +105,12 @@ namespace cv {
* @param k Contrast factor parameter * @param k Contrast factor parameter
*/ */
void pm_g2(const cv::Mat &Lx, const cv::Mat& Ly, cv::Mat& dst, float k) { void pm_g2(const cv::Mat &Lx, const cv::Mat& Ly, cv::Mat& dst, float k) {
dst = 1. / (1. + (Lx.mul(Lx) + Ly.mul(Ly)) / (k*k)); dst = 1.0f / (1.0f + (Lx.mul(Lx) + Ly.mul(Ly)) / (k*k));
} }
/* ************************************************************************* */ /* ************************************************************************* */
/** /**
* @brief This function computes Weickert conductivity coefficient g3 * @brief This function computes Weickert conductivity coefficient gw
* @param Lx First order image derivative in X-direction (horizontal) * @param Lx First order image derivative in X-direction (horizontal)
* @param Ly First order image derivative in Y-direction (vertical) * @param Ly First order image derivative in Y-direction (vertical)
* @param dst Output image * @param dst Output image
...@@ -107,10 +122,28 @@ namespace cv { ...@@ -107,10 +122,28 @@ namespace cv {
void weickert_diffusivity(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, float k) { void weickert_diffusivity(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, float k) {
Mat modg; Mat modg;
cv::pow((Lx.mul(Lx) + Ly.mul(Ly)) / (k*k), 4, modg); cv::pow((Lx.mul(Lx) + Ly.mul(Ly)) / (k*k), 4, modg);
cv::exp(-3.315 / modg, dst); cv::exp(-3.315f / modg, dst);
dst = 1.0f - dst; dst = 1.0f - dst;
} }
/* ************************************************************************* */
/**
* @brief This function computes Charbonnier conductivity coefficient gc
* gc = 1 / sqrt(1 + dL^2 / k^2)
* @param Lx First order image derivative in X-direction (horizontal)
* @param Ly First order image derivative in Y-direction (vertical)
* @param dst Output image
* @param k Contrast factor parameter
* @note For more information check the following paper: J. Weickert
* Applications of nonlinear diffusion in image processing and computer vision,
* Proceedings of Algorithmy 2000
*/
void charbonnier_diffusivity(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, float k) {
Mat den;
cv::sqrt(1.0f + (Lx.mul(Lx) + Ly.mul(Ly)) / (k*k), den);
dst = 1.0f / den;
}
/* ************************************************************************* */ /* ************************************************************************* */
/** /**
* @brief This function computes a good empirical value for the k contrast factor * @brief This function computes a good empirical value for the k contrast factor
...@@ -182,8 +215,7 @@ namespace cv { ...@@ -182,8 +215,7 @@ namespace cv {
} }
// Now find the perc of the histogram percentile // Now find the perc of the histogram percentile
nthreshold = (size_t)(npoints*perc); nthreshold = (int)(npoints*perc);
for (k = 0; nelements < nthreshold && k < nbins; k++) { for (k = 0; nelements < nthreshold && k < nbins; k++) {
nelements = nelements + hist[k]; nelements = nelements + hist[k];
...@@ -206,7 +238,7 @@ namespace cv { ...@@ -206,7 +238,7 @@ namespace cv {
* @param dst Output image * @param dst Output image
* @param xorder Derivative order in X-direction (horizontal) * @param xorder Derivative order in X-direction (horizontal)
* @param yorder Derivative order in Y-direction (vertical) * @param yorder Derivative order in Y-direction (vertical)
* @param scale Scale factor or derivative size * @param scale Scale factor for the derivative size
*/ */
void compute_scharr_derivatives(const cv::Mat& src, cv::Mat& dst, int xorder, int yorder, int scale) { void compute_scharr_derivatives(const cv::Mat& src, cv::Mat& dst, int xorder, int yorder, int scale) {
Mat kx, ky; Mat kx, ky;
...@@ -260,15 +292,15 @@ namespace cv { ...@@ -260,15 +292,15 @@ namespace cv {
/* ************************************************************************* */ /* ************************************************************************* */
/** /**
* @brief This function performs a scalar non-linear diffusion step * @brief This function performs a scalar non-linear diffusion step
* @param Ld2 Output image in the evolution * @param Ld2 Output image in the evolution
* @param c Conductivity image * @param c Conductivity image
* @param Lstep Previous image in the evolution * @param Lstep Previous image in the evolution
* @param stepsize The step size in time units * @param stepsize The step size in time units
* @note Forward Euler Scheme 3x3 stencil * @note Forward Euler Scheme 3x3 stencil
* The function c is a scalar value that depends on the gradient norm * The function c is a scalar value that depends on the gradient norm
* dL_by_ds = d(c dL_by_dx)_by_dx + d(c dL_by_dy)_by_dy * dL_by_ds = d(c dL_by_dx)_by_dx + d(c dL_by_dy)_by_dy
*/ */
void nld_step_scalar(cv::Mat& Ld, const cv::Mat& c, cv::Mat& Lstep, float stepsize) { void nld_step_scalar(cv::Mat& Ld, const cv::Mat& c, cv::Mat& Lstep, float stepsize) {
#ifdef _OPENMP #ifdef _OPENMP
...@@ -288,8 +320,7 @@ namespace cv { ...@@ -288,8 +320,7 @@ namespace cv {
float xpos = ((*(c.ptr<float>(0) + j)) + (*(c.ptr<float>(0) + j + 1)))*((*(Ld.ptr<float>(0) + j + 1)) - (*(Ld.ptr<float>(0) + j))); float xpos = ((*(c.ptr<float>(0) + j)) + (*(c.ptr<float>(0) + j + 1)))*((*(Ld.ptr<float>(0) + j + 1)) - (*(Ld.ptr<float>(0) + j)));
float xneg = ((*(c.ptr<float>(0) + j - 1)) + (*(c.ptr<float>(0) + j)))*((*(Ld.ptr<float>(0) + j)) - (*(Ld.ptr<float>(0) + j - 1))); float xneg = ((*(c.ptr<float>(0) + j - 1)) + (*(c.ptr<float>(0) + j)))*((*(Ld.ptr<float>(0) + j)) - (*(Ld.ptr<float>(0) + j - 1)));
float ypos = ((*(c.ptr<float>(0) + j)) + (*(c.ptr<float>(1) + j)))*((*(Ld.ptr<float>(1) + j)) - (*(Ld.ptr<float>(0) + j))); float ypos = ((*(c.ptr<float>(0) + j)) + (*(c.ptr<float>(1) + j)))*((*(Ld.ptr<float>(1) + j)) - (*(Ld.ptr<float>(0) + j)));
float yneg = ((*(c.ptr<float>(0) + j)) + (*(c.ptr<float>(0) + j)))*((*(Ld.ptr<float>(0) + j)) - (*(Ld.ptr<float>(0) + j))); *(Lstep.ptr<float>(0) + j) = 0.5f*stepsize*(xpos - xneg + ypos);
*(Lstep.ptr<float>(0) + j) = 0.5f*stepsize*(xpos - xneg + ypos - yneg);
} }
for (int j = 1; j < Lstep.cols - 1; j++) { for (int j = 1; j < Lstep.cols - 1; j++) {
...@@ -309,16 +340,29 @@ namespace cv { ...@@ -309,16 +340,29 @@ namespace cv {
} }
for (int i = 1; i < Lstep.rows - 1; i++) { for (int i = 1; i < Lstep.rows - 1; i++) {
float xpos = ((*(c.ptr<float>(i)+Lstep.cols - 1)) + (*(c.ptr<float>(i)+Lstep.cols - 1)))*((*(Ld.ptr<float>(i)+Lstep.cols - 1)) - (*(Ld.ptr<float>(i)+Lstep.cols - 1)));
float xneg = ((*(c.ptr<float>(i)+Lstep.cols - 2)) + (*(c.ptr<float>(i)+Lstep.cols - 1)))*((*(Ld.ptr<float>(i)+Lstep.cols - 1)) - (*(Ld.ptr<float>(i)+Lstep.cols - 2))); float xneg = ((*(c.ptr<float>(i)+Lstep.cols - 2)) + (*(c.ptr<float>(i)+Lstep.cols - 1)))*((*(Ld.ptr<float>(i)+Lstep.cols - 1)) - (*(Ld.ptr<float>(i)+Lstep.cols - 2)));
float ypos = ((*(c.ptr<float>(i)+Lstep.cols - 1)) + (*(c.ptr<float>(i + 1) + Lstep.cols - 1)))*((*(Ld.ptr<float>(i + 1) + Lstep.cols - 1)) - (*(Ld.ptr<float>(i)+Lstep.cols - 1))); float ypos = ((*(c.ptr<float>(i)+Lstep.cols - 1)) + (*(c.ptr<float>(i + 1) + Lstep.cols - 1)))*((*(Ld.ptr<float>(i + 1) + Lstep.cols - 1)) - (*(Ld.ptr<float>(i)+Lstep.cols - 1)));
float yneg = ((*(c.ptr<float>(i - 1) + Lstep.cols - 1)) + (*(c.ptr<float>(i)+Lstep.cols - 1)))*((*(Ld.ptr<float>(i)+Lstep.cols - 1)) - (*(Ld.ptr<float>(i - 1) + Lstep.cols - 1))); float yneg = ((*(c.ptr<float>(i - 1) + Lstep.cols - 1)) + (*(c.ptr<float>(i)+Lstep.cols - 1)))*((*(Ld.ptr<float>(i)+Lstep.cols - 1)) - (*(Ld.ptr<float>(i - 1) + Lstep.cols - 1)));
*(Lstep.ptr<float>(i)+Lstep.cols - 1) = 0.5f*stepsize*(xpos - xneg + ypos - yneg); *(Lstep.ptr<float>(i)+Lstep.cols - 1) = 0.5f*stepsize*(-xneg + ypos - yneg);
} }
Ld = Ld + Lstep; Ld = Ld + Lstep;
} }
/* ************************************************************************* */
/**
* @brief This function downsamples the input image using OpenCV resize
* @param img Input image to be downsampled
* @param dst Output image with half of the resolution of the input image
*/
void halfsample_image(const cv::Mat& src, cv::Mat& dst) {
// Make sure the destination image is of the right size
CV_Assert(src.cols / 2 == dst.cols);
CV_Assert(src.rows / 2 == dst.rows);
resize(src, dst, dst.size(), 0, 0, cv::INTER_AREA);
}
/* ************************************************************************* */ /* ************************************************************************* */
/** /**
* @brief This function checks if a given pixel is a maximum in a local neighbourhood * @brief This function checks if a given pixel is a maximum in a local neighbourhood
......
...@@ -11,11 +11,12 @@ ...@@ -11,11 +11,12 @@
#ifndef KAZE_NLDIFFUSION_FUNCTIONS_H #ifndef KAZE_NLDIFFUSION_FUNCTIONS_H
#define KAZE_NLDIFFUSION_FUNCTIONS_H #define KAZE_NLDIFFUSION_FUNCTIONS_H
/* ************************************************************************* */
// Includes // Includes
#include "precomp.hpp" #include "precomp.hpp"
//************************************************************************************* /* ************************************************************************* */
//************************************************************************************* // Declaration of functions
namespace cv { namespace cv {
namespace details { namespace details {
...@@ -28,11 +29,14 @@ namespace cv { ...@@ -28,11 +29,14 @@ namespace cv {
void pm_g1(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, float k); void pm_g1(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, float k);
void pm_g2(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, float k); void pm_g2(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, float k);
void weickert_diffusivity(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, float k); void weickert_diffusivity(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, float k);
void charbonnier_diffusivity(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, float k);
float compute_k_percentile(const cv::Mat& img, float perc, float gscale, int nbins, int ksize_x, int ksize_y); float compute_k_percentile(const cv::Mat& img, float perc, float gscale, int nbins, int ksize_x, int ksize_y);
// Image derivatives // Image derivatives
void compute_scharr_derivatives(const cv::Mat& src, cv::Mat& dst, int xorder, int yorder, int scale); void compute_scharr_derivatives(const cv::Mat& src, cv::Mat& dst, int xorder, int yorder, int scale);
void compute_derivative_kernels(cv::OutputArray _kx, cv::OutputArray _ky, int dx, int dy, int scale); void compute_derivative_kernels(cv::OutputArray _kx, cv::OutputArray _ky, int dx, int dy, int scale);
void image_derivatives_scharr(const cv::Mat& src, cv::Mat& dst, int xorder, int yorder);
// Nonlinear diffusion filtering scalar step // Nonlinear diffusion filtering scalar step
void nld_step_scalar(cv::Mat& Ld, const cv::Mat& c, cv::Mat& Lstep, float stepsize); void nld_step_scalar(cv::Mat& Ld, const cv::Mat& c, cv::Mat& Lstep, float stepsize);
...@@ -40,6 +44,8 @@ namespace cv { ...@@ -40,6 +44,8 @@ namespace cv {
// For non-maxima suppresion // For non-maxima suppresion
bool check_maximum_neighbourhood(const cv::Mat& img, int dsize, float value, int row, int col, bool same_img); bool check_maximum_neighbourhood(const cv::Mat& img, int dsize, float value, int row, int col, bool same_img);
// Image downsampling
void halfsample_image(const cv::Mat& src, cv::Mat& dst);
} }
} }
} }
......
...@@ -177,4 +177,4 @@ TEST(Features2d_Detector_Keypoints_AKAZE, validation) ...@@ -177,4 +177,4 @@ TEST(Features2d_Detector_Keypoints_AKAZE, validation)
{ {
CV_FeatureDetectorKeypointsTest test(Algorithm::create<FeatureDetector>("Feature2D.AKAZE")); CV_FeatureDetectorKeypointsTest test(Algorithm::create<FeatureDetector>("Feature2D.AKAZE"));
test.safe_run(); test.safe_run();
} }
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment