Additional refactoring preparing for 16-bit implementation
authorErik Karlsson <erik.r.karlsson@gmail.com>
Thu, 12 Feb 2015 17:45:09 +0000 (18:45 +0100)
committerErik Karlsson <erik.r.karlsson@gmail.com>
Thu, 12 Feb 2015 17:45:09 +0000 (18:45 +0100)
modules/photo/src/fast_nlmeans_denoising_invoker.hpp
modules/photo/src/fast_nlmeans_denoising_invoker_commons.hpp
modules/photo/src/fast_nlmeans_multi_denoising_invoker.hpp

index 2ad0189..202e360 100644 (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);
 
index e4e0a3a..0a8713b 100644 (file)
 
 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]) +
@@ -93,17 +125,20 @@ 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);
+        IT A = a_down - b_down;
+        IT B = a_up - b_up;
+        return (A-B)*(A+B);
     }
 };
 
-template <typename IT> struct calcUpDownDist_<uchar, IT>
+template <typename ET, int n, typename IT> struct calcUpDownDist_<Vec<ET, n>, IT>
 {
-    static inline IT f(uchar a_up, uchar a_down, uchar b_up, uchar b_down)
+private:
+    typedef Vec<ET, n> T;
+public:
+    static inline IT f(T a_up, T a_down, T b_up, T b_down)
     {
-        IT A = a_down - b_down;
-        IT B = a_up - b_up;
-        return (A-B)*(A+B);
+        return calcDist<T, IT>(a_down, b_down) - calcDist<T, IT>(a_up, b_up);
     }
 };
 
@@ -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;
     }
 };
index 392733c..48276b4 100644 (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);