Commit 5f8d6886 authored by Erik Karlsson's avatar Erik Karlsson

Added parameter normType to fastNlMeansDenoising

parent 9fff7896
...@@ -153,6 +153,7 @@ denoising time. Recommended value 21 pixels ...@@ -153,6 +153,7 @@ denoising time. Recommended value 21 pixels
parameter applied to all channels or one per channel in dst. Big h value parameter applied to all channels or one per channel in dst. Big h value
perfectly removes noise but also removes image details, smaller h perfectly removes noise but also removes image details, smaller h
value preserves details but also preserves some noise value preserves details but also preserves some noise
@param normType Type of norm used for weight calcluation. Can be either NORM_L2 or NORM_L1
This function expected to be applied to grayscale images. For colored images look at 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 fastNlMeansDenoisingColored. Advanced usage of this functions can be manual denoising of colored
...@@ -162,7 +163,8 @@ parameter. ...@@ -162,7 +163,8 @@ parameter.
*/ */
CV_EXPORTS_W void fastNlMeansDenoising( InputArray src, OutputArray dst, CV_EXPORTS_W void fastNlMeansDenoising( InputArray src, OutputArray dst,
const std::vector<float>& h, const std::vector<float>& h,
int templateWindowSize = 7, int searchWindowSize = 21); int templateWindowSize = 7, int searchWindowSize = 21,
int normType = NORM_L2);
/** @brief Modification of fastNlMeansDenoising function for colored images /** @brief Modification of fastNlMeansDenoising function for colored images
......
...@@ -45,74 +45,115 @@ ...@@ -45,74 +45,115 @@
#include "fast_nlmeans_multi_denoising_invoker.hpp" #include "fast_nlmeans_multi_denoising_invoker.hpp"
#include "fast_nlmeans_denoising_opencl.hpp" #include "fast_nlmeans_denoising_opencl.hpp"
void cv::fastNlMeansDenoising( InputArray _src, OutputArray _dst, float h, template<typename ST, typename IT, typename UIT, typename D>
int templateWindowSize, int searchWindowSize) static void fastNlMeansDenoising_( const Mat& src, Mat& dst, const std::vector<float>& h,
{ int templateWindowSize, int searchWindowSize)
fastNlMeansDenoising(_src, _dst, std::vector<float>(1, h),
templateWindowSize, searchWindowSize);
}
void cv::fastNlMeansDenoising( InputArray _src, OutputArray _dst, const std::vector<float>& h,
int templateWindowSize, int searchWindowSize)
{ {
int hn = (int)h.size(); int hn = (int)h.size();
CV_Assert(hn == 1 || hn == CV_MAT_CN(_src.type()));
Size src_size = _src.size();
CV_OCL_RUN(_src.dims() <= 2 && (_src.isUMat() || _dst.isUMat()) &&
src_size.width > 5 && src_size.height > 5, // low accuracy on small sizes
ocl_fastNlMeansDenoising(_src, _dst, &h[0], hn,
templateWindowSize, searchWindowSize, false))
Mat src = _src.getMat(); switch (CV_MAT_CN(src.type())) {
_dst.create(src_size, src.type()); case 1:
Mat dst = _dst.getMat();
#ifdef HAVE_TEGRA_OPTIMIZATION
if(hn == 1 && tegra::useTegra() &&
tegra::fastNlMeansDenoising(src, dst, h[0], templateWindowSize, searchWindowSize))
return;
#endif
switch (src.type()) {
case CV_8U:
parallel_for_(cv::Range(0, src.rows), parallel_for_(cv::Range(0, src.rows),
FastNlMeansDenoisingInvoker<uchar, int, unsigned, DistSquared, int>( FastNlMeansDenoisingInvoker<ST, IT, UIT, D, int>(
src, dst, templateWindowSize, searchWindowSize, &h[0])); src, dst, templateWindowSize, searchWindowSize, &h[0]));
break; break;
case CV_8UC2: case 2:
if (hn == 1) if (hn == 1)
parallel_for_(cv::Range(0, src.rows), parallel_for_(cv::Range(0, src.rows),
FastNlMeansDenoisingInvoker<Vec2b, int, unsigned, DistSquared, int>( FastNlMeansDenoisingInvoker<Vec<ST, 2>, IT, UIT, D, int>(
src, dst, templateWindowSize, searchWindowSize, &h[0])); src, dst, templateWindowSize, searchWindowSize, &h[0]));
else else
parallel_for_(cv::Range(0, src.rows), parallel_for_(cv::Range(0, src.rows),
FastNlMeansDenoisingInvoker<Vec2b, int, unsigned, DistSquared, Vec2i>( FastNlMeansDenoisingInvoker<Vec<ST, 2>, IT, UIT, D, Vec2i>(
src, dst, templateWindowSize, searchWindowSize, &h[0])); src, dst, templateWindowSize, searchWindowSize, &h[0]));
break; break;
case CV_8UC3: case 3:
if (hn == 1) if (hn == 1)
parallel_for_(cv::Range(0, src.rows), parallel_for_(cv::Range(0, src.rows),
FastNlMeansDenoisingInvoker<Vec3b, int, unsigned, DistSquared, int>( FastNlMeansDenoisingInvoker<Vec<ST, 3>, IT, UIT, D, int>(
src, dst, templateWindowSize, searchWindowSize, &h[0])); src, dst, templateWindowSize, searchWindowSize, &h[0]));
else else
parallel_for_(cv::Range(0, src.rows), parallel_for_(cv::Range(0, src.rows),
FastNlMeansDenoisingInvoker<Vec3b, int, unsigned, DistSquared, Vec3i>( FastNlMeansDenoisingInvoker<Vec<ST, 3>, IT, UIT, D, Vec3i>(
src, dst, templateWindowSize, searchWindowSize, &h[0])); src, dst, templateWindowSize, searchWindowSize, &h[0]));
break; break;
case CV_8UC4: case 4:
if (hn == 1) if (hn == 1)
parallel_for_(cv::Range(0, src.rows), parallel_for_(cv::Range(0, src.rows),
FastNlMeansDenoisingInvoker<Vec4b, int, unsigned, DistSquared, int>( FastNlMeansDenoisingInvoker<Vec<ST, 4>, IT, UIT, D, int>(
src, dst, templateWindowSize, searchWindowSize, &h[0])); src, dst, templateWindowSize, searchWindowSize, &h[0]));
else else
parallel_for_(cv::Range(0, src.rows), parallel_for_(cv::Range(0, src.rows),
FastNlMeansDenoisingInvoker<Vec4b, int, unsigned, DistSquared, Vec4i>( FastNlMeansDenoisingInvoker<Vec<ST, 4>, IT, UIT, D, Vec4i>(
src, dst, templateWindowSize, searchWindowSize, &h[0])); src, dst, templateWindowSize, searchWindowSize, &h[0]));
break; break;
default: default:
CV_Error(Error::StsBadArg, CV_Error(Error::StsBadArg,
"Unsupported image format! Only CV_8U, CV_8UC2, CV_8UC3 and CV_8UC4 are supported"); "Unsupported number of channels! Only 1, 2, 3, and 4 are supported");
}
}
void cv::fastNlMeansDenoising( InputArray _src, OutputArray _dst, float h,
int templateWindowSize, int searchWindowSize)
{
fastNlMeansDenoising(_src, _dst, std::vector<float>(1, h),
templateWindowSize, searchWindowSize);
}
void cv::fastNlMeansDenoising( InputArray _src, OutputArray _dst, const std::vector<float>& h,
int templateWindowSize, int searchWindowSize, int normType)
{
int hn = (int)h.size(), type = _src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
CV_Assert(hn == 1 || hn == cn);
Size src_size = _src.size();
CV_OCL_RUN(_src.dims() <= 2 && (_src.isUMat() || _dst.isUMat()) &&
src_size.width > 5 && src_size.height > 5, // low accuracy on small sizes
ocl_fastNlMeansDenoising(_src, _dst, &h[0], hn,
templateWindowSize, searchWindowSize, normType))
Mat src = _src.getMat();
_dst.create(src_size, src.type());
Mat dst = _dst.getMat();
switch (normType) {
case NORM_L2:
#ifdef HAVE_TEGRA_OPTIMIZATION
if(hn == 1 && tegra::useTegra() &&
tegra::fastNlMeansDenoising(src, dst, h[0], templateWindowSize, searchWindowSize))
return;
#endif
switch (depth) {
case CV_8U:
fastNlMeansDenoising_<uchar, int, unsigned, DistSquared>(src, dst, h,
templateWindowSize,
searchWindowSize);
break;
default:
CV_Error(Error::StsBadArg,
"Unsupported depth! Only CV_8U is supported for NORM_L2");
}
break;
case NORM_L1:
switch (depth) {
case CV_8U:
fastNlMeansDenoising_<uchar, int, unsigned, DistAbs>(src, dst, h,
templateWindowSize,
searchWindowSize);
break;
case CV_16U:
fastNlMeansDenoising_<ushort, int64, uint64, DistAbs>(src, dst, h,
templateWindowSize,
searchWindowSize);
break;
default:
CV_Error(Error::StsBadArg,
"Unsupported depth! Only CV_8U and CV_16U are supported for NORM_L1");
}
break;
default:
CV_Error(Error::StsBadArg,
"Unsupported norm type! Only NORM_L2 and NORM_L1 are supported");
} }
} }
......
...@@ -29,8 +29,10 @@ static int divUp(int a, int b) ...@@ -29,8 +29,10 @@ static int divUp(int a, int b)
} }
template <typename FT, typename ST, typename WT> template <typename FT, typename ST, typename WT>
static bool ocl_calcAlmostDist2Weight(UMat & almostDist2Weight, int searchWindowSize, int templateWindowSize, const FT *h, int hn, int cn, static bool ocl_calcAlmostDist2Weight(UMat & almostDist2Weight,
int & almostTemplateWindowSizeSqBinShift, bool abs) int searchWindowSize, int templateWindowSize,
const FT *h, int hn, int cn, int normType,
int & almostTemplateWindowSizeSqBinShift)
{ {
const WT maxEstimateSumValue = searchWindowSize * searchWindowSize * const WT maxEstimateSumValue = searchWindowSize * searchWindowSize *
std::numeric_limits<ST>::max(); std::numeric_limits<ST>::max();
...@@ -50,7 +52,7 @@ static bool ocl_calcAlmostDist2Weight(UMat & almostDist2Weight, int searchWindow ...@@ -50,7 +52,7 @@ static bool ocl_calcAlmostDist2Weight(UMat & almostDist2Weight, int searchWindow
FT almostDist2ActualDistMultiplier = (FT)(1 << almostTemplateWindowSizeSqBinShift) / templateWindowSizeSq; FT almostDist2ActualDistMultiplier = (FT)(1 << almostTemplateWindowSizeSqBinShift) / templateWindowSizeSq;
const FT WEIGHT_THRESHOLD = 1e-3f; const FT WEIGHT_THRESHOLD = 1e-3f;
int maxDist = abs ? std::numeric_limits<ST>::max() * cn : int maxDist = normType == NORM_L1 ? std::numeric_limits<ST>::max() * cn :
std::numeric_limits<ST>::max() * std::numeric_limits<ST>::max() * cn; std::numeric_limits<ST>::max() * std::numeric_limits<ST>::max() * cn;
int almostMaxDist = (int)(maxDist / almostDist2ActualDistMultiplier + 1); int almostMaxDist = (int)(maxDist / almostDist2ActualDistMultiplier + 1);
FT den[4]; FT den[4];
...@@ -66,7 +68,8 @@ static bool ocl_calcAlmostDist2Weight(UMat & almostDist2Weight, int searchWindow ...@@ -66,7 +68,8 @@ static bool ocl_calcAlmostDist2Weight(UMat & almostDist2Weight, int searchWindow
" -D wlut_t=%s -D convert_wlut_t=%s%s%s", " -D wlut_t=%s -D convert_wlut_t=%s%s%s",
ocl::typeToStr(depth), ocl::typeToStr(CV_MAKE_TYPE(depth, hn)), ocl::typeToStr(depth), ocl::typeToStr(CV_MAKE_TYPE(depth, hn)),
ocl::typeToStr(CV_32SC(hn)), ocl::convertTypeStr(depth, CV_32S, hn, buf), ocl::typeToStr(CV_32SC(hn)), ocl::convertTypeStr(depth, CV_32S, hn, buf),
doubleSupport ? " -D DOUBLE_SUPPORT" : "", abs ? " -D ABS" : "")); doubleSupport ? " -D DOUBLE_SUPPORT" : "",
normType == NORM_L1 ? " -D ABS" : ""));
if (k.empty()) if (k.empty())
return false; return false;
...@@ -79,13 +82,14 @@ static bool ocl_calcAlmostDist2Weight(UMat & almostDist2Weight, int searchWindow ...@@ -79,13 +82,14 @@ static bool ocl_calcAlmostDist2Weight(UMat & almostDist2Weight, int searchWindow
} }
static bool ocl_fastNlMeansDenoising(InputArray _src, OutputArray _dst, const float *h, int hn, static bool ocl_fastNlMeansDenoising(InputArray _src, OutputArray _dst, const float *h, int hn,
int templateWindowSize, int searchWindowSize, bool abs) int templateWindowSize, int searchWindowSize, int normType)
{ {
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);
int ctaSize = ocl::Device::getDefault().isIntel() ? CTA_SIZE_INTEL : CTA_SIZE_DEFAULT; int ctaSize = ocl::Device::getDefault().isIntel() ? CTA_SIZE_INTEL : CTA_SIZE_DEFAULT;
Size size = _src.size(); Size size = _src.size();
if (cn != 1 && cn != 2 && cn != 3 && cn != 4 && depth != CV_8U && (!abs || depth != CV_16U)) if (cn < 1 || cn > 4 || ((normType != NORM_L2 || depth != CV_8U) &&
(normType != NORM_L1 || (depth != CV_8U && depth != CV_16U))))
return false; return false;
int templateWindowHalfWize = templateWindowSize / 2; int templateWindowHalfWize = templateWindowSize / 2;
...@@ -117,7 +121,8 @@ static bool ocl_fastNlMeansDenoising(InputArray _src, OutputArray _dst, const fl ...@@ -117,7 +121,8 @@ static bool ocl_fastNlMeansDenoising(InputArray _src, OutputArray _dst, const fl
ctaSize, templateWindowHalfWize, searchWindowHalfSize, ctaSize, templateWindowHalfWize, searchWindowHalfSize,
ocl::convertTypeStr(depth, CV_32S, cn, buf[2]), cn, ocl::convertTypeStr(depth, CV_32S, cn, buf[2]), cn,
(depth == CV_8U ? sizeof(uchar) : sizeof(ushort)) * (cn == 3 ? 4 : cn), (depth == CV_8U ? sizeof(uchar) : sizeof(ushort)) * (cn == 3 ? 4 : cn),
ocl::convertTypeStr(CV_32S, depth, cn, buf[3]), abs ? " -D ABS" : ""); ocl::convertTypeStr(CV_32S, depth, cn, buf[3]),
normType == NORM_L1 ? " -D ABS" : "");
ocl::Kernel k("fastNlMeansDenoising", ocl::photo::nlmeans_oclsrc, opts); ocl::Kernel k("fastNlMeansDenoising", ocl::photo::nlmeans_oclsrc, opts);
if (k.empty()) if (k.empty())
...@@ -127,15 +132,13 @@ static bool ocl_fastNlMeansDenoising(InputArray _src, OutputArray _dst, const fl ...@@ -127,15 +132,13 @@ static bool ocl_fastNlMeansDenoising(InputArray _src, OutputArray _dst, const fl
if ((depth == CV_8U && if ((depth == CV_8U &&
!ocl_calcAlmostDist2Weight<float, uchar, int>(almostDist2Weight, !ocl_calcAlmostDist2Weight<float, uchar, int>(almostDist2Weight,
searchWindowSize, templateWindowSize, searchWindowSize, templateWindowSize,
h, hn, cn, h, hn, cn, normType,
almostTemplateWindowSizeSqBinShift, almostTemplateWindowSizeSqBinShift)) ||
abs)) ||
(depth == CV_16U && (depth == CV_16U &&
!ocl_calcAlmostDist2Weight<float, ushort, int64>(almostDist2Weight, !ocl_calcAlmostDist2Weight<float, ushort, int64>(almostDist2Weight,
searchWindowSize, templateWindowSize, searchWindowSize, templateWindowSize,
h, hn, cn, h, hn, cn, normType,
almostTemplateWindowSizeSqBinShift, almostTemplateWindowSizeSqBinShift)))
abs)))
return false; return false;
CV_Assert(almostTemplateWindowSizeSqBinShift >= 0); CV_Assert(almostTemplateWindowSizeSqBinShift >= 0);
......
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