mirror of
https://github.com/opencv/opencv.git
synced 2024-11-24 19:20:28 +08:00
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:
parent
e647b7c7e8
commit
8e7aff4486
@ -138,6 +138,31 @@ parameter.
|
|||||||
CV_EXPORTS_W void fastNlMeansDenoising( InputArray src, OutputArray dst, float h = 3,
|
CV_EXPORTS_W void fastNlMeansDenoising( InputArray src, OutputArray dst, float h = 3,
|
||||||
int templateWindowSize = 7, int searchWindowSize = 21);
|
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
|
/** @brief Modification of fastNlMeansDenoising function for colored images
|
||||||
|
|
||||||
@param src Input 8-bit 3-channel image.
|
@param src Input 8-bit 3-channel image.
|
||||||
@ -186,6 +211,37 @@ CV_EXPORTS_W void fastNlMeansDenoisingMulti( InputArrayOfArrays srcImgs, OutputA
|
|||||||
int imgToDenoiseIndex, int temporalWindowSize,
|
int imgToDenoiseIndex, int temporalWindowSize,
|
||||||
float h = 3, int templateWindowSize = 7, int searchWindowSize = 21);
|
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
|
/** @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
|
@param srcImgs Input 8-bit 3-channel images sequence. All images should have the same type and
|
||||||
|
@ -65,32 +65,62 @@ void cv::fastNlMeansDenoising( InputArray _src, OutputArray _dst, float h,
|
|||||||
switch (src.type()) {
|
switch (src.type()) {
|
||||||
case CV_8U:
|
case CV_8U:
|
||||||
parallel_for_(cv::Range(0, src.rows),
|
parallel_for_(cv::Range(0, src.rows),
|
||||||
FastNlMeansDenoisingInvoker<uchar, int, unsigned>(
|
FastNlMeansDenoisingInvoker<uchar, int, unsigned, DistSquared>(
|
||||||
src, dst, templateWindowSize, searchWindowSize, h));
|
src, dst, templateWindowSize, searchWindowSize, h));
|
||||||
break;
|
break;
|
||||||
case CV_8UC2:
|
case CV_8UC2:
|
||||||
parallel_for_(cv::Range(0, src.rows),
|
parallel_for_(cv::Range(0, src.rows),
|
||||||
FastNlMeansDenoisingInvoker<cv::Vec2b, int, unsigned>(
|
FastNlMeansDenoisingInvoker<cv::Vec2b, int, unsigned, DistSquared>(
|
||||||
src, dst, templateWindowSize, searchWindowSize, h));
|
src, dst, templateWindowSize, searchWindowSize, h));
|
||||||
break;
|
break;
|
||||||
case CV_8UC3:
|
case CV_8UC3:
|
||||||
parallel_for_(cv::Range(0, src.rows),
|
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));
|
src, dst, templateWindowSize, searchWindowSize, h));
|
||||||
break;
|
break;
|
||||||
case CV_16U:
|
case CV_16U:
|
||||||
parallel_for_(cv::Range(0, src.rows),
|
parallel_for_(cv::Range(0, src.rows),
|
||||||
FastNlMeansDenoisingInvoker<ushort, int64, uint64>(
|
FastNlMeansDenoisingInvoker<ushort, int64, uint64, DistAbs>(
|
||||||
src, dst, templateWindowSize, searchWindowSize, h));
|
src, dst, templateWindowSize, searchWindowSize, h));
|
||||||
break;
|
break;
|
||||||
case CV_16UC2:
|
case CV_16UC2:
|
||||||
parallel_for_(cv::Range(0, src.rows),
|
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));
|
src, dst, templateWindowSize, searchWindowSize, h));
|
||||||
break;
|
break;
|
||||||
case CV_16UC3:
|
case CV_16UC3:
|
||||||
parallel_for_(cv::Range(0, src.rows),
|
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));
|
src, dst, templateWindowSize, searchWindowSize, h));
|
||||||
break;
|
break;
|
||||||
default:
|
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);
|
int type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
|
||||||
Size src_size = _src.size();
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,37 +220,77 @@ void cv::fastNlMeansDenoisingMulti( InputArrayOfArrays _srcImgs, OutputArray _ds
|
|||||||
{
|
{
|
||||||
case CV_8U:
|
case CV_8U:
|
||||||
parallel_for_(cv::Range(0, srcImgs[0].rows),
|
parallel_for_(cv::Range(0, srcImgs[0].rows),
|
||||||
FastNlMeansMultiDenoisingInvoker<uchar, int, unsigned>(
|
FastNlMeansMultiDenoisingInvoker<uchar, int, unsigned, DistSquared>(
|
||||||
srcImgs, imgToDenoiseIndex, temporalWindowSize,
|
srcImgs, imgToDenoiseIndex, temporalWindowSize,
|
||||||
dst, templateWindowSize, searchWindowSize, h));
|
dst, templateWindowSize, searchWindowSize, h));
|
||||||
break;
|
break;
|
||||||
case CV_8UC2:
|
case CV_8UC2:
|
||||||
parallel_for_(cv::Range(0, srcImgs[0].rows),
|
parallel_for_(cv::Range(0, srcImgs[0].rows),
|
||||||
FastNlMeansMultiDenoisingInvoker<cv::Vec2b, int, unsigned>(
|
FastNlMeansMultiDenoisingInvoker<cv::Vec2b, int, unsigned, DistSquared>(
|
||||||
srcImgs, imgToDenoiseIndex, temporalWindowSize,
|
srcImgs, imgToDenoiseIndex, temporalWindowSize,
|
||||||
dst, templateWindowSize, searchWindowSize, h));
|
dst, templateWindowSize, searchWindowSize, h));
|
||||||
break;
|
break;
|
||||||
case CV_8UC3:
|
case CV_8UC3:
|
||||||
parallel_for_(cv::Range(0, srcImgs[0].rows),
|
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,
|
srcImgs, imgToDenoiseIndex, temporalWindowSize,
|
||||||
dst, templateWindowSize, searchWindowSize, h));
|
dst, templateWindowSize, searchWindowSize, h));
|
||||||
break;
|
break;
|
||||||
case CV_16U:
|
case CV_16U:
|
||||||
parallel_for_(cv::Range(0, srcImgs[0].rows),
|
parallel_for_(cv::Range(0, srcImgs[0].rows),
|
||||||
FastNlMeansMultiDenoisingInvoker<ushort, int64, uint64>(
|
FastNlMeansMultiDenoisingInvoker<ushort, int64, uint64, DistAbs>(
|
||||||
srcImgs, imgToDenoiseIndex, temporalWindowSize,
|
srcImgs, imgToDenoiseIndex, temporalWindowSize,
|
||||||
dst, templateWindowSize, searchWindowSize, h));
|
dst, templateWindowSize, searchWindowSize, h));
|
||||||
break;
|
break;
|
||||||
case CV_16UC2:
|
case CV_16UC2:
|
||||||
parallel_for_(cv::Range(0, srcImgs[0].rows),
|
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,
|
srcImgs, imgToDenoiseIndex, temporalWindowSize,
|
||||||
dst, templateWindowSize, searchWindowSize, h));
|
dst, templateWindowSize, searchWindowSize, h));
|
||||||
break;
|
break;
|
||||||
case CV_16UC3:
|
case CV_16UC3:
|
||||||
parallel_for_(cv::Range(0, srcImgs[0].rows),
|
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,
|
srcImgs, imgToDenoiseIndex, temporalWindowSize,
|
||||||
dst, templateWindowSize, searchWindowSize, h));
|
dst, templateWindowSize, searchWindowSize, h));
|
||||||
break;
|
break;
|
||||||
@ -248,9 +318,9 @@ void cv::fastNlMeansDenoisingColoredMulti( InputArrayOfArrays _srcImgs, OutputAr
|
|||||||
int type = srcImgs[0].type(), depth = CV_MAT_DEPTH(type);
|
int type = srcImgs[0].type(), depth = CV_MAT_DEPTH(type);
|
||||||
int src_imgs_size = static_cast<int>(srcImgs.size());
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@
|
|||||||
|
|
||||||
using namespace cv;
|
using namespace cv;
|
||||||
|
|
||||||
template <typename T, typename IT, typename UIT>
|
template <typename T, typename IT, typename UIT, typename D>
|
||||||
struct FastNlMeansDenoisingInvoker :
|
struct FastNlMeansDenoisingInvoker :
|
||||||
public ParallelLoopBody
|
public ParallelLoopBody
|
||||||
{
|
{
|
||||||
@ -99,8 +99,8 @@ inline int getNearestPowerOf2(int value)
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, typename IT, typename UIT>
|
template <typename T, typename IT, typename UIT, typename D>
|
||||||
FastNlMeansDenoisingInvoker<T, IT, UIT>::FastNlMeansDenoisingInvoker(
|
FastNlMeansDenoisingInvoker<T, IT, UIT, D>::FastNlMeansDenoisingInvoker(
|
||||||
const Mat& src, Mat& dst,
|
const Mat& src, Mat& dst,
|
||||||
int template_window_size,
|
int template_window_size,
|
||||||
int search_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);
|
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;
|
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);
|
size_t almost_max_dist = (size_t)(max_dist / almost_dist2actual_dist_multiplier + 1);
|
||||||
almost_dist2weight_.resize(almost_max_dist);
|
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++)
|
for (int almost_dist = 0; almost_dist < almost_max_dist; almost_dist++)
|
||||||
{
|
{
|
||||||
double dist = almost_dist * almost_dist2actual_dist_multiplier;
|
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_)
|
if (weight < WEIGHT_THRESHOLD * fixed_point_mult_)
|
||||||
weight = 0;
|
weight = 0;
|
||||||
|
|
||||||
@ -149,8 +149,8 @@ FastNlMeansDenoisingInvoker<T, IT, UIT>::FastNlMeansDenoisingInvoker(
|
|||||||
dst_ = Mat::zeros(src_.size(), src_.type());
|
dst_ = Mat::zeros(src_.size(), src_.type());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, typename IT, typename UIT>
|
template <typename T, typename IT, typename UIT, typename D>
|
||||||
void FastNlMeansDenoisingInvoker<T, IT, UIT>::operator() (const Range& range) const
|
void FastNlMeansDenoisingInvoker<T, IT, UIT, D>::operator() (const Range& range) const
|
||||||
{
|
{
|
||||||
int row_from = range.start;
|
int row_from = range.start;
|
||||||
int row_to = range.end - 1;
|
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];
|
dist_sums_row[x] -= col_dist_sums_row[x];
|
||||||
|
|
||||||
int bx = start_bx + 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];
|
dist_sums_row[x] += col_dist_sums_row[x];
|
||||||
up_col_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>
|
template <typename T, typename IT, typename UIT, typename D>
|
||||||
inline void FastNlMeansDenoisingInvoker<T, IT, UIT>::calcDistSumsForFirstElementInRow(
|
inline void FastNlMeansDenoisingInvoker<T, IT, UIT, D>::calcDistSumsForFirstElementInRow(
|
||||||
int i,
|
int i,
|
||||||
Array2d<IT>& dist_sums,
|
Array2d<IT>& dist_sums,
|
||||||
Array3d<IT>& col_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 ty = -template_window_half_size_; ty <= template_window_half_size_; ty++)
|
||||||
for (int tx = -template_window_half_size_; tx <= template_window_half_size_; tx++)
|
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_ + i + ty, border_size_ + j + tx,
|
||||||
border_size_ + start_y + ty, border_size_ + start_x + 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>
|
template <typename T, typename IT, typename UIT, typename D>
|
||||||
inline void FastNlMeansDenoisingInvoker<T, IT, UIT>::calcDistSumsForElementInFirstRow(
|
inline void FastNlMeansDenoisingInvoker<T, IT, UIT, D>::calcDistSumsForElementInFirstRow(
|
||||||
int i, int j, int first_col_num,
|
int i, int j, int first_col_num,
|
||||||
Array2d<IT>& dist_sums,
|
Array2d<IT>& dist_sums,
|
||||||
Array3d<IT>& col_dist_sums,
|
Array3d<IT>& col_dist_sums,
|
||||||
@ -312,7 +312,7 @@ inline void FastNlMeansDenoisingInvoker<T, IT, UIT>::calcDistSumsForElementInFir
|
|||||||
int by = start_by + y;
|
int by = start_by + y;
|
||||||
int bx = start_bx + x;
|
int bx = start_bx + x;
|
||||||
for (int ty = -template_window_half_size_; ty <= template_window_half_size_; ty++)
|
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];
|
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];
|
up_col_dist_sums[j][y][x] = col_dist_sums[new_last_col_num][y][x];
|
||||||
|
@ -81,47 +81,150 @@ template <typename T> struct pixelInfo: public pixelInfo_<T>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename IT> struct calcDist_
|
class DistAbs
|
||||||
{
|
{
|
||||||
static inline IT f(const T a, const T b)
|
template <typename T, typename IT> struct calcDist_
|
||||||
{
|
{
|
||||||
return std::abs((IT)(a-b));
|
static inline IT f(const T a, const T b)
|
||||||
|
{
|
||||||
|
return std::abs((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 std::abs((IT)(a[0]-b[0])) + std::abs((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
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename ET, typename IT> struct calcDist_<Vec<ET, 2>, IT>
|
class DistSquared
|
||||||
{
|
{
|
||||||
static inline IT f(const Vec<ET, 2> a, const Vec<ET, 2> b)
|
template <typename T, typename IT> struct calcDist_
|
||||||
{
|
{
|
||||||
return std::abs((IT)(a[0]-b[0])) + std::abs((IT)(a[1]-b[1]));
|
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, 3>, IT>
|
template <typename ET, typename IT> struct calcDist_<Vec<ET, 2>, 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]));
|
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 T a, const T b)
|
template <typename T, typename IT>
|
||||||
{
|
static inline IT calcDist(const Mat& m, int i1, int j1, int i2, int j2)
|
||||||
return calcDist_<T, IT>::f(a, b);
|
{
|
||||||
}
|
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>
|
template <typename T, typename IT>
|
||||||
static inline IT calcDist(const Mat& m, int i1, int j1, int i2, int j2)
|
static inline IT calcUpDownDist(T a_up, T a_down, T b_up, T b_down)
|
||||||
{
|
{
|
||||||
const T a = m.at<T>(i1, j1);
|
return calcUpDownDist_<T, IT>::f(a_up, a_down, b_up, b_down);
|
||||||
const T b = m.at<T>(i2, j2);
|
};
|
||||||
return calcDist<T, IT>(a,b);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, typename IT>
|
template <typename T>
|
||||||
static inline IT calcUpDownDist(T a_up, T a_down, T b_up, T b_down)
|
static double calcWeight(double dist, double h)
|
||||||
{
|
{
|
||||||
return calcDist<T, IT>(a_down, b_down) - calcDist<T, IT>(a_up, b_up);
|
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_
|
template <typename T, typename IT> struct incWithWeight_
|
||||||
|
@ -50,7 +50,7 @@
|
|||||||
|
|
||||||
using namespace cv;
|
using namespace cv;
|
||||||
|
|
||||||
template <typename T, typename IT, typename UIT>
|
template <typename T, typename IT, typename UIT, typename D>
|
||||||
struct FastNlMeansMultiDenoisingInvoker :
|
struct FastNlMeansMultiDenoisingInvoker :
|
||||||
ParallelLoopBody
|
ParallelLoopBody
|
||||||
{
|
{
|
||||||
@ -94,8 +94,8 @@ private:
|
|||||||
Array4d<IT>& up_col_dist_sums) const;
|
Array4d<IT>& up_col_dist_sums) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T, typename IT, typename UIT>
|
template <typename T, typename IT, typename UIT, typename D>
|
||||||
FastNlMeansMultiDenoisingInvoker<T, IT, UIT>::FastNlMeansMultiDenoisingInvoker(
|
FastNlMeansMultiDenoisingInvoker<T, IT, UIT, D>::FastNlMeansMultiDenoisingInvoker(
|
||||||
const std::vector<Mat>& srcImgs,
|
const std::vector<Mat>& srcImgs,
|
||||||
int imgToDenoiseIndex,
|
int imgToDenoiseIndex,
|
||||||
int temporalWindowSize,
|
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;
|
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;
|
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);
|
int almost_max_dist = (int) (max_dist / almost_dist2actual_dist_multiplier + 1);
|
||||||
almost_dist2weight.resize(almost_max_dist);
|
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++)
|
for (int almost_dist = 0; almost_dist < almost_max_dist; almost_dist++)
|
||||||
{
|
{
|
||||||
double dist = almost_dist * almost_dist2actual_dist_multiplier;
|
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_)
|
if (weight < WEIGHT_THRESHOLD * fixed_point_mult_)
|
||||||
weight = 0;
|
weight = 0;
|
||||||
|
|
||||||
@ -160,8 +160,8 @@ FastNlMeansMultiDenoisingInvoker<T, IT, UIT>::FastNlMeansMultiDenoisingInvoker(
|
|||||||
dst_ = Mat::zeros(srcImgs[0].size(), srcImgs[0].type());
|
dst_ = Mat::zeros(srcImgs[0].size(), srcImgs[0].type());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T, typename IT, typename UIT>
|
template <typename T, typename IT, typename UIT, typename D>
|
||||||
void FastNlMeansMultiDenoisingInvoker<T, IT, UIT>::operator() (const Range& range) const
|
void FastNlMeansMultiDenoisingInvoker<T, IT, UIT, D>::operator() (const Range& range) const
|
||||||
{
|
{
|
||||||
int row_from = range.start;
|
int row_from = range.start;
|
||||||
int row_to = range.end - 1;
|
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];
|
dist_sums_row[x] -= col_dist_sums_row[x];
|
||||||
|
|
||||||
col_dist_sums_row[x] = up_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];
|
dist_sums_row[x] += col_dist_sums_row[x];
|
||||||
up_col_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>
|
template <typename T, typename IT, typename UIT, typename D>
|
||||||
inline void FastNlMeansMultiDenoisingInvoker<T, IT, UIT>::calcDistSumsForFirstElementInRow(
|
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 i, Array3d<IT>& dist_sums, Array4d<IT>& col_dist_sums, Array4d<IT>& up_col_dist_sums) const
|
||||||
{
|
{
|
||||||
int j = 0;
|
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++)
|
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),
|
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));
|
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>
|
template <typename T, typename IT, typename UIT, typename D>
|
||||||
inline void FastNlMeansMultiDenoisingInvoker<T, IT, UIT>::calcDistSumsForElementInFirstRow(
|
inline void FastNlMeansMultiDenoisingInvoker<T, IT, UIT, D>::calcDistSumsForElementInFirstRow(
|
||||||
int i, int j, int first_col_num, Array3d<IT>& dist_sums,
|
int i, int j, int first_col_num, Array3d<IT>& dist_sums,
|
||||||
Array4d<IT>& col_dist_sums, Array4d<IT>& up_col_dist_sums) const
|
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];
|
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++)
|
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),
|
main_extended_src_.at<T>(ay + ty, ax),
|
||||||
cur_extended_src.at<T>(by + ty, bx));
|
cur_extended_src.at<T>(by + ty, bx));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user