|
|
|
@ -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]; |
|
|
|
|