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