Commit 7e358388 authored by Andrey Kamaev's avatar Andrey Kamaev

Minor refactoring of NL-means denoising

parent 3c491755
......@@ -70,7 +70,7 @@ void cv::fastNlMeansDenoising( InputArray _src, OutputArray _dst,
break;
default:
CV_Error(CV_StsBadArg,
"Unsupported matrix format! Only uchar, Vec2b, Vec3b are supported");
"Unsupported image format! Only CV_8UC1, CV_8UC2 and CV_8UC3 are supported");
}
}
......
......@@ -62,11 +62,9 @@ struct FastNlMeansDenoisingInvoker {
void operator() (const BlockedRange& range) const;
void operator= (const FastNlMeansDenoisingInvoker&) {
CV_Error(CV_StsNotImplemented, "Assigment operator is not implemented");
}
private:
void operator= (const FastNlMeansDenoisingInvoker&);
const Mat& src_;
Mat& dst_;
......@@ -80,8 +78,8 @@ struct FastNlMeansDenoisingInvoker {
int search_window_half_size_;
int fixed_point_mult_;
int almost_template_window_size_sq_bin_shift;
vector<int> almost_dist2weight;
int almost_template_window_size_sq_bin_shift_;
vector<int> almost_dist2weight_;
void calcDistSumsForFirstElementInRow(
int i,
......@@ -98,6 +96,13 @@ struct FastNlMeansDenoisingInvoker {
Array3d<int>& up_col_dist_sums) const;
};
inline int getNearestPowerOf2(int value)
{
int p = 0;
while( 1 << p < value) ++p;
return p;
}
template <class T>
FastNlMeansDenoisingInvoker<T>::FastNlMeansDenoisingInvoker(
const cv::Mat& src,
......@@ -106,7 +111,7 @@ FastNlMeansDenoisingInvoker<T>::FastNlMeansDenoisingInvoker(
int search_window_size,
const double h) : src_(src), dst_(dst)
{
CV_Assert(src.channels() <= 3);
CV_Assert(src.channels() == sizeof(T)); //T is Vec1b or Vec2b or Vec3b
template_window_half_size_ = template_window_size / 2;
search_window_half_size_ = search_window_size / 2;
......@@ -122,19 +127,15 @@ FastNlMeansDenoisingInvoker<T>::FastNlMeansDenoisingInvoker(
// precalc weight for every possible l2 dist between blocks
// additional optimization of precalced weights to replace division(averaging) by binary shift
int template_window_size_sq = template_window_size_ * template_window_size_;
almost_template_window_size_sq_bin_shift = 0;
while (1 << almost_template_window_size_sq_bin_shift < template_window_size_sq) {
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;
CV_Assert(template_window_size_ <= 46340 ); // sqrt(INT_MAX)
int template_window_size_sq = template_window_size_ * template_window_size_;
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;
int max_dist = 256 * 256 * src_.channels();
int almost_max_dist = (int) (max_dist / almost_dist2actual_dist_multiplier + 1);
almost_dist2weight.resize(almost_max_dist);
almost_dist2weight_.resize(almost_max_dist);
const double WEIGHT_THRESHOLD = 0.001;
for (int almost_dist = 0; almost_dist < almost_max_dist; almost_dist++) {
......@@ -145,7 +146,7 @@ FastNlMeansDenoisingInvoker<T>::FastNlMeansDenoisingInvoker(
weight = 0;
}
almost_dist2weight[almost_dist] = weight;
almost_dist2weight_[almost_dist] = weight;
}
// additional optimization init end
......@@ -245,9 +246,9 @@ void FastNlMeansDenoisingInvoker<T>::operator() (const BlockedRange& range) cons
int* dist_sums_row = dist_sums.row_ptr(y);
for (int x = 0; x < search_window_size_; x++) {
int almostAvgDist =
dist_sums_row[x] >> almost_template_window_size_sq_bin_shift;
dist_sums_row[x] >> almost_template_window_size_sq_bin_shift_;
int weight = almost_dist2weight[almostAvgDist];
int weight = almost_dist2weight_[almostAvgDist];
weights_sum += weight;
T p = cur_row_ptr[border_size_ + search_window_x + x];
......
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