|
|
|
@ -24,9 +24,7 @@ |
|
|
|
|
using namespace std; |
|
|
|
|
using namespace cv; |
|
|
|
|
|
|
|
|
|
//*************************************************************************************
|
|
|
|
|
//*************************************************************************************
|
|
|
|
|
|
|
|
|
|
/* ************************************************************************* */ |
|
|
|
|
/**
|
|
|
|
|
* @brief This function smoothes an image with a Gaussian kernel |
|
|
|
|
* @param src Input image |
|
|
|
@ -36,32 +34,30 @@ using namespace cv; |
|
|
|
|
* @param sigma Kernel standard deviation |
|
|
|
|
*/ |
|
|
|
|
void gaussian_2D_convolution(const cv::Mat& src, cv::Mat& dst, const size_t& ksize_x, |
|
|
|
|
const size_t& ksize_y, const float& sigma) { |
|
|
|
|
const size_t& ksize_y, const float& sigma) { |
|
|
|
|
|
|
|
|
|
size_t ksize_x_ = 0, ksize_y_ = 0; |
|
|
|
|
size_t ksize_x_ = 0, ksize_y_ = 0; |
|
|
|
|
|
|
|
|
|
// Compute an appropriate kernel size according to the specified sigma
|
|
|
|
|
if (sigma > ksize_x || sigma > ksize_y || ksize_x == 0 || ksize_y == 0) { |
|
|
|
|
ksize_x_ = ceil(2.0*(1.0 + (sigma-0.8)/(0.3))); |
|
|
|
|
ksize_y_ = ksize_x_; |
|
|
|
|
} |
|
|
|
|
// Compute an appropriate kernel size according to the specified sigma
|
|
|
|
|
if (sigma > ksize_x || sigma > ksize_y || ksize_x == 0 || ksize_y == 0) { |
|
|
|
|
ksize_x_ = ceil(2.0*(1.0 + (sigma - 0.8) / (0.3))); |
|
|
|
|
ksize_y_ = ksize_x_; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// The kernel size must be and odd number
|
|
|
|
|
if ((ksize_x_ % 2) == 0) { |
|
|
|
|
ksize_x_ += 1; |
|
|
|
|
} |
|
|
|
|
// The kernel size must be and odd number
|
|
|
|
|
if ((ksize_x_ % 2) == 0) { |
|
|
|
|
ksize_x_ += 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ((ksize_y_ % 2) == 0) { |
|
|
|
|
ksize_y_ += 1; |
|
|
|
|
} |
|
|
|
|
if ((ksize_y_ % 2) == 0) { |
|
|
|
|
ksize_y_ += 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Perform the Gaussian Smoothing with border replication
|
|
|
|
|
GaussianBlur(src,dst,Size(ksize_x_,ksize_y_),sigma,sigma,BORDER_REPLICATE); |
|
|
|
|
// Perform the Gaussian Smoothing with border replication
|
|
|
|
|
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 |
|
|
|
@ -74,13 +70,11 @@ void gaussian_2D_convolution(const cv::Mat& src, cv::Mat& dst, const size_t& ksi |
|
|
|
|
* Journal of Visual Communication and Image Representation 2002 |
|
|
|
|
*/ |
|
|
|
|
void image_derivatives_scharr(const cv::Mat& src, cv::Mat& dst, |
|
|
|
|
const size_t& xorder, const size_t& yorder) { |
|
|
|
|
Scharr(src,dst,CV_32F,xorder,yorder,1.0,0,BORDER_DEFAULT); |
|
|
|
|
const size_t& xorder, const size_t& yorder) { |
|
|
|
|
Scharr(src, dst, CV_32F, xorder, yorder, 1.0, 0, BORDER_DEFAULT); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//*************************************************************************************
|
|
|
|
|
//*************************************************************************************
|
|
|
|
|
|
|
|
|
|
/* ************************************************************************* */ |
|
|
|
|
/**
|
|
|
|
|
* @brief This function computes the Perona and Malik conductivity coefficient g1 |
|
|
|
|
* g1 = exp(-|dL|^2/k^2) |
|
|
|
@ -90,12 +84,10 @@ void image_derivatives_scharr(const cv::Mat& src, cv::Mat& dst, |
|
|
|
|
* @param k Contrast factor parameter |
|
|
|
|
*/ |
|
|
|
|
void pm_g1(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, const float& k) { |
|
|
|
|
exp(-(Lx.mul(Lx)+Ly.mul(Ly))/(k*k),dst); |
|
|
|
|
exp(-(Lx.mul(Lx) + Ly.mul(Ly)) / (k*k), dst); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//*************************************************************************************
|
|
|
|
|
//*************************************************************************************
|
|
|
|
|
|
|
|
|
|
/* ************************************************************************* */ |
|
|
|
|
/**
|
|
|
|
|
* @brief This function computes the Perona and Malik conductivity coefficient g2 |
|
|
|
|
* g2 = 1 / (1 + dL^2 / k^2) |
|
|
|
@ -105,12 +97,10 @@ void pm_g1(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, const float& k) { |
|
|
|
|
* @param k Contrast factor parameter |
|
|
|
|
*/ |
|
|
|
|
void pm_g2(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, const float& k) { |
|
|
|
|
dst = 1.0/(1.0+(Lx.mul(Lx)+Ly.mul(Ly))/(k*k)); |
|
|
|
|
dst = 1.0 / (1.0 + (Lx.mul(Lx) + Ly.mul(Ly)) / (k*k)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//*************************************************************************************
|
|
|
|
|
//*************************************************************************************
|
|
|
|
|
|
|
|
|
|
/* ************************************************************************* */ |
|
|
|
|
/**
|
|
|
|
|
* @brief This function computes Weickert conductivity coefficient gw |
|
|
|
|
* @param Lx First order image derivative in X-direction (horizontal) |
|
|
|
@ -122,15 +112,13 @@ void pm_g2(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, const float& k) { |
|
|
|
|
* Proceedings of Algorithmy 2000 |
|
|
|
|
*/ |
|
|
|
|
void weickert_diffusivity(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, const float& k) { |
|
|
|
|
Mat modg; |
|
|
|
|
pow((Lx.mul(Lx) + Ly.mul(Ly))/(k*k),4,modg); |
|
|
|
|
cv::exp(-3.315/modg, dst); |
|
|
|
|
dst = 1.0 - dst; |
|
|
|
|
Mat modg; |
|
|
|
|
pow((Lx.mul(Lx) + Ly.mul(Ly)) / (k*k), 4, modg); |
|
|
|
|
cv::exp(-3.315 / modg, dst); |
|
|
|
|
dst = 1.0 - dst; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//*************************************************************************************
|
|
|
|
|
//*************************************************************************************
|
|
|
|
|
|
|
|
|
|
/* ************************************************************************* */ |
|
|
|
|
/**
|
|
|
|
|
* @brief This function computes Charbonnier conductivity coefficient gc |
|
|
|
|
* gc = 1 / sqrt(1 + dL^2 / k^2) |
|
|
|
@ -143,14 +131,12 @@ void weickert_diffusivity(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, co |
|
|
|
|
* Proceedings of Algorithmy 2000 |
|
|
|
|
*/ |
|
|
|
|
void charbonnier_diffusivity(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, const float& k) { |
|
|
|
|
Mat den; |
|
|
|
|
cv::sqrt(1.0+(Lx.mul(Lx)+Ly.mul(Ly))/(k*k),den); |
|
|
|
|
dst = 1.0/ den; |
|
|
|
|
Mat den; |
|
|
|
|
cv::sqrt(1.0 + (Lx.mul(Lx) + Ly.mul(Ly)) / (k*k), den); |
|
|
|
|
dst = 1.0 / den; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//*************************************************************************************
|
|
|
|
|
//*************************************************************************************
|
|
|
|
|
|
|
|
|
|
/* ************************************************************************* */ |
|
|
|
|
/**
|
|
|
|
|
* @brief This function computes a good empirical value for the k contrast factor |
|
|
|
|
* given an input image, the percentile (0-1), the gradient scale and the number of |
|
|
|
@ -163,90 +149,87 @@ void charbonnier_diffusivity(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, |
|
|
|
|
* @param ksize_y Kernel size in Y-direction (vertical) for the Gaussian smoothing kernel |
|
|
|
|
* @return k contrast factor |
|
|
|
|
*/ |
|
|
|
|
float compute_k_percentile(const cv::Mat& img, const float& perc, const float& gscale, |
|
|
|
|
const size_t& nbins, const size_t& ksize_x, const size_t& ksize_y) { |
|
|
|
|
|
|
|
|
|
size_t nbin = 0, nelements = 0, nthreshold = 0, k = 0; |
|
|
|
|
float kperc = 0.0, modg = 0.0, lx = 0.0, ly = 0.0; |
|
|
|
|
float npoints = 0.0; |
|
|
|
|
float hmax = 0.0; |
|
|
|
|
|
|
|
|
|
// Create the array for the histogram
|
|
|
|
|
float *hist = new float[nbins]; |
|
|
|
|
|
|
|
|
|
// Create the matrices
|
|
|
|
|
Mat gaussian = Mat::zeros(img.rows,img.cols,CV_32F); |
|
|
|
|
Mat Lx = Mat::zeros(img.rows,img.cols,CV_32F); |
|
|
|
|
Mat Ly = Mat::zeros(img.rows,img.cols,CV_32F); |
|
|
|
|
|
|
|
|
|
// Set the histogram to zero, just in case
|
|
|
|
|
for (size_t i = 0; i < nbins; i++) { |
|
|
|
|
hist[i] = 0.0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Perform the Gaussian convolution
|
|
|
|
|
gaussian_2D_convolution(img,gaussian,ksize_x,ksize_y,gscale); |
|
|
|
|
|
|
|
|
|
// Compute the Gaussian derivatives Lx and Ly
|
|
|
|
|
image_derivatives_scharr(gaussian,Lx,1,0); |
|
|
|
|
image_derivatives_scharr(gaussian,Ly,0,1); |
|
|
|
|
|
|
|
|
|
// Skip the borders for computing the histogram
|
|
|
|
|
for (int i = 1; i < gaussian.rows-1; i++) { |
|
|
|
|
for (int j = 1; j < gaussian.cols-1; j++) { |
|
|
|
|
lx = *(Lx.ptr<float>(i)+j); |
|
|
|
|
ly = *(Ly.ptr<float>(i)+j); |
|
|
|
|
modg = sqrt(lx*lx + ly*ly); |
|
|
|
|
|
|
|
|
|
// Get the maximum
|
|
|
|
|
if (modg > hmax) { |
|
|
|
|
hmax = modg; |
|
|
|
|
} |
|
|
|
|
float compute_k_percentile(const cv::Mat& img, float perc, float gscale, |
|
|
|
|
size_t nbins, size_t ksize_x, size_t ksize_y) { |
|
|
|
|
|
|
|
|
|
size_t nbin = 0, nelements = 0, nthreshold = 0, k = 0; |
|
|
|
|
float kperc = 0.0, modg = 0.0, lx = 0.0, ly = 0.0; |
|
|
|
|
float npoints = 0.0; |
|
|
|
|
float hmax = 0.0; |
|
|
|
|
|
|
|
|
|
// Create the array for the histogram
|
|
|
|
|
float *hist = new float[nbins]; |
|
|
|
|
|
|
|
|
|
// Create the matrices
|
|
|
|
|
cv::Mat gaussian = cv::Mat::zeros(img.rows, img.cols, CV_32F); |
|
|
|
|
cv::Mat Lx = cv::Mat::zeros(img.rows, img.cols, CV_32F); |
|
|
|
|
cv::Mat Ly = cv::Mat::zeros(img.rows, img.cols, CV_32F); |
|
|
|
|
|
|
|
|
|
// Set the histogram to zero
|
|
|
|
|
for (size_t i = 0; i < nbins; i++) |
|
|
|
|
hist[i] = 0.0; |
|
|
|
|
|
|
|
|
|
// Perform the Gaussian convolution
|
|
|
|
|
gaussian_2D_convolution(img, gaussian, ksize_x, ksize_y, gscale); |
|
|
|
|
|
|
|
|
|
// Compute the Gaussian derivatives Lx and Ly
|
|
|
|
|
image_derivatives_scharr(gaussian, Lx, 1, 0); |
|
|
|
|
image_derivatives_scharr(gaussian, Ly, 0, 1); |
|
|
|
|
|
|
|
|
|
// Skip the borders for computing the histogram
|
|
|
|
|
for (int i = 1; i < gaussian.rows - 1; i++) { |
|
|
|
|
for (int j = 1; j < gaussian.cols - 1; j++) { |
|
|
|
|
lx = *(Lx.ptr<float>(i)+j); |
|
|
|
|
ly = *(Ly.ptr<float>(i)+j); |
|
|
|
|
modg = sqrt(lx*lx + ly*ly); |
|
|
|
|
|
|
|
|
|
// Get the maximum
|
|
|
|
|
if (modg > hmax) { |
|
|
|
|
hmax = modg; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Skip the borders for computing the histogram
|
|
|
|
|
for (int i = 1; i < gaussian.rows-1; i++) { |
|
|
|
|
for (int j = 1; j < gaussian.cols-1; j++) { |
|
|
|
|
lx = *(Lx.ptr<float>(i)+j); |
|
|
|
|
ly = *(Ly.ptr<float>(i)+j); |
|
|
|
|
modg = sqrt(lx*lx + ly*ly); |
|
|
|
|
// Skip the borders for computing the histogram
|
|
|
|
|
for (int i = 1; i < gaussian.rows - 1; i++) { |
|
|
|
|
for (int j = 1; j < gaussian.cols - 1; j++) { |
|
|
|
|
lx = *(Lx.ptr<float>(i)+j); |
|
|
|
|
ly = *(Ly.ptr<float>(i)+j); |
|
|
|
|
modg = sqrt(lx*lx + ly*ly); |
|
|
|
|
|
|
|
|
|
// Find the correspondent bin
|
|
|
|
|
if (modg != 0.0) { |
|
|
|
|
nbin = floor(nbins*(modg/hmax)); |
|
|
|
|
// Find the correspondent bin
|
|
|
|
|
if (modg != 0.0) { |
|
|
|
|
nbin = floor(nbins*(modg / hmax)); |
|
|
|
|
|
|
|
|
|
if (nbin == nbins) { |
|
|
|
|
nbin--; |
|
|
|
|
} |
|
|
|
|
if (nbin == nbins) { |
|
|
|
|
nbin--; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
hist[nbin]++; |
|
|
|
|
npoints++; |
|
|
|
|
} |
|
|
|
|
hist[nbin]++; |
|
|
|
|
npoints++; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Now find the perc of the histogram percentile
|
|
|
|
|
nthreshold = (size_t)(npoints*perc); |
|
|
|
|
// Now find the perc of the histogram percentile
|
|
|
|
|
nthreshold = (size_t)(npoints*perc); |
|
|
|
|
|
|
|
|
|
for (k = 0; nelements < nthreshold && k < nbins; k++) { |
|
|
|
|
nelements = nelements + hist[k]; |
|
|
|
|
} |
|
|
|
|
for (k = 0; nelements < nthreshold && k < nbins; k++) { |
|
|
|
|
nelements = nelements + hist[k]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (nelements < nthreshold) { |
|
|
|
|
kperc = 0.03; |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
kperc = hmax*((float)(k)/(float)nbins); |
|
|
|
|
} |
|
|
|
|
if (nelements < nthreshold) { |
|
|
|
|
kperc = 0.03; |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
kperc = hmax*((float)(k) / (float)nbins); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
delete [] hist; |
|
|
|
|
return kperc; |
|
|
|
|
delete[] hist; |
|
|
|
|
return kperc; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//*************************************************************************************
|
|
|
|
|
//*************************************************************************************
|
|
|
|
|
|
|
|
|
|
/* ************************************************************************* */ |
|
|
|
|
/**
|
|
|
|
|
* @brief This function computes Scharr image derivatives |
|
|
|
|
* @param src Input image |
|
|
|
@ -256,16 +239,14 @@ float compute_k_percentile(const cv::Mat& img, const float& perc, const float& g |
|
|
|
|
* @param scale Scale factor for the derivative size |
|
|
|
|
*/ |
|
|
|
|
void compute_scharr_derivatives(const cv::Mat& src, cv::Mat& dst, const size_t& xorder, |
|
|
|
|
const size_t& yorder, const size_t& scale) { |
|
|
|
|
const size_t& yorder, const size_t& scale) { |
|
|
|
|
|
|
|
|
|
Mat kx, ky; |
|
|
|
|
compute_derivative_kernels(kx, ky, xorder,yorder,scale); |
|
|
|
|
sepFilter2D(src,dst,CV_32F,kx,ky); |
|
|
|
|
Mat kx, ky; |
|
|
|
|
compute_derivative_kernels(kx, ky, xorder, yorder, scale); |
|
|
|
|
sepFilter2D(src, dst, CV_32F, kx, ky); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//*************************************************************************************
|
|
|
|
|
//*************************************************************************************
|
|
|
|
|
|
|
|
|
|
/* ************************************************************************* */ |
|
|
|
|
/**
|
|
|
|
|
* @brief This function performs a scalar non-linear diffusion step |
|
|
|
|
* @param Ld2 Output image in the evolution |
|
|
|
@ -281,64 +262,50 @@ void nld_step_scalar(cv::Mat& Ld, const cv::Mat& c, cv::Mat& Lstep, const float& |
|
|
|
|
#ifdef _OPENMP |
|
|
|
|
#pragma omp parallel for schedule(dynamic) |
|
|
|
|
#endif |
|
|
|
|
for (int i = 1; i < Lstep.rows-1; i++) { |
|
|
|
|
for (int j = 1; j < Lstep.cols-1; j++) { |
|
|
|
|
float xpos = ((*(c.ptr<float>(i)+j))+(*(c.ptr<float>(i)+j+1)))*((*(Ld.ptr<float>(i)+j+1))-(*(Ld.ptr<float>(i)+j))); |
|
|
|
|
float xneg = ((*(c.ptr<float>(i)+j-1))+(*(c.ptr<float>(i)+j)))*((*(Ld.ptr<float>(i)+j))-(*(Ld.ptr<float>(i)+j-1))); |
|
|
|
|
|
|
|
|
|
float ypos = ((*(c.ptr<float>(i)+j))+(*(c.ptr<float>(i+1)+j)))*((*(Ld.ptr<float>(i+1)+j))-(*(Ld.ptr<float>(i)+j))); |
|
|
|
|
float yneg = ((*(c.ptr<float>(i-1)+j))+(*(c.ptr<float>(i)+j)))*((*(Ld.ptr<float>(i)+j))-(*(Ld.ptr<float>(i-1)+j))); |
|
|
|
|
|
|
|
|
|
*(Lstep.ptr<float>(i)+j) = 0.5*stepsize*(xpos-xneg + ypos-yneg); |
|
|
|
|
for (int i = 1; i < Lstep.rows - 1; i++) { |
|
|
|
|
for (int j = 1; j < Lstep.cols - 1; j++) { |
|
|
|
|
float xpos = ((*(c.ptr<float>(i)+j)) + (*(c.ptr<float>(i)+j + 1)))*((*(Ld.ptr<float>(i)+j + 1)) - (*(Ld.ptr<float>(i)+j))); |
|
|
|
|
float xneg = ((*(c.ptr<float>(i)+j - 1)) + (*(c.ptr<float>(i)+j)))*((*(Ld.ptr<float>(i)+j)) - (*(Ld.ptr<float>(i)+j - 1))); |
|
|
|
|
float ypos = ((*(c.ptr<float>(i)+j)) + (*(c.ptr<float>(i + 1) + j)))*((*(Ld.ptr<float>(i + 1) + j)) - (*(Ld.ptr<float>(i)+j))); |
|
|
|
|
float yneg = ((*(c.ptr<float>(i - 1) + j)) + (*(c.ptr<float>(i)+j)))*((*(Ld.ptr<float>(i)+j)) - (*(Ld.ptr<float>(i - 1) + j))); |
|
|
|
|
*(Lstep.ptr<float>(i)+j) = 0.5*stepsize*(xpos - xneg + ypos - yneg); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (int j = 1; j < Lstep.cols-1; 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 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.5*stepsize*(xpos-xneg + ypos-yneg); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (int j = 1; j < Lstep.cols-1; j++) { |
|
|
|
|
float xpos = ((*(c.ptr<float>(Lstep.rows-1)+j))+(*(c.ptr<float>(Lstep.rows-1)+j+1)))*((*(Ld.ptr<float>(Lstep.rows-1)+j+1))-(*(Ld.ptr<float>(Lstep.rows-1)+j))); |
|
|
|
|
float xneg = ((*(c.ptr<float>(Lstep.rows-1)+j-1))+(*(c.ptr<float>(Lstep.rows-1)+j)))*((*(Ld.ptr<float>(Lstep.rows-1)+j))-(*(Ld.ptr<float>(Lstep.rows-1)+j-1))); |
|
|
|
|
|
|
|
|
|
float ypos = ((*(c.ptr<float>(Lstep.rows-1)+j))+(*(c.ptr<float>(Lstep.rows-1)+j)))*((*(Ld.ptr<float>(Lstep.rows-1)+j))-(*(Ld.ptr<float>(Lstep.rows-1)+j))); |
|
|
|
|
float yneg = ((*(c.ptr<float>(Lstep.rows-2)+j))+(*(c.ptr<float>(Lstep.rows-1)+j)))*((*(Ld.ptr<float>(Lstep.rows-1)+j))-(*(Ld.ptr<float>(Lstep.rows-2)+j))); |
|
|
|
|
|
|
|
|
|
*(Lstep.ptr<float>(Lstep.rows-1)+j) = 0.5*stepsize*(xpos-xneg + ypos-yneg); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (int i = 1; i < Lstep.rows-1; i++) { |
|
|
|
|
float xpos = ((*(c.ptr<float>(i)))+(*(c.ptr<float>(i)+1)))*((*(Ld.ptr<float>(i)+1))-(*(Ld.ptr<float>(i)))); |
|
|
|
|
float xneg = ((*(c.ptr<float>(i)))+(*(c.ptr<float>(i))))*((*(Ld.ptr<float>(i)))-(*(Ld.ptr<float>(i)))); |
|
|
|
|
|
|
|
|
|
float ypos = ((*(c.ptr<float>(i)))+(*(c.ptr<float>(i+1))))*((*(Ld.ptr<float>(i+1)))-(*(Ld.ptr<float>(i)))); |
|
|
|
|
float yneg = ((*(c.ptr<float>(i-1)))+(*(c.ptr<float>(i))))*((*(Ld.ptr<float>(i)))-(*(Ld.ptr<float>(i-1)))); |
|
|
|
|
|
|
|
|
|
*(Lstep.ptr<float>(i)) = 0.5*stepsize*(xpos-xneg + ypos-yneg); |
|
|
|
|
} |
|
|
|
|
for (int j = 1; j < Lstep.cols - 1; 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 ypos = ((*(c.ptr<float>(0) + j)) + (*(c.ptr<float>(1) + j)))*((*(Ld.ptr<float>(1) + j)) - (*(Ld.ptr<float>(0) + j))); |
|
|
|
|
*(Lstep.ptr<float>(0) + j) = 0.5*stepsize*(xpos - xneg + ypos); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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))); |
|
|
|
|
for (int j = 1; j < Lstep.cols - 1; j++) { |
|
|
|
|
float xpos = ((*(c.ptr<float>(Lstep.rows - 1) + j)) + (*(c.ptr<float>(Lstep.rows - 1) + j + 1)))*((*(Ld.ptr<float>(Lstep.rows - 1) + j + 1)) - (*(Ld.ptr<float>(Lstep.rows - 1) + j))); |
|
|
|
|
float xneg = ((*(c.ptr<float>(Lstep.rows - 1) + j - 1)) + (*(c.ptr<float>(Lstep.rows - 1) + j)))*((*(Ld.ptr<float>(Lstep.rows - 1) + j)) - (*(Ld.ptr<float>(Lstep.rows - 1) + j - 1))); |
|
|
|
|
float ypos = ((*(c.ptr<float>(Lstep.rows - 1) + j)) + (*(c.ptr<float>(Lstep.rows - 1) + j)))*((*(Ld.ptr<float>(Lstep.rows - 1) + j)) - (*(Ld.ptr<float>(Lstep.rows - 1) + j))); |
|
|
|
|
float yneg = ((*(c.ptr<float>(Lstep.rows - 2) + j)) + (*(c.ptr<float>(Lstep.rows - 1) + j)))*((*(Ld.ptr<float>(Lstep.rows - 1) + j)) - (*(Ld.ptr<float>(Lstep.rows - 2) + j))); |
|
|
|
|
*(Lstep.ptr<float>(Lstep.rows - 1) + j) = 0.5*stepsize*(xpos - xneg + ypos - yneg); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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))); |
|
|
|
|
for (int i = 1; i < Lstep.rows - 1; i++) { |
|
|
|
|
float xpos = ((*(c.ptr<float>(i))) + (*(c.ptr<float>(i)+1)))*((*(Ld.ptr<float>(i)+1)) - (*(Ld.ptr<float>(i)))); |
|
|
|
|
float xneg = ((*(c.ptr<float>(i))) + (*(c.ptr<float>(i))))*((*(Ld.ptr<float>(i))) - (*(Ld.ptr<float>(i)))); |
|
|
|
|
float ypos = ((*(c.ptr<float>(i))) + (*(c.ptr<float>(i + 1))))*((*(Ld.ptr<float>(i + 1))) - (*(Ld.ptr<float>(i)))); |
|
|
|
|
float yneg = ((*(c.ptr<float>(i - 1))) + (*(c.ptr<float>(i))))*((*(Ld.ptr<float>(i))) - (*(Ld.ptr<float>(i - 1)))); |
|
|
|
|
*(Lstep.ptr<float>(i)) = 0.5*stepsize*(xpos - xneg + ypos - yneg); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
*(Lstep.ptr<float>(i)+Lstep.cols-1) = 0.5*stepsize*(xpos-xneg + ypos-yneg); |
|
|
|
|
} |
|
|
|
|
for (int i = 1; i < Lstep.rows - 1; i++) { |
|
|
|
|
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 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.5*stepsize*(-xneg + ypos - yneg); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Ld = Ld + Lstep; |
|
|
|
|
Ld = Ld + Lstep; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//*************************************************************************************
|
|
|
|
|
//*************************************************************************************
|
|
|
|
|
|
|
|
|
|
/* ************************************************************************* */ |
|
|
|
|
/**
|
|
|
|
|
* @brief This function downsamples the input image with the kernel [1/4,1/2,1/4] |
|
|
|
|
* @param img Input image to be downsampled |
|
|
|
@ -346,22 +313,20 @@ void nld_step_scalar(cv::Mat& Ld, const cv::Mat& c, cv::Mat& Lstep, const float& |
|
|
|
|
*/ |
|
|
|
|
void downsample_image(const cv::Mat& src, cv::Mat& dst) { |
|
|
|
|
|
|
|
|
|
int i1 = 0, j1 = 0, i2 = 0, j2 = 0; |
|
|
|
|
int i1 = 0, j1 = 0, i2 = 0, j2 = 0; |
|
|
|
|
|
|
|
|
|
for (i1 = 1; i1 < src.rows; i1+=2) { |
|
|
|
|
j2 = 0; |
|
|
|
|
for (j1 = 1; j1 < src.cols; j1+=2) { |
|
|
|
|
*(dst.ptr<float>(i2)+j2) = 0.5*(*(src.ptr<float>(i1)+j1))+0.25*(*(src.ptr<float>(i1)+j1-1) + *(src.ptr<float>(i1)+j1+1)); |
|
|
|
|
j2++; |
|
|
|
|
} |
|
|
|
|
for (i1 = 1; i1 < src.rows; i1 += 2) { |
|
|
|
|
j2 = 0; |
|
|
|
|
for (j1 = 1; j1 < src.cols; j1 += 2) { |
|
|
|
|
*(dst.ptr<float>(i2)+j2) = 0.5*(*(src.ptr<float>(i1)+j1)) + 0.25*(*(src.ptr<float>(i1)+j1 - 1) + *(src.ptr<float>(i1)+j1 + 1)); |
|
|
|
|
j2++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
i2++; |
|
|
|
|
} |
|
|
|
|
i2++; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//*************************************************************************************
|
|
|
|
|
//*************************************************************************************
|
|
|
|
|
|
|
|
|
|
/* ************************************************************************* */ |
|
|
|
|
/**
|
|
|
|
|
* @brief This function downsamples the input image using OpenCV resize |
|
|
|
|
* @param img Input image to be downsampled |
|
|
|
@ -369,15 +334,13 @@ void downsample_image(const cv::Mat& src, cv::Mat& dst) { |
|
|
|
|
*/ |
|
|
|
|
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); |
|
|
|
|
// 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 Compute Scharr derivative kernels for sizes different than 3 |
|
|
|
|
* @param kx_ The derivative kernel in x-direction |
|
|
|
@ -387,45 +350,45 @@ void halfsample_image(const cv::Mat& src, cv::Mat& dst) { |
|
|
|
|
* @param scale The kernel size |
|
|
|
|
*/ |
|
|
|
|
void compute_derivative_kernels(cv::OutputArray kx_, cv::OutputArray ky_, |
|
|
|
|
const size_t& dx, const size_t& dy, const size_t& scale) { |
|
|
|
|
const size_t& dx, const size_t& dy, const size_t& scale) { |
|
|
|
|
|
|
|
|
|
const int ksize = 3 + 2*(scale-1); |
|
|
|
|
const int ksize = 3 + 2 * (scale - 1); |
|
|
|
|
|
|
|
|
|
// The usual Scharr kernel
|
|
|
|
|
if (scale == 1) { |
|
|
|
|
getDerivKernels(kx_,ky_,dx,dy,0,true,CV_32F); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
// The usual Scharr kernel
|
|
|
|
|
if (scale == 1) { |
|
|
|
|
getDerivKernels(kx_, ky_, dx, dy, 0, true, CV_32F); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
kx_.create(ksize,1,CV_32F,-1,true); |
|
|
|
|
ky_.create(ksize,1,CV_32F,-1,true); |
|
|
|
|
Mat kx = kx_.getMat(); |
|
|
|
|
Mat ky = ky_.getMat(); |
|
|
|
|
kx_.create(ksize, 1, CV_32F, -1, true); |
|
|
|
|
ky_.create(ksize, 1, CV_32F, -1, true); |
|
|
|
|
Mat kx = kx_.getMat(); |
|
|
|
|
Mat ky = ky_.getMat(); |
|
|
|
|
|
|
|
|
|
float w = 10.0/3.0; |
|
|
|
|
float norm = 1.0/(2.0*scale*(w+2.0)); |
|
|
|
|
float w = 10.0 / 3.0; |
|
|
|
|
float norm = 1.0 / (2.0*scale*(w + 2.0)); |
|
|
|
|
|
|
|
|
|
for (int k = 0; k < 2; k++) { |
|
|
|
|
Mat* kernel = k == 0 ? &kx : &ky; |
|
|
|
|
int order = k == 0 ? dx : dy; |
|
|
|
|
float kerI[1000]; |
|
|
|
|
for (int k = 0; k < 2; k++) { |
|
|
|
|
Mat* kernel = k == 0 ? &kx : &ky; |
|
|
|
|
int order = k == 0 ? dx : dy; |
|
|
|
|
float kerI[1000]; |
|
|
|
|
|
|
|
|
|
for (int t = 0; t<ksize; t++) { |
|
|
|
|
kerI[t] = 0; |
|
|
|
|
} |
|
|
|
|
for (int t = 0; t < ksize; t++) { |
|
|
|
|
kerI[t] = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (order == 0) { |
|
|
|
|
kerI[0] = norm; |
|
|
|
|
kerI[ksize/2] = w*norm; |
|
|
|
|
kerI[ksize-1] = norm; |
|
|
|
|
} |
|
|
|
|
else if (order == 1) { |
|
|
|
|
kerI[0] = -1; |
|
|
|
|
kerI[ksize/2] = 0; |
|
|
|
|
kerI[ksize-1] = 1; |
|
|
|
|
} |
|
|
|
|
if (order == 0) { |
|
|
|
|
kerI[0] = norm; |
|
|
|
|
kerI[ksize / 2] = w*norm; |
|
|
|
|
kerI[ksize - 1] = norm; |
|
|
|
|
} |
|
|
|
|
else if (order == 1) { |
|
|
|
|
kerI[0] = -1; |
|
|
|
|
kerI[ksize / 2] = 0; |
|
|
|
|
kerI[ksize - 1] = 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Mat temp(kernel->rows, kernel->cols, CV_32F, &kerI[0]); |
|
|
|
|
temp.copyTo(*kernel); |
|
|
|
|
} |
|
|
|
|
Mat temp(kernel->rows, kernel->cols, CV_32F, &kerI[0]); |
|
|
|
|
temp.copyTo(*kernel); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|