Minor refactoring of NL-means denoising

This commit is contained in:
Andrey Kamaev 2012-09-17 17:18:04 +04:00
parent 3c4917555d
commit 7e35838849
5 changed files with 201 additions and 200 deletions

View File

@ -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");
}
}

View File

@ -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,12 +111,12 @@ 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;
template_window_size_ = template_window_half_size_ * 2 + 1;
search_window_size_ = search_window_half_size_ * 2 + 1;
search_window_half_size_ = search_window_size / 2;
template_window_size_ = template_window_half_size_ * 2 + 1;
search_window_size_ = search_window_half_size_ * 2 + 1;
border_size_ = search_window_half_size_ + template_window_half_size_;
copyMakeBorder(src_, extended_src_,
@ -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];

View File

@ -63,9 +63,9 @@ struct FastNlMeansMultiDenoisingInvoker {
void operator() (const BlockedRange& range) const;
void operator= (const FastNlMeansMultiDenoisingInvoker&) {
CV_Error(CV_StsNotImplemented, "Assigment operator is not implemented");
}
void operator= (const FastNlMeansMultiDenoisingInvoker&) {
CV_Error(CV_StsNotImplemented, "Assigment operator is not implemented");
}
private:
int rows_;
@ -186,7 +186,7 @@ void FastNlMeansMultiDenoisingInvoker<T>::operator() (const BlockedRange& range)
// for lazy calc optimization
Array4d<int> col_dist_sums(
template_window_size_, temporal_window_size_, search_window_size_, search_window_size_);
template_window_size_, temporal_window_size_, search_window_size_, search_window_size_);
int first_col_num = -1;