Commit 7e358388 authored by Andrey Kamaev's avatar Andrey Kamaev

Minor refactoring of NL-means denoising

parent 3c491755
...@@ -47,20 +47,20 @@ template <class T> struct Array2d { ...@@ -47,20 +47,20 @@ template <class T> struct Array2d {
int n1,n2; int n1,n2;
bool needToDeallocArray; bool needToDeallocArray;
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 // copy constructor for self allocating arrays not supported
throw new exception(); throw new exception();
} }
} }
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)
{ {
a = new T[n1*n2]; a = new T[n1*n2];
} }
...@@ -74,7 +74,7 @@ template <class T> struct Array2d { ...@@ -74,7 +74,7 @@ template <class T> struct Array2d {
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];
} }
...@@ -84,12 +84,12 @@ template <class T> struct Array3d { ...@@ -84,12 +84,12 @@ 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)
{ {
a = new T[n1*n2*n3]; a = new T[n1*n2*n3];
} }
...@@ -115,25 +115,25 @@ template <class T> struct Array4d { ...@@ -115,25 +115,25 @@ template <class T> struct Array4d {
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() {
......
...@@ -51,37 +51,37 @@ void cv::fastNlMeansDenoising( InputArray _src, OutputArray _dst, ...@@ -51,37 +51,37 @@ void cv::fastNlMeansDenoising( InputArray _src, OutputArray _dst,
Mat src = _src.getMat(); Mat src = _src.getMat();
_dst.create(src.size(), src.type()); _dst.create(src.size(), src.type());
Mat dst = _dst.getMat(); Mat dst = _dst.getMat();
switch (src.type()) { switch (src.type()) {
case CV_8U: case CV_8U:
parallel_for(cv::BlockedRange(0, src.rows), parallel_for(cv::BlockedRange(0, src.rows),
FastNlMeansDenoisingInvoker<uchar>( FastNlMeansDenoisingInvoker<uchar>(
src, dst, templateWindowSize, searchWindowSize, h)); src, dst, templateWindowSize, searchWindowSize, h));
break; break;
case CV_8UC2: case CV_8UC2:
parallel_for(cv::BlockedRange(0, src.rows), parallel_for(cv::BlockedRange(0, src.rows),
FastNlMeansDenoisingInvoker<cv::Vec2b>( FastNlMeansDenoisingInvoker<cv::Vec2b>(
src, dst, templateWindowSize, searchWindowSize, h)); src, dst, templateWindowSize, searchWindowSize, h));
break; break;
case CV_8UC3: case CV_8UC3:
parallel_for(cv::BlockedRange(0, src.rows), parallel_for(cv::BlockedRange(0, src.rows),
FastNlMeansDenoisingInvoker<cv::Vec3b>( FastNlMeansDenoisingInvoker<cv::Vec3b>(
src, dst, templateWindowSize, searchWindowSize, h)); src, dst, templateWindowSize, searchWindowSize, h));
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");
} }
} }
void cv::fastNlMeansDenoisingColored( InputArray _src, OutputArray _dst, void cv::fastNlMeansDenoisingColored( InputArray _src, OutputArray _dst,
int templateWindowSize, int searchWindowSize, int templateWindowSize, int searchWindowSize,
int h, int hForColorComponents) int h, int hForColorComponents)
{ {
Mat src = _src.getMat(); Mat src = _src.getMat();
_dst.create(src.size(), src.type()); _dst.create(src.size(), src.type());
Mat dst = _dst.getMat(); Mat dst = _dst.getMat();
if (src.type() != CV_8UC3) { if (src.type() != CV_8UC3) {
CV_Error(CV_StsBadArg, "Type of input image should be CV_8UC3!"); CV_Error(CV_StsBadArg, "Type of input image should be CV_8UC3!");
return; return;
...@@ -89,13 +89,13 @@ void cv::fastNlMeansDenoisingColored( InputArray _src, OutputArray _dst, ...@@ -89,13 +89,13 @@ void cv::fastNlMeansDenoisingColored( InputArray _src, OutputArray _dst,
Mat src_lab; Mat src_lab;
cvtColor(src, src_lab, CV_LBGR2Lab); cvtColor(src, src_lab, CV_LBGR2Lab);
Mat l(src.size(), CV_8U); Mat l(src.size(), CV_8U);
Mat ab(src.size(), CV_8UC2); Mat ab(src.size(), CV_8UC2);
Mat l_ab[] = { l, ab }; Mat l_ab[] = { l, ab };
int from_to[] = { 0,0, 1,1, 2,2 }; int from_to[] = { 0,0, 1,1, 2,2 };
mixChannels(&src_lab, 1, l_ab, 2, from_to, 3); mixChannels(&src_lab, 1, l_ab, 2, from_to, 3);
fastNlMeansDenoising(l, l, templateWindowSize, searchWindowSize, h); fastNlMeansDenoising(l, l, templateWindowSize, searchWindowSize, h);
fastNlMeansDenoising(ab, ab, templateWindowSize, searchWindowSize, hForColorComponents); fastNlMeansDenoising(ab, ab, templateWindowSize, searchWindowSize, hForColorComponents);
...@@ -106,10 +106,10 @@ void cv::fastNlMeansDenoisingColored( InputArray _src, OutputArray _dst, ...@@ -106,10 +106,10 @@ void cv::fastNlMeansDenoisingColored( InputArray _src, OutputArray _dst,
cvtColor(dst_lab, dst, CV_Lab2LBGR); cvtColor(dst_lab, dst, CV_Lab2LBGR);
} }
static void fastNlMeansDenoisingMultiCheckPreconditions( static void fastNlMeansDenoisingMultiCheckPreconditions(
const std::vector<Mat>& srcImgs, const std::vector<Mat>& srcImgs,
int imgToDenoiseIndex, int temporalWindowSize, int imgToDenoiseIndex, int temporalWindowSize,
int templateWindowSize, int searchWindowSize) int templateWindowSize, int searchWindowSize)
{ {
int src_imgs_size = (int)srcImgs.size(); int src_imgs_size = (int)srcImgs.size();
if (src_imgs_size == 0) { if (src_imgs_size == 0) {
...@@ -123,10 +123,10 @@ static void fastNlMeansDenoisingMultiCheckPreconditions( ...@@ -123,10 +123,10 @@ static void fastNlMeansDenoisingMultiCheckPreconditions(
} }
int temporalWindowHalfSize = temporalWindowSize / 2; int temporalWindowHalfSize = temporalWindowSize / 2;
if (imgToDenoiseIndex - temporalWindowHalfSize < 0 || if (imgToDenoiseIndex - temporalWindowHalfSize < 0 ||
imgToDenoiseIndex + temporalWindowHalfSize >= src_imgs_size) imgToDenoiseIndex + temporalWindowHalfSize >= src_imgs_size)
{ {
CV_Error(CV_StsBadArg, CV_Error(CV_StsBadArg,
"imgToDenoiseIndex and temporalWindowSize " "imgToDenoiseIndex and temporalWindowSize "
"should be choosen corresponding srcImgs size!"); "should be choosen corresponding srcImgs size!");
} }
...@@ -138,16 +138,16 @@ static void fastNlMeansDenoisingMultiCheckPreconditions( ...@@ -138,16 +138,16 @@ static void fastNlMeansDenoisingMultiCheckPreconditions(
} }
} }
void cv::fastNlMeansDenoisingMulti( InputArrayOfArrays _srcImgs, void cv::fastNlMeansDenoisingMulti( InputArrayOfArrays _srcImgs,
int imgToDenoiseIndex, int temporalWindowSize, int imgToDenoiseIndex, int temporalWindowSize,
OutputArray _dst, OutputArray _dst,
int templateWindowSize, int searchWindowSize, int h) int templateWindowSize, int searchWindowSize, int h)
{ {
vector<Mat> srcImgs; vector<Mat> srcImgs;
_srcImgs.getMatVector(srcImgs); _srcImgs.getMatVector(srcImgs);
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());
...@@ -155,43 +155,43 @@ void cv::fastNlMeansDenoisingMulti( InputArrayOfArrays _srcImgs, ...@@ -155,43 +155,43 @@ void cv::fastNlMeansDenoisingMulti( InputArrayOfArrays _srcImgs,
switch (srcImgs[0].type()) { switch (srcImgs[0].type()) {
case CV_8U: case CV_8U:
parallel_for(cv::BlockedRange(0, srcImgs[0].rows), parallel_for(cv::BlockedRange(0, srcImgs[0].rows),
FastNlMeansMultiDenoisingInvoker<uchar>( FastNlMeansMultiDenoisingInvoker<uchar>(
srcImgs, imgToDenoiseIndex, temporalWindowSize, srcImgs, imgToDenoiseIndex, temporalWindowSize,
dst, templateWindowSize, searchWindowSize, h)); dst, templateWindowSize, searchWindowSize, h));
break; break;
case CV_8UC2: case CV_8UC2:
parallel_for(cv::BlockedRange(0, srcImgs[0].rows), parallel_for(cv::BlockedRange(0, srcImgs[0].rows),
FastNlMeansMultiDenoisingInvoker<cv::Vec2b>( FastNlMeansMultiDenoisingInvoker<cv::Vec2b>(
srcImgs, imgToDenoiseIndex, temporalWindowSize, srcImgs, imgToDenoiseIndex, temporalWindowSize,
dst, templateWindowSize, searchWindowSize, h)); dst, templateWindowSize, searchWindowSize, h));
break; break;
case CV_8UC3: case CV_8UC3:
parallel_for(cv::BlockedRange(0, srcImgs[0].rows), parallel_for(cv::BlockedRange(0, srcImgs[0].rows),
FastNlMeansMultiDenoisingInvoker<cv::Vec3b>( FastNlMeansMultiDenoisingInvoker<cv::Vec3b>(
srcImgs, imgToDenoiseIndex, temporalWindowSize, srcImgs, imgToDenoiseIndex, temporalWindowSize,
dst, templateWindowSize, searchWindowSize, h)); dst, templateWindowSize, searchWindowSize, h));
break; break;
default: default:
CV_Error(CV_StsBadArg, CV_Error(CV_StsBadArg,
"Unsupported matrix format! Only uchar, Vec2b, Vec3b are supported"); "Unsupported matrix format! Only uchar, Vec2b, Vec3b are supported");
} }
} }
void cv::fastNlMeansDenoisingColoredMulti( InputArrayOfArrays _srcImgs, void cv::fastNlMeansDenoisingColoredMulti( InputArrayOfArrays _srcImgs,
int imgToDenoiseIndex, int temporalWindowSize, int imgToDenoiseIndex, int temporalWindowSize,
OutputArray _dst, OutputArray _dst,
int templateWindowSize, int searchWindowSize, int templateWindowSize, int searchWindowSize,
int h, int hForColorComponents) int h, int hForColorComponents)
{ {
vector<Mat> srcImgs; vector<Mat> srcImgs;
_srcImgs.getMatVector(srcImgs); _srcImgs.getMatVector(srcImgs);
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();
...@@ -207,26 +207,26 @@ void cv::fastNlMeansDenoisingColoredMulti( InputArrayOfArrays _srcImgs, ...@@ -207,26 +207,26 @@ void cv::fastNlMeansDenoisingColoredMulti( InputArrayOfArrays _srcImgs,
// TODO convert only required images // TODO convert only required images
vector<Mat> src_lab(src_imgs_size); vector<Mat> src_lab(src_imgs_size);
vector<Mat> l(src_imgs_size); vector<Mat> l(src_imgs_size);
vector<Mat> ab(src_imgs_size); 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);
cvtColor(srcImgs[i], src_lab[i], CV_LBGR2Lab); cvtColor(srcImgs[i], src_lab[i], CV_LBGR2Lab);
Mat l_ab[] = { l[i], ab[i] }; Mat l_ab[] = { l[i], ab[i] };
mixChannels(&src_lab[i], 1, l_ab, 2, from_to, 3); mixChannels(&src_lab[i], 1, l_ab, 2, from_to, 3);
} }
Mat dst_l; Mat dst_l;
Mat dst_ab; Mat dst_ab;
fastNlMeansDenoisingMulti( fastNlMeansDenoisingMulti(
l, imgToDenoiseIndex, temporalWindowSize, l, imgToDenoiseIndex, temporalWindowSize,
dst_l, templateWindowSize, searchWindowSize, h); dst_l, templateWindowSize, searchWindowSize, h);
fastNlMeansDenoisingMulti( fastNlMeansDenoisingMulti(
ab, imgToDenoiseIndex, temporalWindowSize, ab, imgToDenoiseIndex, temporalWindowSize,
dst_ab, templateWindowSize, searchWindowSize, hForColorComponents); dst_ab, templateWindowSize, searchWindowSize, hForColorComponents);
Mat l_ab_denoised[] = { dst_l, dst_ab }; Mat l_ab_denoised[] = { dst_l, dst_ab };
......
...@@ -56,17 +56,15 @@ using namespace cv; ...@@ -56,17 +56,15 @@ using namespace cv;
template <typename T> template <typename T>
struct FastNlMeansDenoisingInvoker { struct FastNlMeansDenoisingInvoker {
public: public:
FastNlMeansDenoisingInvoker(const Mat& src, Mat& dst, FastNlMeansDenoisingInvoker(const Mat& src, Mat& dst,
int template_window_size, int search_window_size, const double h); int template_window_size, int search_window_size, const double h);
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,41 +78,48 @@ struct FastNlMeansDenoisingInvoker { ...@@ -80,41 +78,48 @@ 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,
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 j,
int first_col_num, 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;
}; };
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,
cv::Mat& dst, cv::Mat& dst,
int template_window_size, int template_window_size,
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;
template_window_size_ = template_window_half_size_ * 2 + 1; template_window_size_ = template_window_half_size_ * 2 + 1;
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_, cv::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;
...@@ -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
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 = 0; almost_template_window_size_sq_bin_shift_ = getNearestPowerOf2(template_window_size_sq);
while (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;
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;
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
...@@ -160,10 +161,10 @@ void FastNlMeansDenoisingInvoker<T>::operator() (const BlockedRange& range) cons ...@@ -160,10 +161,10 @@ void FastNlMeansDenoisingInvoker<T>::operator() (const BlockedRange& range) cons
int row_to = range.end() - 1; int row_to = range.end() - 1;
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
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;
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_);
...@@ -179,17 +180,17 @@ void FastNlMeansDenoisingInvoker<T>::operator() (const BlockedRange& range) cons ...@@ -179,17 +180,17 @@ void FastNlMeansDenoisingInvoker<T>::operator() (const BlockedRange& range) cons
} else { // calc cur dist_sums using previous dist_sums } else { // calc cur dist_sums using previous dist_sums
if (i == row_from) { 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 = int start_bx =
border_size_ + j - search_window_half_size_ + template_window_half_size_; 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);
...@@ -200,64 +201,64 @@ void FastNlMeansDenoisingInvoker<T>::operator() (const BlockedRange& range) cons ...@@ -200,64 +201,64 @@ void FastNlMeansDenoisingInvoker<T>::operator() (const BlockedRange& range) cons
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 = const T* b_down_ptr =
extended_src_.ptr<T>(start_by + template_window_half_size_ + y); 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++) {
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] =
up_col_dist_sums_row[x] + up_col_dist_sums_row[x] +
calcUpDownDist( calcUpDownDist(
a_up, a_down, a_up, a_down,
b_up_ptr[start_bx + x], b_down_ptr[start_bx + x] 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];
} }
} }
} }
first_col_num = (first_col_num + 1) % template_window_size_; first_col_num = (first_col_num + 1) % template_window_size_;
} }
// calc weights // calc weights
int weights_sum = 0; int weights_sum = 0;
int estimation[3]; int estimation[3];
for (int channel_num = 0; channel_num < src_.channels(); channel_num++) { for (int channel_num = 0; channel_num < src_.channels(); 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_;
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];
incWithWeight(estimation, weight, p); incWithWeight(estimation, weight, p);
} }
} }
if (weights_sum > 0) { if (weights_sum > 0) {
for (int channel_num = 0; channel_num < src_.channels(); channel_num++) { for (int channel_num = 0; channel_num < src_.channels(); channel_num++) {
estimation[channel_num] = estimation[channel_num] =
cvRound(((double)estimation[channel_num]) / weights_sum); cvRound(((double)estimation[channel_num]) / weights_sum);
} }
...@@ -272,9 +273,9 @@ void FastNlMeansDenoisingInvoker<T>::operator() (const BlockedRange& range) cons ...@@ -272,9 +273,9 @@ void FastNlMeansDenoisingInvoker<T>::operator() (const BlockedRange& range) cons
template <class T> template <class T>
inline void FastNlMeansDenoisingInvoker<T>::calcDistSumsForFirstElementInRow( inline void FastNlMeansDenoisingInvoker<T>::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
{ {
int j = 0; int j = 0;
...@@ -291,7 +292,7 @@ inline void FastNlMeansDenoisingInvoker<T>::calcDistSumsForFirstElementInRow( ...@@ -291,7 +292,7 @@ inline void FastNlMeansDenoisingInvoker<T>::calcDistSumsForFirstElementInRow(
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);
...@@ -310,29 +311,29 @@ inline void FastNlMeansDenoisingInvoker<T>::calcDistSumsForElementInFirstRow( ...@@ -310,29 +311,29 @@ inline void FastNlMeansDenoisingInvoker<T>::calcDistSumsForElementInFirstRow(
int i, int i,
int j, int j,
int first_col_num, 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
{ {
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 = border_size_ + i - search_window_half_size_; int start_by = 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_;
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];
......
...@@ -65,7 +65,7 @@ template <> inline int calcDist(const Vec3b a, const Vec3b b) { ...@@ -65,7 +65,7 @@ template <> inline int calcDist(const Vec3b a, const Vec3b b) {
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);
} }
...@@ -108,7 +108,7 @@ template <> inline Vec2b saturateCastFromArray(int* estimation) { ...@@ -108,7 +108,7 @@ template <> inline Vec2b saturateCastFromArray(int* estimation) {
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]);
......
...@@ -56,16 +56,16 @@ using namespace cv; ...@@ -56,16 +56,16 @@ using namespace cv;
template <typename T> template <typename T>
struct FastNlMeansMultiDenoisingInvoker { struct FastNlMeansMultiDenoisingInvoker {
public: public:
FastNlMeansMultiDenoisingInvoker( FastNlMeansMultiDenoisingInvoker(
const std::vector<Mat>& srcImgs, int imgToDenoiseIndex, int temporalWindowSize, const std::vector<Mat>& srcImgs, int imgToDenoiseIndex, int temporalWindowSize,
Mat& dst, int template_window_size, int search_window_size, const double h); Mat& dst, int template_window_size, int search_window_size, const double h);
void operator() (const BlockedRange& range) const; void operator() (const BlockedRange& range) const;
void operator= (const FastNlMeansMultiDenoisingInvoker&) { void operator= (const FastNlMeansMultiDenoisingInvoker&) {
CV_Error(CV_StsNotImplemented, "Assigment operator is not implemented"); CV_Error(CV_StsNotImplemented, "Assigment operator is not implemented");
} }
private: private:
int rows_; int rows_;
...@@ -91,28 +91,28 @@ struct FastNlMeansMultiDenoisingInvoker { ...@@ -91,28 +91,28 @@ struct FastNlMeansMultiDenoisingInvoker {
vector<int> almost_dist2weight; vector<int> almost_dist2weight;
void calcDistSumsForFirstElementInRow( void calcDistSumsForFirstElementInRow(
int i, int i,
Array3d<int>& dist_sums, Array3d<int>& dist_sums,
Array4d<int>& col_dist_sums, Array4d<int>& col_dist_sums,
Array4d<int>& up_col_dist_sums) const; Array4d<int>& up_col_dist_sums) const;
void calcDistSumsForElementInFirstRow( void calcDistSumsForElementInFirstRow(
int i, int i,
int j, int j,
int first_col_num, int first_col_num,
Array3d<int>& dist_sums, Array3d<int>& dist_sums,
Array4d<int>& col_dist_sums, Array4d<int>& col_dist_sums,
Array4d<int>& up_col_dist_sums) const; Array4d<int>& up_col_dist_sums) const;
}; };
template <class T> template <class T>
FastNlMeansMultiDenoisingInvoker<T>::FastNlMeansMultiDenoisingInvoker( FastNlMeansMultiDenoisingInvoker<T>::FastNlMeansMultiDenoisingInvoker(
const vector<Mat>& srcImgs, const vector<Mat>& srcImgs,
int imgToDenoiseIndex, int imgToDenoiseIndex,
int temporalWindowSize, int temporalWindowSize,
cv::Mat& dst, cv::Mat& dst,
int template_window_size, int template_window_size,
int search_window_size, int search_window_size,
const double h) : dst_(dst), extended_srcs_(srcImgs.size()) const double h) : dst_(dst), extended_srcs_(srcImgs.size())
{ {
CV_Assert(srcImgs.size() > 0); CV_Assert(srcImgs.size() > 0);
...@@ -131,14 +131,14 @@ FastNlMeansMultiDenoisingInvoker<T>::FastNlMeansMultiDenoisingInvoker( ...@@ -131,14 +131,14 @@ FastNlMeansMultiDenoisingInvoker<T>::FastNlMeansMultiDenoisingInvoker(
temporal_window_size_ = temporal_window_half_size_ * 2 + 1; temporal_window_size_ = temporal_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_;
for (int i = 0; i < temporal_window_size_; i++) { for (int i = 0; i < temporal_window_size_; i++) {
copyMakeBorder( copyMakeBorder(
srcImgs[imgToDenoiseIndex - temporal_window_half_size_ + i], extended_srcs_[i], srcImgs[imgToDenoiseIndex - temporal_window_half_size_ + i], extended_srcs_[i],
border_size_, border_size_, border_size_, border_size_, cv::BORDER_DEFAULT); border_size_, border_size_, border_size_, border_size_, cv::BORDER_DEFAULT);
} }
main_extended_src_ = extended_srcs_[temporal_window_half_size_]; main_extended_src_ = extended_srcs_[temporal_window_half_size_];
const int max_estimate_sum_value = const int max_estimate_sum_value =
temporal_window_size_ * search_window_size_ * search_window_size_ * 255; temporal_window_size_ * search_window_size_ * search_window_size_ * 255;
fixed_point_mult_ = numeric_limits<int>::max() / max_estimate_sum_value; fixed_point_mult_ = numeric_limits<int>::max() / max_estimate_sum_value;
...@@ -150,9 +150,9 @@ FastNlMeansMultiDenoisingInvoker<T>::FastNlMeansMultiDenoisingInvoker( ...@@ -150,9 +150,9 @@ FastNlMeansMultiDenoisingInvoker<T>::FastNlMeansMultiDenoisingInvoker(
while (1 << almost_template_window_size_sq_bin_shift < template_window_size_sq) { while (1 << almost_template_window_size_sq_bin_shift < template_window_size_sq) {
almost_template_window_size_sq_bin_shift++; almost_template_window_size_sq_bin_shift++;
} }
int almost_template_window_size_sq = 1 << 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_dist2actual_dist_multiplier =
((double) almost_template_window_size_sq) / template_window_size_sq; ((double) almost_template_window_size_sq) / template_window_size_sq;
int max_dist = 256 * 256 * channels_count_; int max_dist = 256 * 256 * channels_count_;
...@@ -183,16 +183,16 @@ void FastNlMeansMultiDenoisingInvoker<T>::operator() (const BlockedRange& range) ...@@ -183,16 +183,16 @@ void FastNlMeansMultiDenoisingInvoker<T>::operator() (const BlockedRange& range)
int row_to = range.end() - 1; int row_to = range.end() - 1;
Array3d<int> dist_sums(temporal_window_size_, search_window_size_, search_window_size_); Array3d<int> dist_sums(temporal_window_size_, search_window_size_, search_window_size_);
// for lazy calc optimization // for lazy calc optimization
Array4d<int> col_dist_sums( 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; int first_col_num = -1;
Array4d<int> up_col_dist_sums( Array4d<int> up_col_dist_sums(
cols_, temporal_window_size_, search_window_size_, search_window_size_); cols_, temporal_window_size_, 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 < cols_; j++) { for (int j = 0; j < cols_; j++) {
int search_window_y = i - search_window_half_size_; int search_window_y = i - search_window_half_size_;
...@@ -205,17 +205,17 @@ void FastNlMeansMultiDenoisingInvoker<T>::operator() (const BlockedRange& range) ...@@ -205,17 +205,17 @@ void FastNlMeansMultiDenoisingInvoker<T>::operator() (const BlockedRange& range)
} else { // calc cur dist_sums using previous dist_sums } else { // calc cur dist_sums using previous dist_sums
if (i == row_from) { 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 = int start_bx =
border_size_ + j - search_window_half_size_ + template_window_half_size_; border_size_ + j - search_window_half_size_ + template_window_half_size_;
T a_up = main_extended_src_.at<T>(ay - template_window_half_size_ - 1, ax); T a_up = main_extended_src_.at<T>(ay - template_window_half_size_ - 1, ax);
...@@ -231,41 +231,41 @@ void FastNlMeansMultiDenoisingInvoker<T>::operator() (const BlockedRange& range) ...@@ -231,41 +231,41 @@ void FastNlMeansMultiDenoisingInvoker<T>::operator() (const BlockedRange& range)
Array2d<int> cur_up_col_dist_sums = up_col_dist_sums[j][d]; Array2d<int> cur_up_col_dist_sums = up_col_dist_sums[j][d];
for (int y = 0; y < search_window_size; y++) { for (int y = 0; y < search_window_size; y++) {
int* dist_sums_row = cur_dist_sums.row_ptr(y); int* dist_sums_row = cur_dist_sums.row_ptr(y);
int* col_dist_sums_row = cur_col_dist_sums.row_ptr(y); int* col_dist_sums_row = cur_col_dist_sums.row_ptr(y);
int* up_col_dist_sums_row = cur_up_col_dist_sums.row_ptr(y); int* up_col_dist_sums_row = cur_up_col_dist_sums.row_ptr(y);
const T* b_up_ptr = const T* b_up_ptr =
cur_extended_src.ptr<T>(start_by - template_window_half_size_ - 1 + y); cur_extended_src.ptr<T>(start_by - template_window_half_size_ - 1 + y);
const T* b_down_ptr = const T* b_down_ptr =
cur_extended_src.ptr<T>(start_by + template_window_half_size_ + y); cur_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++) {
dist_sums_row[x] -= col_dist_sums_row[x]; dist_sums_row[x] -= col_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] +
calcUpDownDist( calcUpDownDist(
a_up, a_down, a_up, a_down,
b_up_ptr[start_bx + x], b_down_ptr[start_bx + x] 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];
} }
} }
} }
} }
first_col_num = (first_col_num + 1) % template_window_size_; first_col_num = (first_col_num + 1) % template_window_size_;
} }
// calc weights // calc weights
int weights_sum = 0; int weights_sum = 0;
int estimation[3]; int estimation[3];
for (int channel_num = 0; channel_num < channels_count_; channel_num++) { for (int channel_num = 0; channel_num < channels_count_; channel_num++) {
estimation[channel_num] = 0; estimation[channel_num] = 0;
} }
...@@ -277,12 +277,12 @@ void FastNlMeansMultiDenoisingInvoker<T>::operator() (const BlockedRange& range) ...@@ -277,12 +277,12 @@ void FastNlMeansMultiDenoisingInvoker<T>::operator() (const BlockedRange& range)
int* dist_sums_row = dist_sums.row_ptr(d, y); int* dist_sums_row = dist_sums.row_ptr(d, 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];
incWithWeight(estimation, weight, p); incWithWeight(estimation, weight, p);
} }
...@@ -291,7 +291,7 @@ void FastNlMeansMultiDenoisingInvoker<T>::operator() (const BlockedRange& range) ...@@ -291,7 +291,7 @@ void FastNlMeansMultiDenoisingInvoker<T>::operator() (const BlockedRange& range)
if (weights_sum > 0) { if (weights_sum > 0) {
for (int channel_num = 0; channel_num < channels_count_; channel_num++) { for (int channel_num = 0; channel_num < channels_count_; channel_num++) {
estimation[channel_num] = estimation[channel_num] =
cvRound(((double)estimation[channel_num]) / weights_sum); cvRound(((double)estimation[channel_num]) / weights_sum);
} }
...@@ -307,9 +307,9 @@ void FastNlMeansMultiDenoisingInvoker<T>::operator() (const BlockedRange& range) ...@@ -307,9 +307,9 @@ void FastNlMeansMultiDenoisingInvoker<T>::operator() (const BlockedRange& range)
template <class T> template <class T>
inline void FastNlMeansMultiDenoisingInvoker<T>::calcDistSumsForFirstElementInRow( inline void FastNlMeansMultiDenoisingInvoker<T>::calcDistSumsForFirstElementInRow(
int i, int i,
Array3d<int>& dist_sums, Array3d<int>& dist_sums,
Array4d<int>& col_dist_sums, Array4d<int>& col_dist_sums,
Array4d<int>& up_col_dist_sums) const Array4d<int>& up_col_dist_sums) const
{ {
int j = 0; int j = 0;
...@@ -328,7 +328,7 @@ inline void FastNlMeansMultiDenoisingInvoker<T>::calcDistSumsForFirstElementInRo ...@@ -328,7 +328,7 @@ inline void FastNlMeansMultiDenoisingInvoker<T>::calcDistSumsForFirstElementInRo
int* dist_sums_ptr = &dist_sums[d][y][x]; int* dist_sums_ptr = &dist_sums[d][y][x];
int* col_dist_sums_ptr = &col_dist_sums[0][d][y][x]; int* col_dist_sums_ptr = &col_dist_sums[0][d][y][x];
int col_dist_sums_step = col_dist_sums.step_size(0); int col_dist_sums_step = col_dist_sums.step_size(0);
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++) {
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++) {
int dist = calcDist<T>( int dist = calcDist<T>(
...@@ -355,16 +355,16 @@ inline void FastNlMeansMultiDenoisingInvoker<T>::calcDistSumsForElementInFirstRo ...@@ -355,16 +355,16 @@ inline void FastNlMeansMultiDenoisingInvoker<T>::calcDistSumsForElementInFirstRo
int i, int i,
int j, int j,
int first_col_num, int first_col_num,
Array3d<int>& dist_sums, Array3d<int>& dist_sums,
Array4d<int>& col_dist_sums, Array4d<int>& col_dist_sums,
Array4d<int>& up_col_dist_sums) const Array4d<int>& up_col_dist_sums) const
{ {
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 = border_size_ + i - search_window_half_size_; int start_by = 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_;
int new_last_col_num = first_col_num; int new_last_col_num = first_col_num;
for (int d = 0; d < temporal_window_size_; d++) { for (int d = 0; d < temporal_window_size_; d++) {
...@@ -372,19 +372,19 @@ inline void FastNlMeansMultiDenoisingInvoker<T>::calcDistSumsForElementInFirstRo ...@@ -372,19 +372,19 @@ inline void FastNlMeansMultiDenoisingInvoker<T>::calcDistSumsForElementInFirstRo
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[d][y][x] -= col_dist_sums[first_col_num][d][y][x]; dist_sums[d][y][x] -= col_dist_sums[first_col_num][d][y][x];
col_dist_sums[new_last_col_num][d][y][x] = 0; col_dist_sums[new_last_col_num][d][y][x] = 0;
int by = start_by + y; int by = start_by + y;
int bx = start_bx + x; int bx = start_bx + x;
int* col_dist_sums_ptr = &col_dist_sums[new_last_col_num][d][y][x]; int* col_dist_sums_ptr = &col_dist_sums[new_last_col_num][d][y][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_ptr += *col_dist_sums_ptr +=
calcDist<T>( calcDist<T>(
main_extended_src_.at<T>(ay + ty, ax), main_extended_src_.at<T>(ay + ty, ax),
cur_extended_src.at<T>(by + ty, bx) cur_extended_src.at<T>(by + ty, bx)
); );
} }
dist_sums[d][y][x] += col_dist_sums[new_last_col_num][d][y][x]; dist_sums[d][y][x] += col_dist_sums[new_last_col_num][d][y][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