Changed fastNlMeansDenoising and fastNlMeansDenoisingMulti back to sum of sq distances. Moved sq sum of abs distances to fastNlMeansDenoisingAbs and fastNlMeansDenoisingMultiAbs

This commit is contained in:
Erik Karlsson 2015-02-18 14:59:52 +01:00
parent e647b7c7e8
commit 8e7aff4486
5 changed files with 301 additions and 72 deletions

View File

@ -138,6 +138,31 @@ parameter.
CV_EXPORTS_W void fastNlMeansDenoising( InputArray src, OutputArray dst, float h = 3,
int templateWindowSize = 7, int searchWindowSize = 21);
/** @brief Perform image denoising using Non-local Means Denoising
algorithm <http://www.ipol.im/pub/algo/bcm_non_local_means_denoising/>
with several computational optimizations. Noise expected to be a
gaussian white noise. Uses squared sum of absolute value distances
instead of sum of squared distances for weight calculation
@param src Input 8-bit or 16-bit 1-channel, 2-channel or 3-channel image.
@param dst Output image with the same size and type as src .
@param templateWindowSize Size in pixels of the template patch that is used to compute weights.
Should be odd. Recommended value 7 pixels
@param searchWindowSize Size in pixels of the window that is used to compute weighted average for
given pixel. Should be odd. Affect performance linearly: greater searchWindowsSize - greater
denoising time. Recommended value 21 pixels
@param h Parameter regulating filter strength. Big h value perfectly removes noise but also
removes image details, smaller h value preserves details but also preserves some noise
This function expected to be applied to grayscale images. For colored images look at
fastNlMeansDenoisingColored. Advanced usage of this functions can be manual denoising of colored
image in different colorspaces. Such approach is used in fastNlMeansDenoisingColored by converting
image to CIELAB colorspace and then separately denoise L and AB components with different h
parameter.
*/
CV_EXPORTS_W void fastNlMeansDenoisingAbs( InputArray src, OutputArray dst, float h = 3,
int templateWindowSize = 7, int searchWindowSize = 21);
/** @brief Modification of fastNlMeansDenoising function for colored images
@param src Input 8-bit 3-channel image.
@ -186,6 +211,37 @@ CV_EXPORTS_W void fastNlMeansDenoisingMulti( InputArrayOfArrays srcImgs, OutputA
int imgToDenoiseIndex, int temporalWindowSize,
float h = 3, int templateWindowSize = 7, int searchWindowSize = 21);
/** @brief Modification of fastNlMeansDenoising function for images
sequence where consequtive images have been captured in small period
of time. For example video. This version of the function is for
grayscale images or for manual manipulation with colorspaces. For more
details see
<http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.131.6394>. Uses
squared sum of absolute value distances instead of sum of squared
distances for weight calculation
@param srcImgs Input 8-bit or 16-bit 1-channel, 2-channel or 3-channel
images sequence. All images should
have the same type and size.
@param imgToDenoiseIndex Target image to denoise index in srcImgs sequence
@param temporalWindowSize Number of surrounding images to use for target image denoising. Should
be odd. Images from imgToDenoiseIndex - temporalWindowSize / 2 to
imgToDenoiseIndex - temporalWindowSize / 2 from srcImgs will be used to denoise
srcImgs[imgToDenoiseIndex] image.
@param dst Output image with the same size and type as srcImgs images.
@param templateWindowSize Size in pixels of the template patch that is used to compute weights.
Should be odd. Recommended value 7 pixels
@param searchWindowSize Size in pixels of the window that is used to compute weighted average for
given pixel. Should be odd. Affect performance linearly: greater searchWindowsSize - greater
denoising time. Recommended value 21 pixels
@param h Parameter regulating filter strength for luminance component. Bigger h value perfectly
removes noise but also removes image details, smaller h value preserves details but also preserves
some noise
*/
CV_EXPORTS_W void fastNlMeansDenoisingMultiAbs( InputArrayOfArrays srcImgs, OutputArray dst,
int imgToDenoiseIndex, int temporalWindowSize,
float h = 3, int templateWindowSize = 7, int searchWindowSize = 21);
/** @brief Modification of fastNlMeansDenoisingMulti function for colored images sequences
@param srcImgs Input 8-bit 3-channel images sequence. All images should have the same type and

View File

@ -65,32 +65,62 @@ void cv::fastNlMeansDenoising( InputArray _src, OutputArray _dst, float h,
switch (src.type()) {
case CV_8U:
parallel_for_(cv::Range(0, src.rows),
FastNlMeansDenoisingInvoker<uchar, int, unsigned>(
FastNlMeansDenoisingInvoker<uchar, int, unsigned, DistSquared>(
src, dst, templateWindowSize, searchWindowSize, h));
break;
case CV_8UC2:
parallel_for_(cv::Range(0, src.rows),
FastNlMeansDenoisingInvoker<cv::Vec2b, int, unsigned>(
FastNlMeansDenoisingInvoker<cv::Vec2b, int, unsigned, DistSquared>(
src, dst, templateWindowSize, searchWindowSize, h));
break;
case CV_8UC3:
parallel_for_(cv::Range(0, src.rows),
FastNlMeansDenoisingInvoker<cv::Vec3b, int, unsigned>(
FastNlMeansDenoisingInvoker<cv::Vec3b, int, unsigned, DistSquared>(
src, dst, templateWindowSize, searchWindowSize, h));
break;
default:
CV_Error(Error::StsBadArg,
"Unsupported image format! Only CV_8U, CV_8UC2, and CV_8UC3 are supported");
}
}
void cv::fastNlMeansDenoisingAbs( InputArray _src, OutputArray _dst, float h,
int templateWindowSize, int searchWindowSize)
{
Size src_size = _src.size();
Mat src = _src.getMat();
_dst.create(src_size, src.type());
Mat dst = _dst.getMat();
switch (src.type()) {
case CV_8U:
parallel_for_(cv::Range(0, src.rows),
FastNlMeansDenoisingInvoker<uchar, int, unsigned, DistAbs>(
src, dst, templateWindowSize, searchWindowSize, h));
break;
case CV_8UC2:
parallel_for_(cv::Range(0, src.rows),
FastNlMeansDenoisingInvoker<cv::Vec2b, int, unsigned, DistAbs>(
src, dst, templateWindowSize, searchWindowSize, h));
break;
case CV_8UC3:
parallel_for_(cv::Range(0, src.rows),
FastNlMeansDenoisingInvoker<cv::Vec3b, int, unsigned, DistAbs>(
src, dst, templateWindowSize, searchWindowSize, h));
break;
case CV_16U:
parallel_for_(cv::Range(0, src.rows),
FastNlMeansDenoisingInvoker<ushort, int64, uint64>(
FastNlMeansDenoisingInvoker<ushort, int64, uint64, DistAbs>(
src, dst, templateWindowSize, searchWindowSize, h));
break;
case CV_16UC2:
parallel_for_(cv::Range(0, src.rows),
FastNlMeansDenoisingInvoker<cv::Vec<ushort, 2>, int64, uint64>(
FastNlMeansDenoisingInvoker<cv::Vec<ushort, 2>, int64, uint64, DistAbs>(
src, dst, templateWindowSize, searchWindowSize, h));
break;
case CV_16UC3:
parallel_for_(cv::Range(0, src.rows),
FastNlMeansDenoisingInvoker<cv::Vec<ushort, 3>, int64, uint64>(
FastNlMeansDenoisingInvoker<cv::Vec<ushort, 3>, int64, uint64, DistAbs>(
src, dst, templateWindowSize, searchWindowSize, h));
break;
default:
@ -105,9 +135,9 @@ void cv::fastNlMeansDenoisingColored( InputArray _src, OutputArray _dst,
{
int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
Size src_size = _src.size();
if (type != CV_8UC3 && type != CV_16UC3 && type != CV_8UC4 && type != CV_16UC4)
if (type != CV_8UC3 && type != CV_8UC4)
{
CV_Error(Error::StsBadArg, "Type of input image should be CV_8UC3, CV_16UC3, CV_8UC4, or CV_16UC4");
CV_Error(Error::StsBadArg, "Type of input image should be CV_8UC3 or CV_8UC4!");
return;
}
@ -190,37 +220,77 @@ void cv::fastNlMeansDenoisingMulti( InputArrayOfArrays _srcImgs, OutputArray _ds
{
case CV_8U:
parallel_for_(cv::Range(0, srcImgs[0].rows),
FastNlMeansMultiDenoisingInvoker<uchar, int, unsigned>(
FastNlMeansMultiDenoisingInvoker<uchar, int, unsigned, DistSquared>(
srcImgs, imgToDenoiseIndex, temporalWindowSize,
dst, templateWindowSize, searchWindowSize, h));
break;
case CV_8UC2:
parallel_for_(cv::Range(0, srcImgs[0].rows),
FastNlMeansMultiDenoisingInvoker<cv::Vec2b, int, unsigned>(
FastNlMeansMultiDenoisingInvoker<cv::Vec2b, int, unsigned, DistSquared>(
srcImgs, imgToDenoiseIndex, temporalWindowSize,
dst, templateWindowSize, searchWindowSize, h));
break;
case CV_8UC3:
parallel_for_(cv::Range(0, srcImgs[0].rows),
FastNlMeansMultiDenoisingInvoker<cv::Vec3b, int, unsigned>(
FastNlMeansMultiDenoisingInvoker<cv::Vec3b, int, unsigned, DistSquared>(
srcImgs, imgToDenoiseIndex, temporalWindowSize,
dst, templateWindowSize, searchWindowSize, h));
break;
default:
CV_Error(Error::StsBadArg,
"Unsupported image format! Only CV_8U, CV_8UC2, and CV_8UC3 are supported");
}
}
void cv::fastNlMeansDenoisingMultiAbs( InputArrayOfArrays _srcImgs, OutputArray _dst,
int imgToDenoiseIndex, int temporalWindowSize,
float h, int templateWindowSize, int searchWindowSize)
{
std::vector<Mat> srcImgs;
_srcImgs.getMatVector(srcImgs);
fastNlMeansDenoisingMultiCheckPreconditions(
srcImgs, imgToDenoiseIndex,
temporalWindowSize, templateWindowSize, searchWindowSize);
_dst.create(srcImgs[0].size(), srcImgs[0].type());
Mat dst = _dst.getMat();
switch (srcImgs[0].type())
{
case CV_8U:
parallel_for_(cv::Range(0, srcImgs[0].rows),
FastNlMeansMultiDenoisingInvoker<uchar, int, unsigned, DistAbs>(
srcImgs, imgToDenoiseIndex, temporalWindowSize,
dst, templateWindowSize, searchWindowSize, h));
break;
case CV_8UC2:
parallel_for_(cv::Range(0, srcImgs[0].rows),
FastNlMeansMultiDenoisingInvoker<cv::Vec2b, int, unsigned, DistAbs>(
srcImgs, imgToDenoiseIndex, temporalWindowSize,
dst, templateWindowSize, searchWindowSize, h));
break;
case CV_8UC3:
parallel_for_(cv::Range(0, srcImgs[0].rows),
FastNlMeansMultiDenoisingInvoker<cv::Vec3b, int, unsigned, DistAbs>(
srcImgs, imgToDenoiseIndex, temporalWindowSize,
dst, templateWindowSize, searchWindowSize, h));
break;
case CV_16U:
parallel_for_(cv::Range(0, srcImgs[0].rows),
FastNlMeansMultiDenoisingInvoker<ushort, int64, uint64>(
FastNlMeansMultiDenoisingInvoker<ushort, int64, uint64, DistAbs>(
srcImgs, imgToDenoiseIndex, temporalWindowSize,
dst, templateWindowSize, searchWindowSize, h));
break;
case CV_16UC2:
parallel_for_(cv::Range(0, srcImgs[0].rows),
FastNlMeansMultiDenoisingInvoker<cv::Vec<ushort, 2>, int64, uint64>(
FastNlMeansMultiDenoisingInvoker<cv::Vec<ushort, 2>, int64, uint64, DistAbs>(
srcImgs, imgToDenoiseIndex, temporalWindowSize,
dst, templateWindowSize, searchWindowSize, h));
break;
case CV_16UC3:
parallel_for_(cv::Range(0, srcImgs[0].rows),
FastNlMeansMultiDenoisingInvoker<cv::Vec<ushort, 3>, int64, uint64>(
FastNlMeansMultiDenoisingInvoker<cv::Vec<ushort, 3>, int64, uint64, DistAbs>(
srcImgs, imgToDenoiseIndex, temporalWindowSize,
dst, templateWindowSize, searchWindowSize, h));
break;
@ -248,9 +318,9 @@ void cv::fastNlMeansDenoisingColoredMulti( InputArrayOfArrays _srcImgs, OutputAr
int type = srcImgs[0].type(), depth = CV_MAT_DEPTH(type);
int src_imgs_size = static_cast<int>(srcImgs.size());
if (type != CV_8UC3 && type != CV_16UC3)
if (type != CV_8UC3)
{
CV_Error(Error::StsBadArg, "Type of input images should be CV_8UC3 or CV_16UC3!");
CV_Error(Error::StsBadArg, "Type of input images should be CV_8UC3!");
return;
}

View File

@ -50,7 +50,7 @@
using namespace cv;
template <typename T, typename IT, typename UIT>
template <typename T, typename IT, typename UIT, typename D>
struct FastNlMeansDenoisingInvoker :
public ParallelLoopBody
{
@ -99,8 +99,8 @@ inline int getNearestPowerOf2(int value)
return p;
}
template <class T, typename IT, typename UIT>
FastNlMeansDenoisingInvoker<T, IT, UIT>::FastNlMeansDenoisingInvoker(
template <typename T, typename IT, typename UIT, typename D>
FastNlMeansDenoisingInvoker<T, IT, UIT, D>::FastNlMeansDenoisingInvoker(
const Mat& src, Mat& dst,
int template_window_size,
int search_window_size,
@ -128,7 +128,7 @@ FastNlMeansDenoisingInvoker<T, IT, UIT>::FastNlMeansDenoisingInvoker(
almost_template_window_size_sq_bin_shift_ = getNearestPowerOf2(template_window_size_sq);
double almost_dist2actual_dist_multiplier = ((double)(1 << almost_template_window_size_sq_bin_shift_)) / template_window_size_sq;
IT max_dist = (IT)pixelInfo<T>::sampleMax() * (IT)pixelInfo<T>::channels;
IT max_dist = D::template maxDist<T, IT>();
size_t almost_max_dist = (size_t)(max_dist / almost_dist2actual_dist_multiplier + 1);
almost_dist2weight_.resize(almost_max_dist);
@ -136,7 +136,7 @@ FastNlMeansDenoisingInvoker<T, IT, UIT>::FastNlMeansDenoisingInvoker(
for (int almost_dist = 0; almost_dist < almost_max_dist; almost_dist++)
{
double dist = almost_dist * almost_dist2actual_dist_multiplier;
IT weight = (IT)round(fixed_point_mult_ * std::exp(-dist*dist / (h * h * pixelInfo<T>::channels)));
IT weight = (IT)round(fixed_point_mult_ * D::template calcWeight<T>(dist, h));
if (weight < WEIGHT_THRESHOLD * fixed_point_mult_)
weight = 0;
@ -149,8 +149,8 @@ FastNlMeansDenoisingInvoker<T, IT, UIT>::FastNlMeansDenoisingInvoker(
dst_ = Mat::zeros(src_.size(), src_.type());
}
template <class T, typename IT, typename UIT>
void FastNlMeansDenoisingInvoker<T, IT, UIT>::operator() (const Range& range) const
template <typename T, typename IT, typename UIT, typename D>
void FastNlMeansDenoisingInvoker<T, IT, UIT, D>::operator() (const Range& range) const
{
int row_from = range.start;
int row_to = range.end - 1;
@ -215,7 +215,7 @@ void FastNlMeansDenoisingInvoker<T, IT, UIT>::operator() (const Range& range) co
dist_sums_row[x] -= col_dist_sums_row[x];
int bx = start_bx + x;
col_dist_sums_row[x] = up_col_dist_sums_row[x] + calcUpDownDist<T, IT>(a_up, a_down, b_up_ptr[bx], b_down_ptr[bx]);
col_dist_sums_row[x] = up_col_dist_sums_row[x] + D::template calcUpDownDist<T, IT>(a_up, a_down, b_up_ptr[bx], b_down_ptr[bx]);
dist_sums_row[x] += col_dist_sums_row[x];
up_col_dist_sums_row[x] = col_dist_sums_row[x];
@ -254,8 +254,8 @@ void FastNlMeansDenoisingInvoker<T, IT, UIT>::operator() (const Range& range) co
}
}
template <class T, typename IT, typename UIT>
inline void FastNlMeansDenoisingInvoker<T, IT, UIT>::calcDistSumsForFirstElementInRow(
template <typename T, typename IT, typename UIT, typename D>
inline void FastNlMeansDenoisingInvoker<T, IT, UIT, D>::calcDistSumsForFirstElementInRow(
int i,
Array2d<IT>& dist_sums,
Array3d<IT>& col_dist_sums,
@ -276,7 +276,7 @@ inline void FastNlMeansDenoisingInvoker<T, IT, UIT>::calcDistSumsForFirstElement
for (int ty = -template_window_half_size_; ty <= template_window_half_size_; ty++)
for (int tx = -template_window_half_size_; tx <= template_window_half_size_; tx++)
{
int dist = calcDist<T, IT>(extended_src_,
int dist = D::template calcDist<T, IT>(extended_src_,
border_size_ + i + ty, border_size_ + j + tx,
border_size_ + start_y + ty, border_size_ + start_x + tx);
@ -288,8 +288,8 @@ inline void FastNlMeansDenoisingInvoker<T, IT, UIT>::calcDistSumsForFirstElement
}
}
template <class T, typename IT, typename UIT>
inline void FastNlMeansDenoisingInvoker<T, IT, UIT>::calcDistSumsForElementInFirstRow(
template <typename T, typename IT, typename UIT, typename D>
inline void FastNlMeansDenoisingInvoker<T, IT, UIT, D>::calcDistSumsForElementInFirstRow(
int i, int j, int first_col_num,
Array2d<IT>& dist_sums,
Array3d<IT>& col_dist_sums,
@ -312,7 +312,7 @@ inline void FastNlMeansDenoisingInvoker<T, IT, UIT>::calcDistSumsForElementInFir
int by = start_by + y;
int bx = start_bx + x;
for (int ty = -template_window_half_size_; ty <= template_window_half_size_; ty++)
col_dist_sums[new_last_col_num][y][x] += calcDist<T,IT>(extended_src_, ay + ty, ax, by + ty, bx);
col_dist_sums[new_last_col_num][y][x] += D::template calcDist<T,IT>(extended_src_, ay + ty, ax, by + ty, bx);
dist_sums[y][x] += col_dist_sums[new_last_col_num][y][x];
up_col_dist_sums[j][y][x] = col_dist_sums[new_last_col_num][y][x];

View File

@ -81,6 +81,8 @@ template <typename T> struct pixelInfo: public pixelInfo_<T>
}
};
class DistAbs
{
template <typename T, typename IT> struct calcDist_
{
static inline IT f(const T a, const T b)
@ -101,10 +103,14 @@ template <typename ET, typename IT> struct calcDist_<Vec<ET, 3>, IT>
{
static inline IT f(const Vec<ET, 3> a, const Vec<ET, 3> b)
{
return std::abs((IT)(a[0]-b[0])) + std::abs((IT)(a[1]-b[1])) + std::abs((IT)(a[2]-b[2]));
return
std::abs((IT)(a[0]-b[0])) +
std::abs((IT)(a[1]-b[1])) +
std::abs((IT)(a[2]-b[2]));
}
};
public:
template <typename T, typename IT> static inline IT calcDist(const T a, const T b)
{
return calcDist_<T, IT>::f(a, b);
@ -124,6 +130,103 @@ static inline IT calcUpDownDist(T a_up, T a_down, T b_up, T b_down)
return calcDist<T, IT>(a_down, b_down) - calcDist<T, IT>(a_up, b_up);
};
template <typename T>
static double calcWeight(double dist, double h)
{
return std::exp(-dist*dist / (h * h * pixelInfo<T>::channels));
}
template <typename T, typename IT>
static double maxDist()
{
return (IT)pixelInfo<T>::sampleMax() * (IT)pixelInfo<T>::channels;
}
};
class DistSquared
{
template <typename T, typename IT> struct calcDist_
{
static inline IT f(const T a, const T b)
{
return (IT)(a-b) * (IT)(a-b);
}
};
template <typename ET, typename IT> struct calcDist_<Vec<ET, 2>, IT>
{
static inline IT f(const Vec<ET, 2> a, const Vec<ET, 2> b)
{
return (IT)(a[0]-b[0])*(IT)(a[0]-b[0]) + (IT)(a[1]-b[1])*(IT)(a[1]-b[1]);
}
};
template <typename ET, typename IT> struct calcDist_<Vec<ET, 3>, IT>
{
static inline IT f(const Vec<ET, 3> a, const Vec<ET, 3> b)
{
return
(IT)(a[0]-b[0])*(IT)(a[0]-b[0]) +
(IT)(a[1]-b[1])*(IT)(a[1]-b[1]) +
(IT)(a[2]-b[2])*(IT)(a[2]-b[2]);
}
};
template <typename T, typename IT> struct calcUpDownDist_
{
static inline IT f(T a_up, T a_down, T b_up, T b_down)
{
IT A = a_down - b_down;
IT B = a_up - b_up;
return (A-B)*(A+B);
}
};
template <typename ET, int n, typename IT> struct calcUpDownDist_<Vec<ET, n>, IT>
{
private:
typedef Vec<ET, n> T;
public:
static inline IT f(T a_up, T a_down, T b_up, T b_down)
{
return calcDist<T, IT>(a_down, b_down) - calcDist<T, IT>(a_up, b_up);
}
};
public:
template <typename T, typename IT> static inline IT calcDist(const T a, const T b)
{
return calcDist_<T, IT>::f(a, b);
}
template <typename T, typename IT>
static inline IT calcDist(const Mat& m, int i1, int j1, int i2, int j2)
{
const T a = m.at<T>(i1, j1);
const T b = m.at<T>(i2, j2);
return calcDist<T, IT>(a,b);
}
template <typename T, typename IT>
static inline IT calcUpDownDist(T a_up, T a_down, T b_up, T b_down)
{
return calcUpDownDist_<T, IT>::f(a_up, a_down, b_up, b_down);
};
template <typename T>
static double calcWeight(double dist, double h)
{
return std::exp(-dist / (h * h * pixelInfo<T>::channels));
}
template <typename T, typename IT>
static double maxDist()
{
return (IT)pixelInfo<T>::sampleMax() * (IT)pixelInfo<T>::sampleMax() *
(IT)pixelInfo<T>::channels;
}
};
template <typename T, typename IT> struct incWithWeight_
{
static inline void f(IT* estimation, IT weight, T p)

View File

@ -50,7 +50,7 @@
using namespace cv;
template <typename T, typename IT, typename UIT>
template <typename T, typename IT, typename UIT, typename D>
struct FastNlMeansMultiDenoisingInvoker :
ParallelLoopBody
{
@ -94,8 +94,8 @@ private:
Array4d<IT>& up_col_dist_sums) const;
};
template <class T, typename IT, typename UIT>
FastNlMeansMultiDenoisingInvoker<T, IT, UIT>::FastNlMeansMultiDenoisingInvoker(
template <typename T, typename IT, typename UIT, typename D>
FastNlMeansMultiDenoisingInvoker<T, IT, UIT, D>::FastNlMeansMultiDenoisingInvoker(
const std::vector<Mat>& srcImgs,
int imgToDenoiseIndex,
int temporalWindowSize,
@ -139,7 +139,7 @@ FastNlMeansMultiDenoisingInvoker<T, IT, UIT>::FastNlMeansMultiDenoisingInvoker(
int almost_template_window_size_sq = 1 << almost_template_window_size_sq_bin_shift;
double almost_dist2actual_dist_multiplier = (double) almost_template_window_size_sq / template_window_size_sq;
IT max_dist = (IT)pixelInfo<T>::sampleMax() * (IT)pixelInfo<T>::channels;
IT max_dist = D::template maxDist<T,IT>();
int almost_max_dist = (int) (max_dist / almost_dist2actual_dist_multiplier + 1);
almost_dist2weight.resize(almost_max_dist);
@ -147,7 +147,7 @@ FastNlMeansMultiDenoisingInvoker<T, IT, UIT>::FastNlMeansMultiDenoisingInvoker(
for (int almost_dist = 0; almost_dist < almost_max_dist; almost_dist++)
{
double dist = almost_dist * almost_dist2actual_dist_multiplier;
IT weight = (IT)round(fixed_point_mult_ * std::exp(-dist*dist / (h * h * pixelInfo<T>::channels)));
IT weight = (IT)round(fixed_point_mult_ * D::template calcWeight<T>(dist, h));
if (weight < WEIGHT_THRESHOLD * fixed_point_mult_)
weight = 0;
@ -160,8 +160,8 @@ FastNlMeansMultiDenoisingInvoker<T, IT, UIT>::FastNlMeansMultiDenoisingInvoker(
dst_ = Mat::zeros(srcImgs[0].size(), srcImgs[0].type());
}
template <class T, typename IT, typename UIT>
void FastNlMeansMultiDenoisingInvoker<T, IT, UIT>::operator() (const Range& range) const
template <typename T, typename IT, typename UIT, typename D>
void FastNlMeansMultiDenoisingInvoker<T, IT, UIT, D>::operator() (const Range& range) const
{
int row_from = range.start;
int row_to = range.end - 1;
@ -234,7 +234,7 @@ void FastNlMeansMultiDenoisingInvoker<T, IT, UIT>::operator() (const Range& rang
dist_sums_row[x] -= col_dist_sums_row[x];
col_dist_sums_row[x] = up_col_dist_sums_row[x] +
calcUpDownDist<T, IT>(a_up, a_down, b_up_ptr[start_bx + x], b_down_ptr[start_bx + x]);
D::template calcUpDownDist<T, IT>(a_up, a_down, b_up_ptr[start_bx + x], b_down_ptr[start_bx + x]);
dist_sums_row[x] += col_dist_sums_row[x];
up_col_dist_sums_row[x] = col_dist_sums_row[x];
@ -284,8 +284,8 @@ void FastNlMeansMultiDenoisingInvoker<T, IT, UIT>::operator() (const Range& rang
}
}
template <class T, typename IT, typename UIT>
inline void FastNlMeansMultiDenoisingInvoker<T, IT, UIT>::calcDistSumsForFirstElementInRow(
template <typename T, typename IT, typename UIT, typename D>
inline void FastNlMeansMultiDenoisingInvoker<T, IT, UIT, D>::calcDistSumsForFirstElementInRow(
int i, Array3d<IT>& dist_sums, Array4d<IT>& col_dist_sums, Array4d<IT>& up_col_dist_sums) const
{
int j = 0;
@ -310,7 +310,7 @@ inline void FastNlMeansMultiDenoisingInvoker<T, IT, UIT>::calcDistSumsForFirstEl
{
for (int ty = -template_window_half_size_; ty <= template_window_half_size_; ty++)
{
IT dist = calcDist<T, IT>(
IT dist = D::template calcDist<T, IT>(
main_extended_src_.at<T>(border_size_ + i + ty, border_size_ + j + tx),
cur_extended_src.at<T>(border_size_ + start_y + ty, border_size_ + start_x + tx));
@ -325,8 +325,8 @@ inline void FastNlMeansMultiDenoisingInvoker<T, IT, UIT>::calcDistSumsForFirstEl
}
}
template <class T, typename IT, typename UIT>
inline void FastNlMeansMultiDenoisingInvoker<T, IT, UIT>::calcDistSumsForElementInFirstRow(
template <typename T, typename IT, typename UIT, typename D>
inline void FastNlMeansMultiDenoisingInvoker<T, IT, UIT, D>::calcDistSumsForElementInFirstRow(
int i, int j, int first_col_num, Array3d<IT>& dist_sums,
Array4d<IT>& col_dist_sums, Array4d<IT>& up_col_dist_sums) const
{
@ -353,7 +353,7 @@ inline void FastNlMeansMultiDenoisingInvoker<T, IT, UIT>::calcDistSumsForElement
IT* col_dist_sums_ptr = &col_dist_sums[new_last_col_num][d][y][x];
for (int ty = -template_window_half_size_; ty <= template_window_half_size_; ty++)
{
*col_dist_sums_ptr += calcDist<T, IT>(
*col_dist_sums_ptr += D::template calcDist<T, IT>(
main_extended_src_.at<T>(ay + ty, ax),
cur_extended_src.at<T>(by + ty, bx));
}