Commit d27068f7 authored by Ilya Lavrenov's avatar Ilya Lavrenov

some more refactoring

parent e16d89e8
...@@ -39,10 +39,14 @@ ...@@ -39,10 +39,14 @@
// //
//M*/ //M*/
#include "opencv2/core/base.hpp"
#ifndef __OPENCV_DENOISING_ARRAYS_HPP__ #ifndef __OPENCV_DENOISING_ARRAYS_HPP__
#define __OPENCV_DENOISING_ARRAYS_HPP__ #define __OPENCV_DENOISING_ARRAYS_HPP__
template <class T> struct Array2d { template <class T>
struct Array2d
{
T* a; T* a;
int n1,n2; int n1,n2;
bool needToDeallocArray; bool needToDeallocArray;
...@@ -50,14 +54,16 @@ template <class T> struct Array2d { ...@@ -50,14 +54,16 @@ template <class T> struct Array2d {
Array2d(const Array2d& array2d): Array2d(const Array2d& array2d):
a(array2d.a), n1(array2d.n1), n2(array2d.n2), needToDeallocArray(false) a(array2d.a), n1(array2d.n1), n2(array2d.n2), needToDeallocArray(false)
{ {
if (array2d.needToDeallocArray) { if (array2d.needToDeallocArray)
// copy constructor for self allocating arrays not supported {
throw new std::exception(); CV_Error(Error::BadDataPtr, "Copy constructor for self allocating arrays not supported");
} }
} }
Array2d(T* _a, int _n1, int _n2): Array2d(T* _a, int _n1, int _n2):
a(_a), n1(_n1), n2(_n2), needToDeallocArray(false) {} a(_a), n1(_n1), n2(_n2), needToDeallocArray(false)
{
}
Array2d(int _n1, int _n2): Array2d(int _n1, int _n2):
n1(_n1), n2(_n2), needToDeallocArray(true) n1(_n1), n2(_n2), needToDeallocArray(true)
...@@ -65,28 +71,34 @@ template <class T> struct Array2d { ...@@ -65,28 +71,34 @@ template <class T> struct Array2d {
a = new T[n1*n2]; a = new T[n1*n2];
} }
~Array2d() { ~Array2d()
if (needToDeallocArray) { {
if (needToDeallocArray)
delete[] a; delete[] a;
}
} }
T* operator [] (int i) { T* operator [] (int i)
{
return a + i*n2; return a + i*n2;
} }
inline T* row_ptr(int i) { inline T* row_ptr(int i)
{
return (*this)[i]; return (*this)[i];
} }
}; };
template <class T> struct Array3d { template <class T>
struct Array3d
{
T* a; T* a;
int n1,n2,n3; int n1,n2,n3;
bool needToDeallocArray; bool needToDeallocArray;
Array3d(T* _a, int _n1, int _n2, int _n3): Array3d(T* _a, int _n1, int _n2, int _n3):
a(_a), n1(_n1), n2(_n2), n3(_n3), needToDeallocArray(false) {} a(_a), n1(_n1), n2(_n2), n3(_n3), needToDeallocArray(false)
{
}
Array3d(int _n1, int _n2, int _n3): Array3d(int _n1, int _n2, int _n3):
n1(_n1), n2(_n2), n3(_n3), needToDeallocArray(true) n1(_n1), n2(_n2), n3(_n3), needToDeallocArray(true)
...@@ -94,64 +106,72 @@ template <class T> struct Array3d { ...@@ -94,64 +106,72 @@ template <class T> struct Array3d {
a = new T[n1*n2*n3]; a = new T[n1*n2*n3];
} }
~Array3d() { ~Array3d()
if (needToDeallocArray) { {
if (needToDeallocArray)
delete[] a; delete[] a;
}
} }
Array2d<T> operator [] (int i) { Array2d<T> operator [] (int i)
{
Array2d<T> array2d(a + i*n2*n3, n2, n3); Array2d<T> array2d(a + i*n2*n3, n2, n3);
return array2d; return array2d;
} }
inline T* row_ptr(int i1, int i2) { inline T* row_ptr(int i1, int i2)
{
return a + i1*n2*n3 + i2*n3; return a + i1*n2*n3 + i2*n3;
} }
}; };
template <class T> struct Array4d { template <class T>
struct Array4d
{
T* a; T* a;
int n1,n2,n3,n4; int n1,n2,n3,n4;
bool needToDeallocArray; bool needToDeallocArray;
int steps[4]; int steps[4];
void init_steps() { void init_steps()
{
steps[0] = n2*n3*n4; steps[0] = n2*n3*n4;
steps[1] = n3*n4; steps[1] = n3*n4;
steps[2] = n4; steps[2] = n4;
steps[3] = 1; steps[3] = 1;
} }
Array4d(T* _a, int _n1, int _n2, int _n3, int _n4): Array4d(T* _a, int _n1, int _n2, int _n3, int _n4) :
a(_a), n1(_n1), n2(_n2), n3(_n3), n4(_n4), needToDeallocArray(false) a(_a), n1(_n1), n2(_n2), n3(_n3), n4(_n4), needToDeallocArray(false)
{ {
init_steps(); init_steps();
} }
Array4d(int _n1, int _n2, int _n3, int _n4): Array4d(int _n1, int _n2, int _n3, int _n4) :
n1(_n1), n2(_n2), n3(_n3), n4(_n4), needToDeallocArray(true) n1(_n1), n2(_n2), n3(_n3), n4(_n4), needToDeallocArray(true)
{ {
a = new T[n1*n2*n3*n4]; a = new T[n1*n2*n3*n4];
init_steps(); init_steps();
} }
~Array4d() { ~Array4d()
if (needToDeallocArray) { {
if (needToDeallocArray)
delete[] a; delete[] a;
}
} }
Array3d<T> operator [] (int i) { Array3d<T> operator [] (int i)
{
Array3d<T> array3d(a + i*n2*n3*n4, n2, n3, n4); Array3d<T> array3d(a + i*n2*n3*n4, n2, n3, n4);
return array3d; return array3d;
} }
inline T* row_ptr(int i1, int i2, int i3) { inline T* row_ptr(int i1, int i2, int i3)
{
return a + i1*n2*n3*n4 + i2*n3*n4 + i3*n4; return a + i1*n2*n3*n4 + i2*n3*n4 + i3*n4;
} }
inline int step_size(int dimension) { inline int step_size(int dimension)
{
return steps[dimension]; return steps[dimension];
} }
}; };
......
...@@ -117,7 +117,8 @@ static void fastNlMeansDenoisingMultiCheckPreconditions( ...@@ -117,7 +117,8 @@ static void fastNlMeansDenoisingMultiCheckPreconditions(
int templateWindowSize, int searchWindowSize) int templateWindowSize, int searchWindowSize)
{ {
int src_imgs_size = static_cast<int>(srcImgs.size()); int src_imgs_size = static_cast<int>(srcImgs.size());
if (src_imgs_size == 0) { if (src_imgs_size == 0)
{
CV_Error(Error::StsBadArg, "Input images vector should not be empty!"); CV_Error(Error::StsBadArg, "Input images vector should not be empty!");
} }
...@@ -136,11 +137,11 @@ static void fastNlMeansDenoisingMultiCheckPreconditions( ...@@ -136,11 +137,11 @@ static void fastNlMeansDenoisingMultiCheckPreconditions(
"should be choosen corresponding srcImgs size!"); "should be choosen corresponding srcImgs size!");
} }
for (int i = 1; i < src_imgs_size; i++) { for (int i = 1; i < src_imgs_size; i++)
if (srcImgs[0].size() != srcImgs[i].size() || srcImgs[0].type() != srcImgs[i].type()) { if (srcImgs[0].size() != srcImgs[i].size() || srcImgs[0].type() != srcImgs[i].type())
{
CV_Error(Error::StsBadArg, "Input images should have the same size and type!"); CV_Error(Error::StsBadArg, "Input images should have the same size and type!");
} }
}
} }
void cv::fastNlMeansDenoisingMulti( InputArrayOfArrays _srcImgs, OutputArray _dst, void cv::fastNlMeansDenoisingMulti( InputArrayOfArrays _srcImgs, OutputArray _dst,
...@@ -152,12 +153,13 @@ void cv::fastNlMeansDenoisingMulti( InputArrayOfArrays _srcImgs, OutputArray _ds ...@@ -152,12 +153,13 @@ void cv::fastNlMeansDenoisingMulti( InputArrayOfArrays _srcImgs, OutputArray _ds
fastNlMeansDenoisingMultiCheckPreconditions( fastNlMeansDenoisingMultiCheckPreconditions(
srcImgs, imgToDenoiseIndex, srcImgs, imgToDenoiseIndex,
temporalWindowSize, templateWindowSize, searchWindowSize temporalWindowSize, templateWindowSize, searchWindowSize);
);
_dst.create(srcImgs[0].size(), srcImgs[0].type()); _dst.create(srcImgs[0].size(), srcImgs[0].type());
Mat dst = _dst.getMat(); Mat dst = _dst.getMat();
switch (srcImgs[0].type()) { switch (srcImgs[0].type())
{
case CV_8U: case CV_8U:
parallel_for_(cv::Range(0, srcImgs[0].rows), parallel_for_(cv::Range(0, srcImgs[0].rows),
FastNlMeansMultiDenoisingInvoker<uchar>( FastNlMeansMultiDenoisingInvoker<uchar>(
...@@ -192,15 +194,15 @@ void cv::fastNlMeansDenoisingColoredMulti( InputArrayOfArrays _srcImgs, OutputAr ...@@ -192,15 +194,15 @@ void cv::fastNlMeansDenoisingColoredMulti( InputArrayOfArrays _srcImgs, OutputAr
fastNlMeansDenoisingMultiCheckPreconditions( fastNlMeansDenoisingMultiCheckPreconditions(
srcImgs, imgToDenoiseIndex, srcImgs, imgToDenoiseIndex,
temporalWindowSize, templateWindowSize, searchWindowSize temporalWindowSize, templateWindowSize, searchWindowSize);
);
_dst.create(srcImgs[0].size(), srcImgs[0].type()); _dst.create(srcImgs[0].size(), srcImgs[0].type());
Mat dst = _dst.getMat(); Mat dst = _dst.getMat();
int src_imgs_size = static_cast<int>(srcImgs.size()); int src_imgs_size = static_cast<int>(srcImgs.size());
if (srcImgs[0].type() != CV_8UC3) { if (srcImgs[0].type() != CV_8UC3)
{
CV_Error(Error::StsBadArg, "Type of input images should be CV_8UC3!"); CV_Error(Error::StsBadArg, "Type of input images should be CV_8UC3!");
return; return;
} }
...@@ -211,7 +213,8 @@ void cv::fastNlMeansDenoisingColoredMulti( InputArrayOfArrays _srcImgs, OutputAr ...@@ -211,7 +213,8 @@ void cv::fastNlMeansDenoisingColoredMulti( InputArrayOfArrays _srcImgs, OutputAr
std::vector<Mat> src_lab(src_imgs_size); std::vector<Mat> src_lab(src_imgs_size);
std::vector<Mat> l(src_imgs_size); std::vector<Mat> l(src_imgs_size);
std::vector<Mat> ab(src_imgs_size); std::vector<Mat> ab(src_imgs_size);
for (int i = 0; i < src_imgs_size; i++) { for (int i = 0; i < src_imgs_size; i++)
{
src_lab[i] = Mat::zeros(srcImgs[0].size(), CV_8UC3); src_lab[i] = Mat::zeros(srcImgs[0].size(), CV_8UC3);
l[i] = Mat::zeros(srcImgs[0].size(), CV_8UC1); l[i] = Mat::zeros(srcImgs[0].size(), CV_8UC1);
ab[i] = Mat::zeros(srcImgs[0].size(), CV_8UC2); ab[i] = Mat::zeros(srcImgs[0].size(), CV_8UC2);
......
...@@ -101,7 +101,7 @@ inline int getNearestPowerOf2(int value) ...@@ -101,7 +101,7 @@ inline int getNearestPowerOf2(int value)
template <class T> template <class T>
FastNlMeansDenoisingInvoker<T>::FastNlMeansDenoisingInvoker( FastNlMeansDenoisingInvoker<T>::FastNlMeansDenoisingInvoker(
const cv::Mat& src, cv::Mat& dst, const Mat& src, Mat& dst,
int template_window_size, int template_window_size,
int search_window_size, int search_window_size,
const float h) : const float h) :
...@@ -115,22 +115,20 @@ FastNlMeansDenoisingInvoker<T>::FastNlMeansDenoisingInvoker( ...@@ -115,22 +115,20 @@ FastNlMeansDenoisingInvoker<T>::FastNlMeansDenoisingInvoker(
search_window_size_ = search_window_half_size_ * 2 + 1; search_window_size_ = search_window_half_size_ * 2 + 1;
border_size_ = search_window_half_size_ + template_window_half_size_; border_size_ = search_window_half_size_ + template_window_half_size_;
copyMakeBorder(src_, extended_src_, copyMakeBorder(src_, extended_src_, border_size_, border_size_, border_size_, border_size_, BORDER_DEFAULT);
border_size_, border_size_, border_size_, border_size_, cv::BORDER_DEFAULT);
const int max_estimate_sum_value = search_window_size_ * search_window_size_ * 255; const int max_estimate_sum_value = search_window_size_ * search_window_size_ * 255;
fixed_point_mult_ = std::numeric_limits<int>::max() / max_estimate_sum_value; fixed_point_mult_ = std::numeric_limits<int>::max() / max_estimate_sum_value;
// 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
CV_Assert(template_window_size_ <= 46340); // sqrt(INT_MAX)
CV_Assert(template_window_size_ <= 46340 ); // sqrt(INT_MAX)
int template_window_size_sq = template_window_size_ * template_window_size_; int template_window_size_sq = template_window_size_ * template_window_size_;
almost_template_window_size_sq_bin_shift_ = getNearestPowerOf2(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; double almost_dist2actual_dist_multiplier = ((double)(1 << almost_template_window_size_sq_bin_shift_)) / template_window_size_sq;
int max_dist = 255 * 255 * sizeof(T); int max_dist = 255 * 255 * sizeof(T);
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;
...@@ -157,12 +155,14 @@ void FastNlMeansDenoisingInvoker<T>::operator() (const Range& range) const ...@@ -157,12 +155,14 @@ 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;
// sums of cols anf rows for current pixel p
Array2d<int> dist_sums(search_window_size_, search_window_size_); Array2d<int> dist_sums(search_window_size_, search_window_size_);
// for lazy calc optimization // for lazy calc optimization (sum of cols for current pixel)
Array3d<int> col_dist_sums(template_window_size_, search_window_size_, search_window_size_); Array3d<int> col_dist_sums(template_window_size_, search_window_size_, search_window_size_);
int first_col_num = -1; int first_col_num = -1;
// last elements of column sum (for each element in row)
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++)
...@@ -177,7 +177,6 @@ void FastNlMeansDenoisingInvoker<T>::operator() (const Range& range) const ...@@ -177,7 +177,6 @@ void FastNlMeansDenoisingInvoker<T>::operator() (const Range& range) const
{ {
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 else
{ {
...@@ -186,7 +185,6 @@ void FastNlMeansDenoisingInvoker<T>::operator() (const Range& range) const ...@@ -186,7 +185,6 @@ void FastNlMeansDenoisingInvoker<T>::operator() (const Range& range) const
{ {
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
{ {
...@@ -204,29 +202,23 @@ void FastNlMeansDenoisingInvoker<T>::operator() (const Range& range) const ...@@ -204,29 +202,23 @@ void FastNlMeansDenoisingInvoker<T>::operator() (const Range& range) const
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 * up_col_dist_sums_row = up_col_dist_sums.row_ptr(j, y);
int* col_dist_sums_row = col_dist_sums.row_ptr(first_col_num,y); const T * b_up_ptr = extended_src_.ptr<T>(start_by - template_window_half_size_ - 1 + y);
int* up_col_dist_sums_row = up_col_dist_sums.row_ptr(j, y); const T * b_down_ptr = extended_src_.ptr<T>(start_by + template_window_half_size_ + y);
const T* b_up_ptr = 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);
for (int x = 0; x < search_window_size; x++) for (int x = 0; x < search_window_size; x++)
{ {
// remove from current pixel sum column sum with index "first_col_num"
dist_sums_row[x] -= col_dist_sums_row[x]; dist_sums_row[x] -= col_dist_sums_row[x];
col_dist_sums_row[x] = int bx = start_bx + x;
up_col_dist_sums_row[x] + col_dist_sums_row[x] = up_col_dist_sums_row[x] + calcUpDownDist(a_up, a_down, b_up_ptr[bx], b_down_ptr[bx]);
calcUpDownDist(
a_up, a_down,
b_up_ptr[start_bx + x], b_down_ptr[start_bx + x]
);
dist_sums_row[x] += col_dist_sums_row[x]; dist_sums_row[x] += col_dist_sums_row[x];
up_col_dist_sums_row[x] = col_dist_sums_row[x]; up_col_dist_sums_row[x] = col_dist_sums_row[x];
} }
} }
} }
...@@ -235,9 +227,7 @@ void FastNlMeansDenoisingInvoker<T>::operator() (const Range& range) const ...@@ -235,9 +227,7 @@ void FastNlMeansDenoisingInvoker<T>::operator() (const Range& range) const
} }
// calc weights // calc weights
int weights_sum = 0; int estimation[3], weights_sum = 0;
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;
...@@ -247,9 +237,7 @@ void FastNlMeansDenoisingInvoker<T>::operator() (const Range& range) const ...@@ -247,9 +237,7 @@ void FastNlMeansDenoisingInvoker<T>::operator() (const Range& range) const
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;
...@@ -302,9 +290,7 @@ inline void FastNlMeansDenoisingInvoker<T>::calcDistSumsForFirstElementInRow( ...@@ -302,9 +290,7 @@ inline void FastNlMeansDenoisingInvoker<T>::calcDistSumsForFirstElementInRow(
template <class T> template <class T>
inline void FastNlMeansDenoisingInvoker<T>::calcDistSumsForElementInFirstRow( inline void FastNlMeansDenoisingInvoker<T>::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
...@@ -326,8 +312,7 @@ inline void FastNlMeansDenoisingInvoker<T>::calcDistSumsForElementInFirstRow( ...@@ -326,8 +312,7 @@ inline void FastNlMeansDenoisingInvoker<T>::calcDistSumsForElementInFirstRow(
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];
......
...@@ -70,7 +70,7 @@ template <typename T> static inline int calcDist(const Mat& m, int i1, int j1, i ...@@ -70,7 +70,7 @@ template <typename T> static inline int calcDist(const Mat& m, int i1, int j1, i
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)
......
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