Commit e16d89e8 authored by Ilya Lavrenov's avatar Ilya Lavrenov

some refactoring

parent edbff688
...@@ -51,14 +51,16 @@ ...@@ -51,14 +51,16 @@
using namespace cv; using namespace cv;
template <typename T> template <typename T>
struct FastNlMeansDenoisingInvoker : ParallelLoopBody { struct FastNlMeansDenoisingInvoker :
public: public ParallelLoopBody
{
public:
FastNlMeansDenoisingInvoker(const Mat& src, Mat& dst, FastNlMeansDenoisingInvoker(const Mat& src, Mat& dst,
int template_window_size, int search_window_size, const float h); int template_window_size, int search_window_size, const float h);
void operator() (const Range& range) const; void operator() (const Range& range) const;
private: private:
void operator= (const FastNlMeansDenoisingInvoker&); void operator= (const FastNlMeansDenoisingInvoker&);
const Mat& src_; const Mat& src_;
...@@ -78,15 +80,12 @@ struct FastNlMeansDenoisingInvoker : ParallelLoopBody { ...@@ -78,15 +80,12 @@ struct FastNlMeansDenoisingInvoker : ParallelLoopBody {
std::vector<int> almost_dist2weight_; std::vector<int> almost_dist2weight_;
void calcDistSumsForFirstElementInRow( void calcDistSumsForFirstElementInRow(
int i, int i, Array2d<int>& dist_sums,
Array2d<int>& dist_sums,
Array3d<int>& col_dist_sums, Array3d<int>& col_dist_sums,
Array3d<int>& up_col_dist_sums) const; Array3d<int>& up_col_dist_sums) const;
void calcDistSumsForElementInFirstRow( void calcDistSumsForElementInFirstRow(
int i, int i, int j, int first_col_num,
int j,
int first_col_num,
Array2d<int>& dist_sums, Array2d<int>& dist_sums,
Array3d<int>& col_dist_sums, Array3d<int>& col_dist_sums,
Array3d<int>& up_col_dist_sums) const; Array3d<int>& up_col_dist_sums) const;
...@@ -95,17 +94,18 @@ struct FastNlMeansDenoisingInvoker : ParallelLoopBody { ...@@ -95,17 +94,18 @@ struct FastNlMeansDenoisingInvoker : ParallelLoopBody {
inline int getNearestPowerOf2(int value) inline int getNearestPowerOf2(int value)
{ {
int p = 0; int p = 0;
while( 1 << p < value) ++p; while( 1 << p < value)
++p;
return p; return p;
} }
template <class T> template <class T>
FastNlMeansDenoisingInvoker<T>::FastNlMeansDenoisingInvoker( FastNlMeansDenoisingInvoker<T>::FastNlMeansDenoisingInvoker(
const cv::Mat& src, const cv::Mat& src, cv::Mat& dst,
cv::Mat& dst,
int template_window_size, int template_window_size,
int search_window_size, int search_window_size,
const float h) : src_(src), dst_(dst) const float h) :
src_(src), dst_(dst)
{ {
CV_Assert(src.channels() == sizeof(T)); //T is Vec1b or Vec2b or Vec3b CV_Assert(src.channels() == sizeof(T)); //T is Vec1b or Vec2b or Vec3b
...@@ -134,7 +134,8 @@ FastNlMeansDenoisingInvoker<T>::FastNlMeansDenoisingInvoker( ...@@ -134,7 +134,8 @@ FastNlMeansDenoisingInvoker<T>::FastNlMeansDenoisingInvoker(
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++)
{
double dist = almost_dist * almost_dist2actual_dist_multiplier; double dist = almost_dist * almost_dist2actual_dist_multiplier;
int weight = cvRound(fixed_point_mult_ * std::exp(-dist / (h * h * sizeof(T)))); int weight = cvRound(fixed_point_mult_ * std::exp(-dist / (h * h * sizeof(T))));
...@@ -144,15 +145,15 @@ FastNlMeansDenoisingInvoker<T>::FastNlMeansDenoisingInvoker( ...@@ -144,15 +145,15 @@ FastNlMeansDenoisingInvoker<T>::FastNlMeansDenoisingInvoker(
almost_dist2weight_[almost_dist] = weight; almost_dist2weight_[almost_dist] = weight;
} }
CV_Assert(almost_dist2weight_[0] == fixed_point_mult_); CV_Assert(almost_dist2weight_[0] == fixed_point_mult_);
// additional optimization init end
if (dst_.empty()) { // additional optimization init end
if (dst_.empty())
dst_ = Mat::zeros(src_.size(), src_.type()); dst_ = Mat::zeros(src_.size(), src_.type());
}
} }
template <class T> template <class T>
void FastNlMeansDenoisingInvoker<T>::operator() (const Range& range) const { void FastNlMeansDenoisingInvoker<T>::operator() (const Range& range) const
{
int row_from = range.start; int row_from = range.start;
int row_to = range.end - 1; int row_to = range.end - 1;
...@@ -164,30 +165,36 @@ void FastNlMeansDenoisingInvoker<T>::operator() (const Range& range) const { ...@@ -164,30 +165,36 @@ void FastNlMeansDenoisingInvoker<T>::operator() (const Range& range) const {
int first_col_num = -1; int first_col_num = -1;
Array3d<int> up_col_dist_sums(src_.cols, search_window_size_, search_window_size_); Array3d<int> up_col_dist_sums(src_.cols, search_window_size_, search_window_size_);
for (int i = row_from; i <= row_to; i++) { for (int i = row_from; i <= row_to; i++)
for (int j = 0; j < src_.cols; j++) { {
for (int j = 0; j < src_.cols; j++)
{
int search_window_y = i - search_window_half_size_; int search_window_y = i - search_window_half_size_;
int search_window_x = j - search_window_half_size_; int search_window_x = j - search_window_half_size_;
// calc dist_sums // calc dist_sums
if (j == 0) { if (j == 0)
{
calcDistSumsForFirstElementInRow(i, dist_sums, col_dist_sums, up_col_dist_sums); calcDistSumsForFirstElementInRow(i, dist_sums, col_dist_sums, up_col_dist_sums);
first_col_num = 0; first_col_num = 0;
} else { // calc cur dist_sums using previous dist_sums }
if (i == row_from) { else
{
// calc cur dist_sums using previous dist_sums
if (i == row_from)
{
calcDistSumsForElementInFirstRow(i, j, first_col_num, calcDistSumsForElementInFirstRow(i, j, first_col_num,
dist_sums, col_dist_sums, up_col_dist_sums); dist_sums, col_dist_sums, up_col_dist_sums);
} else { }
else
{
int ay = border_size_ + i; int ay = border_size_ + i;
int ax = border_size_ + j + template_window_half_size_; int ax = border_size_ + j + template_window_half_size_;
int start_by = int start_by = border_size_ + i - search_window_half_size_;
border_size_ + i - search_window_half_size_; int start_bx = border_size_ + j - search_window_half_size_ + template_window_half_size_;
int start_bx =
border_size_ + j - search_window_half_size_ + template_window_half_size_;
T a_up = extended_src_.at<T>(ay - template_window_half_size_ - 1, ax); T a_up = extended_src_.at<T>(ay - template_window_half_size_ - 1, ax);
T a_down = extended_src_.at<T>(ay + template_window_half_size_, ax); T a_down = extended_src_.at<T>(ay + template_window_half_size_, ax);
...@@ -195,20 +202,18 @@ void FastNlMeansDenoisingInvoker<T>::operator() (const Range& range) const { ...@@ -195,20 +202,18 @@ void FastNlMeansDenoisingInvoker<T>::operator() (const Range& range) const {
// copy class member to local variable for optimization // copy class member to local variable for optimization
int search_window_size = search_window_size_; int search_window_size = search_window_size_;
for (int y = 0; y < search_window_size; y++) { for (int y = 0; y < search_window_size; y++)
{
int* dist_sums_row = dist_sums.row_ptr(y); int* dist_sums_row = dist_sums.row_ptr(y);
int* col_dist_sums_row = col_dist_sums.row_ptr(first_col_num,y); int* col_dist_sums_row = col_dist_sums.row_ptr(first_col_num,y);
int* up_col_dist_sums_row = up_col_dist_sums.row_ptr(j, y); int* up_col_dist_sums_row = up_col_dist_sums.row_ptr(j, y);
const T* b_up_ptr = const T* b_up_ptr = extended_src_.ptr<T>(start_by - template_window_half_size_ - 1 + y);
extended_src_.ptr<T>(start_by - template_window_half_size_ - 1 + y); const T* b_down_ptr = extended_src_.ptr<T>(start_by + template_window_half_size_ + y);
const T* b_down_ptr = for (int x = 0; x < search_window_size; x++)
extended_src_.ptr<T>(start_by + template_window_half_size_ + y); {
for (int x = 0; x < search_window_size; x++) {
dist_sums_row[x] -= col_dist_sums_row[x]; dist_sums_row[x] -= col_dist_sums_row[x];
col_dist_sums_row[x] = col_dist_sums_row[x] =
...@@ -233,14 +238,15 @@ void FastNlMeansDenoisingInvoker<T>::operator() (const Range& range) const { ...@@ -233,14 +238,15 @@ void FastNlMeansDenoisingInvoker<T>::operator() (const Range& range) const {
int weights_sum = 0; int weights_sum = 0;
int estimation[3]; int estimation[3];
for (size_t channel_num = 0; channel_num < sizeof(T); channel_num++) { for (size_t channel_num = 0; channel_num < sizeof(T); channel_num++)
estimation[channel_num] = 0; estimation[channel_num] = 0;
}
for (int y = 0; y < search_window_size_; y++) { for (int y = 0; y < search_window_size_; y++)
{
const T* cur_row_ptr = extended_src_.ptr<T>(border_size_ + search_window_y + y); const T* cur_row_ptr = extended_src_.ptr<T>(border_size_ + search_window_y + y);
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_;
...@@ -269,18 +275,19 @@ inline void FastNlMeansDenoisingInvoker<T>::calcDistSumsForFirstElementInRow( ...@@ -269,18 +275,19 @@ inline void FastNlMeansDenoisingInvoker<T>::calcDistSumsForFirstElementInRow(
{ {
int j = 0; int j = 0;
for (int y = 0; y < search_window_size_; y++) { for (int y = 0; y < search_window_size_; y++)
for (int x = 0; x < search_window_size_; x++) { for (int x = 0; x < search_window_size_; x++)
{
dist_sums[y][x] = 0; dist_sums[y][x] = 0;
for (int tx = 0; tx < template_window_size_; tx++) { for (int tx = 0; tx < template_window_size_; tx++)
col_dist_sums[tx][y][x] = 0; col_dist_sums[tx][y][x] = 0;
}
int start_y = i + y - search_window_half_size_; int start_y = i + y - search_window_half_size_;
int start_x = j + x - search_window_half_size_; int start_x = j + x - search_window_half_size_;
for (int ty = -template_window_half_size_; ty <= template_window_half_size_; ty++) { for (int ty = -template_window_half_size_; ty <= template_window_half_size_; ty++)
for (int tx = -template_window_half_size_; tx <= template_window_half_size_; tx++) { for (int tx = -template_window_half_size_; tx <= template_window_half_size_; tx++)
{
int dist = calcDist<T>(extended_src_, int dist = calcDist<T>(extended_src_,
border_size_ + i + ty, border_size_ + j + tx, border_size_ + i + ty, border_size_ + j + tx,
border_size_ + start_y + ty, border_size_ + start_x + tx); border_size_ + start_y + ty, border_size_ + start_x + tx);
...@@ -288,11 +295,9 @@ inline void FastNlMeansDenoisingInvoker<T>::calcDistSumsForFirstElementInRow( ...@@ -288,11 +295,9 @@ inline void FastNlMeansDenoisingInvoker<T>::calcDistSumsForFirstElementInRow(
dist_sums[y][x] += dist; dist_sums[y][x] += dist;
col_dist_sums[tx + template_window_half_size_][y][x] += dist; col_dist_sums[tx + template_window_half_size_][y][x] += dist;
} }
}
up_col_dist_sums[j][y][x] = col_dist_sums[template_window_size_ - 1][y][x]; up_col_dist_sums[j][y][x] = col_dist_sums[template_window_size_ - 1][y][x];
} }
}
} }
template <class T> template <class T>
...@@ -312,23 +317,21 @@ inline void FastNlMeansDenoisingInvoker<T>::calcDistSumsForElementInFirstRow( ...@@ -312,23 +317,21 @@ inline void FastNlMeansDenoisingInvoker<T>::calcDistSumsForElementInFirstRow(
int new_last_col_num = first_col_num; int new_last_col_num = first_col_num;
for (int y = 0; y < search_window_size_; y++) { for (int y = 0; y < search_window_size_; y++)
for (int x = 0; x < search_window_size_; x++) { for (int x = 0; x < search_window_size_; x++)
{
dist_sums[y][x] -= col_dist_sums[first_col_num][y][x]; dist_sums[y][x] -= col_dist_sums[first_col_num][y][x];
col_dist_sums[new_last_col_num][y][x] = 0; col_dist_sums[new_last_col_num][y][x] = 0;
int by = start_by + y; int by = start_by + y;
int bx = start_bx + x; int bx = start_bx + x;
for (int ty = -template_window_half_size_; ty <= template_window_half_size_; ty++) { for (int ty = -template_window_half_size_; ty <= template_window_half_size_; ty++)
col_dist_sums[new_last_col_num][y][x] += col_dist_sums[new_last_col_num][y][x] +=
calcDist<T>(extended_src_, ay + ty, ax, by + ty, bx); calcDist<T>(extended_src_, ay + ty, ax, by + ty, bx);
}
dist_sums[y][x] += col_dist_sums[new_last_col_num][y][x]; dist_sums[y][x] += col_dist_sums[new_last_col_num][y][x];
up_col_dist_sums[j][y][x] = col_dist_sums[new_last_col_num][y][x]; up_col_dist_sums[j][y][x] = col_dist_sums[new_last_col_num][y][x];
} }
}
} }
#endif #endif
...@@ -46,29 +46,35 @@ using namespace cv; ...@@ -46,29 +46,35 @@ using namespace cv;
template <typename T> static inline int calcDist(const T a, const T b); template <typename T> static inline int calcDist(const T a, const T b);
template <> inline int calcDist(const uchar a, const uchar b) { template <> inline int calcDist(const uchar a, const uchar b)
{
return (a-b) * (a-b); return (a-b) * (a-b);
} }
template <> inline int calcDist(const Vec2b a, const Vec2b b) { template <> inline int calcDist(const Vec2b a, const Vec2b b)
{
return (a[0]-b[0])*(a[0]-b[0]) + (a[1]-b[1])*(a[1]-b[1]); return (a[0]-b[0])*(a[0]-b[0]) + (a[1]-b[1])*(a[1]-b[1]);
} }
template <> inline int calcDist(const Vec3b a, const Vec3b b) { template <> inline int calcDist(const Vec3b a, const Vec3b b)
{
return (a[0]-b[0])*(a[0]-b[0]) + (a[1]-b[1])*(a[1]-b[1]) + (a[2]-b[2])*(a[2]-b[2]); return (a[0]-b[0])*(a[0]-b[0]) + (a[1]-b[1])*(a[1]-b[1]) + (a[2]-b[2])*(a[2]-b[2]);
} }
template <typename T> static inline int calcDist(const Mat& m, int i1, int j1, int i2, int j2) { template <typename T> static inline int calcDist(const Mat& m, int i1, int j1, int i2, int j2)
{
const T a = m.at<T>(i1, j1); const T a = m.at<T>(i1, j1);
const T b = m.at<T>(i2, j2); const T b = m.at<T>(i2, j2);
return calcDist<T>(a,b); return calcDist<T>(a,b);
} }
template <typename T> static inline int calcUpDownDist(T a_up, T a_down, T b_up, T b_down) { template <typename T> static inline int calcUpDownDist(T a_up, T a_down, T b_up, T b_down)
{
return calcDist(a_down,b_down) - calcDist(a_up, b_up); return calcDist(a_down,b_down) - calcDist(a_up, b_up);
} }
template <> inline int calcUpDownDist(uchar a_up, uchar a_down, uchar b_up, uchar b_down) { template <> inline int calcUpDownDist(uchar a_up, uchar a_down, uchar b_up, uchar b_down)
{
int A = a_down - b_down; int A = a_down - b_down;
int B = a_up - b_up; int B = a_up - b_up;
return (A-B)*(A+B); return (A-B)*(A+B);
...@@ -76,16 +82,20 @@ template <> inline int calcUpDownDist(uchar a_up, uchar a_down, uchar b_up, uch ...@@ -76,16 +82,20 @@ template <> inline int calcUpDownDist(uchar a_up, uchar a_down, uchar b_up, uch
template <typename T> static inline void incWithWeight(int* estimation, int weight, T p); template <typename T> static inline void incWithWeight(int* estimation, int weight, T p);
template <> inline void incWithWeight(int* estimation, int weight, uchar p) { template <> inline void incWithWeight(int* estimation, int weight, uchar p)
{
estimation[0] += weight * p; estimation[0] += weight * p;
} }
template <> inline void incWithWeight(int* estimation, int weight, Vec2b p) { template <> inline void incWithWeight(int* estimation, int weight, Vec2b p)
{
estimation[0] += weight * p[0]; estimation[0] += weight * p[0];
estimation[1] += weight * p[1]; estimation[1] += weight * p[1];
} }
template <> inline void incWithWeight(int* estimation, int weight, Vec3b p) { template <> inline void incWithWeight(int* estimation, int weight, Vec3b p)
{
estimation[0] += weight * p[0]; estimation[0] += weight * p[0];
estimation[1] += weight * p[1]; estimation[1] += weight * p[1];
estimation[2] += weight * p[2]; estimation[2] += weight * p[2];
...@@ -93,18 +103,21 @@ template <> inline void incWithWeight(int* estimation, int weight, Vec3b p) { ...@@ -93,18 +103,21 @@ template <> inline void incWithWeight(int* estimation, int weight, Vec3b p) {
template <typename T> static inline T saturateCastFromArray(int* estimation); template <typename T> static inline T saturateCastFromArray(int* estimation);
template <> inline uchar saturateCastFromArray(int* estimation) { template <> inline uchar saturateCastFromArray(int* estimation)
{
return saturate_cast<uchar>(estimation[0]); return saturate_cast<uchar>(estimation[0]);
} }
template <> inline Vec2b saturateCastFromArray(int* estimation) { template <> inline Vec2b saturateCastFromArray(int* estimation)
{
Vec2b res; Vec2b res;
res[0] = saturate_cast<uchar>(estimation[0]); res[0] = saturate_cast<uchar>(estimation[0]);
res[1] = saturate_cast<uchar>(estimation[1]); res[1] = saturate_cast<uchar>(estimation[1]);
return res; return res;
} }
template <> inline Vec3b saturateCastFromArray(int* estimation) { template <> inline Vec3b saturateCastFromArray(int* estimation)
{
Vec3b res; Vec3b res;
res[0] = saturate_cast<uchar>(estimation[0]); res[0] = saturate_cast<uchar>(estimation[0]);
res[1] = saturate_cast<uchar>(estimation[1]); res[1] = saturate_cast<uchar>(estimation[1]);
......
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