Additional refactoring preparing for 16-bit implementation

This commit is contained in:
Erik Karlsson 2015-02-12 18:45:09 +01:00
parent e178294b49
commit 8368fb9ea8
3 changed files with 83 additions and 51 deletions

View File

@ -107,7 +107,7 @@ FastNlMeansDenoisingInvoker<T, IT, UIT>::FastNlMeansDenoisingInvoker(
const float h) :
src_(src), dst_(dst)
{
CV_Assert(src.channels() == sizeof(T)); //T is Vec1b or Vec2b or Vec3b
CV_Assert(src.channels() == pixelInfo<T>::channels);
template_window_half_size_ = template_window_size / 2;
search_window_half_size_ = search_window_size / 2;
@ -117,17 +117,21 @@ FastNlMeansDenoisingInvoker<T, IT, UIT>::FastNlMeansDenoisingInvoker(
border_size_ = search_window_half_size_ + template_window_half_size_;
copyMakeBorder(src_, extended_src_, border_size_, border_size_, border_size_, border_size_, BORDER_DEFAULT);
const IT max_estimate_sum_value = (IT)search_window_size_ * (IT)search_window_size_ * 255;
const IT max_estimate_sum_value =
(IT)search_window_size_ * (IT)search_window_size_ * (IT)pixelInfo<T>::sampleMax();
fixed_point_mult_ = std::numeric_limits<IT>::max() / max_estimate_sum_value;
// precalc weight for every possible l2 dist between blocks
// additional optimization of precalced weights to replace division(averaging) by binary shift
// squared distances are truncated to 16 bits to get a reasonable table size
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);
almost_template_window_size_sq_bin_shift_ =
getNearestPowerOf2(template_window_size_sq) + 2*pixelInfo<T>::sampleBits() - 16;
double almost_dist2actual_dist_multiplier = ((double)(1 << almost_template_window_size_sq_bin_shift_)) / template_window_size_sq;
IT max_dist = 255 * 255 * sizeof(T);
IT max_dist =
(IT)pixelInfo<T>::sampleMax() * (IT)pixelInfo<T>::sampleMax() * (IT)pixelInfo<T>::channels;
int almost_max_dist = (int)(max_dist / almost_dist2actual_dist_multiplier + 1);
almost_dist2weight_.resize(almost_max_dist);

View File

@ -44,30 +44,62 @@
using namespace cv;
template <typename T, typename IT> struct calcDist_
template <typename T> struct pixelInfo_
{
static inline IT f(const T a, const T b);
static const int channels = 1;
typedef T sampleType;
};
template <typename IT> struct calcDist_<uchar, IT>
template <typename ET, int n> struct pixelInfo_<Vec<ET, n> >
{
static inline IT f(uchar a, uchar b)
static const int channels = n;
typedef ET sampleType;
};
template <typename T> struct pixelInfo: public pixelInfo_<T>
{
using typename pixelInfo_<T>::sampleType;
static inline sampleType sampleMax()
{
return std::numeric_limits<sampleType>::max();
}
static inline sampleType sampleMin()
{
return std::numeric_limits<sampleType>::min();
}
static inline size_t sampleBytes()
{
return sizeof(sampleType);
}
static inline size_t sampleBits()
{
return 8*sampleBytes();
}
};
template <typename T, typename IT> struct calcDist_
{
static inline IT f(const T a, const T b)
{
return (IT)(a-b) * (IT)(a-b);
}
};
template <typename IT> struct calcDist_<Vec2b, IT>
template <typename ET, typename IT> struct calcDist_<Vec<ET, 2>, IT>
{
static inline IT f(const Vec2b a, const Vec2b b)
static inline IT f(const Vec<ET, 2> a, const Vec<ET, 2> b)
{
return (IT)(a[0]-b[0])*(IT)(a[0]-b[0]) + (IT)(a[1]-b[1])*(IT)(a[1]-b[1]);
}
};
template <typename IT> struct calcDist_<Vec3b, IT>
template <typename ET, typename IT> struct calcDist_<Vec<ET, 3>, IT>
{
static inline IT f(const Vec3b a, const Vec3b b)
static inline IT f(const Vec<ET, 3> a, const Vec<ET, 3> b)
{
return
(IT)(a[0]-b[0])*(IT)(a[0]-b[0]) +
@ -92,14 +124,6 @@ static inline IT calcDist(const Mat& m, int i1, int j1, int i2, int j2)
template <typename T, typename IT> struct calcUpDownDist_
{
static inline IT f(T a_up, T a_down, T b_up, T b_down)
{
return calcDist<T, IT>(a_down, b_down) - calcDist<T, IT>(a_up, b_up);
}
};
template <typename IT> struct calcUpDownDist_<uchar, IT>
{
static inline IT f(uchar a_up, uchar a_down, uchar b_up, uchar b_down)
{
IT A = a_down - b_down;
IT B = a_up - b_up;
@ -107,6 +131,17 @@ template <typename IT> struct calcUpDownDist_<uchar, IT>
}
};
template <typename ET, int n, typename IT> struct calcUpDownDist_<Vec<ET, n>, IT>
{
private:
typedef Vec<ET, n> T;
public:
static inline IT f(T a_up, T a_down, T b_up, T b_down)
{
return calcDist<T, IT>(a_down, b_down) - calcDist<T, IT>(a_up, b_up);
}
};
template <typename T, typename IT>
static inline IT calcUpDownDist(T a_up, T a_down, T b_up, T b_down)
{
@ -115,29 +150,24 @@ static inline IT calcUpDownDist(T a_up, T a_down, T b_up, T b_down)
template <typename T, typename IT> struct incWithWeight_
{
static inline void f(IT* estimation, IT weight, T p);
};
template <typename IT> struct incWithWeight_<uchar, IT>
{
static inline void f(IT* estimation, IT weight, uchar p)
static inline void f(IT* estimation, IT weight, T p)
{
estimation[0] += weight * p;
}
};
template <typename IT> struct incWithWeight_<Vec2b, IT>
template <typename ET, typename IT> struct incWithWeight_<Vec<ET, 2>, IT>
{
static inline void f(IT* estimation, IT weight, Vec2b p)
static inline void f(IT* estimation, IT weight, Vec<ET, 2> p)
{
estimation[0] += weight * p[0];
estimation[1] += weight * p[1];
}
};
template <typename IT> struct incWithWeight_<Vec3b, IT>
template <typename ET, typename IT> struct incWithWeight_<Vec<ET, 3>, IT>
{
static inline void f(IT* estimation, IT weight, Vec3b p)
static inline void f(IT* estimation, IT weight, Vec<ET, 3> p)
{
estimation[0] += weight * p[0];
estimation[1] += weight * p[1];
@ -153,36 +183,31 @@ static inline void incWithWeight(IT* estimation, IT weight, T p)
template <typename T, typename IT> struct saturateCastFromArray_
{
static inline T f(IT* estimation);
};
template <typename IT> struct saturateCastFromArray_<uchar, IT>
{
static inline uchar f(IT* estimation)
static inline T f(IT* estimation)
{
return saturate_cast<uchar>(estimation[0]);
return saturate_cast<T>(estimation[0]);
}
};
template <typename IT> struct saturateCastFromArray_<Vec2b, IT>
template <typename ET, typename IT> struct saturateCastFromArray_<Vec<ET, 2>, IT>
{
static inline Vec2b f(IT* estimation)
static inline Vec<ET, 2> f(IT* estimation)
{
Vec2b res;
res[0] = saturate_cast<uchar>(estimation[0]);
res[1] = saturate_cast<uchar>(estimation[1]);
Vec<ET, 2> res;
res[0] = saturate_cast<ET>(estimation[0]);
res[1] = saturate_cast<ET>(estimation[1]);
return res;
}
};
template <typename IT> struct saturateCastFromArray_<Vec3b, IT>
template <typename ET, typename IT> struct saturateCastFromArray_<Vec<ET, 3>, IT>
{
static inline Vec3b f(IT* estimation)
static inline Vec<ET, 3> f(IT* estimation)
{
Vec3b res;
res[0] = saturate_cast<uchar>(estimation[0]);
res[1] = saturate_cast<uchar>(estimation[1]);
res[2] = saturate_cast<uchar>(estimation[2]);
Vec<ET, 3> res;
res[0] = saturate_cast<ET>(estimation[0]);
res[1] = saturate_cast<ET>(estimation[1]);
res[2] = saturate_cast<ET>(estimation[2]);
return res;
}
};

View File

@ -106,7 +106,7 @@ FastNlMeansMultiDenoisingInvoker<T, IT, UIT>::FastNlMeansMultiDenoisingInvoker(
dst_(dst), extended_srcs_(srcImgs.size())
{
CV_Assert(srcImgs.size() > 0);
CV_Assert(srcImgs[0].channels() == sizeof(T));
CV_Assert(srcImgs[0].channels() == pixelInfo<T>::channels);
rows_ = srcImgs[0].rows;
cols_ = srcImgs[0].cols;
@ -126,20 +126,23 @@ FastNlMeansMultiDenoisingInvoker<T, IT, UIT>::FastNlMeansMultiDenoisingInvoker(
main_extended_src_ = extended_srcs_[temporal_window_half_size_];
const IT max_estimate_sum_value =
(IT)temporal_window_size_ * (IT)search_window_size_ * (IT)search_window_size_ * 255;
(IT)temporal_window_size_ * (IT)search_window_size_ * (IT)search_window_size_ * (IT)pixelInfo<T>::sampleMax();
fixed_point_mult_ = std::numeric_limits<IT>::max() / max_estimate_sum_value;
// precalc weight for every possible l2 dist between blocks
// additional optimization of precalced weights to replace division(averaging) by binary shift
// squared distances are truncated to 16 bits to get a reasonable table size
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++;
almost_template_window_size_sq_bin_shift += 2*pixelInfo<T>::sampleBits() - 16;
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;
IT max_dist = 255 * 255 * sizeof(T);
IT max_dist =
(IT)pixelInfo<T>::sampleMax() * (IT)pixelInfo<T>::sampleMax() * (IT)pixelInfo<T>::channels;
int almost_max_dist = (int) (max_dist / almost_dist2actual_dist_multiplier + 1);
almost_dist2weight.resize(almost_max_dist);