Home | History | Annotate | Download | only in src
      1 /*M///////////////////////////////////////////////////////////////////////////////////////
      2 //
      3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
      4 //
      5 //  By downloading, copying, installing or using the software you agree to this license.
      6 //  If you do not agree to this license, do not download, install,
      7 //  copy or use the software.
      8 //
      9 //
     10 //                        Intel License Agreement
     11 //                For Open Source Computer Vision Library
     12 //
     13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
     14 // Third party copyrights are property of their respective icvers.
     15 //
     16 // Redistribution and use in source and binary forms, with or without modification,
     17 // are permitted provided that the following conditions are met:
     18 //
     19 //   * Redistribution's of source code must retain the above copyright notice,
     20 //     this list of conditions and the following disclaimer.
     21 //
     22 //   * Redistribution's in binary form must reproduce the above copyright notice,
     23 //     this list of conditions and the following disclaimer in the documentation
     24 //     and/or other materials provided with the distribution.
     25 //
     26 //   * The name of Intel Corporation may not be used to endorse or promote products
     27 //     derived from this software without specific prior written permission.
     28 //
     29 // This software is provided by the copyright holders and contributors "as is" and
     30 // any express or implied warranties, including, but not limited to, the implied
     31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
     32 // In no event shall the Intel Corporation or contributors be liable for any direct,
     33 // indirect, incidental, special, exemplary, or consequential damages
     34 // (including, but not limited to, procurement of substitute goods or services;
     35 // loss of use, data, or profits; or business interruption) however caused
     36 // and on any theory of liability, whether in contract, strict liability,
     37 // or tort (including negligence or otherwise) arising in any way out of
     38 // the use of this software, even if advised of the possibility of such damage.
     39 //
     40 //M*/
     41 
     42 #ifndef __OPENCV_FAST_NLMEANS_DENOISING_INVOKER_COMMONS_HPP__
     43 #define __OPENCV_FAST_NLMEANS_DENOISING_INVOKER_COMMONS_HPP__
     44 
     45 using namespace cv;
     46 
     47 // std::isnan is a part of C++11 and it is not supported in MSVS2010/2012
     48 #if defined _MSC_VER && _MSC_VER < 1800 /* MSVC 2013 */
     49 #include <float.h>
     50 namespace std {
     51 template <typename T> bool isnan(T value) { return _isnan(value) != 0; }
     52 }
     53 #endif
     54 
     55 template <typename T> struct pixelInfo_
     56 {
     57     static const int channels = 1;
     58     typedef T sampleType;
     59 };
     60 
     61 template <typename ET, int n> struct pixelInfo_<Vec<ET, n> >
     62 {
     63     static const int channels = n;
     64     typedef ET sampleType;
     65 };
     66 
     67 template <typename T> struct pixelInfo: public pixelInfo_<T>
     68 {
     69     typedef typename pixelInfo_<T>::sampleType sampleType;
     70 
     71     static inline sampleType sampleMax()
     72     {
     73         return std::numeric_limits<sampleType>::max();
     74     }
     75 
     76     static inline sampleType sampleMin()
     77     {
     78         return std::numeric_limits<sampleType>::min();
     79     }
     80 
     81     static inline size_t sampleBytes()
     82     {
     83         return sizeof(sampleType);
     84     }
     85 
     86     static inline size_t sampleBits()
     87     {
     88         return 8*sampleBytes();
     89     }
     90 };
     91 
     92 class DistAbs
     93 {
     94     template <typename T> struct calcDist_
     95     {
     96         static inline int f(const T a, const T b)
     97         {
     98             return std::abs((int)(a-b));
     99         }
    100     };
    101 
    102     template <typename ET> struct calcDist_<Vec<ET, 2> >
    103     {
    104         static inline int f(const Vec<ET, 2> a, const Vec<ET, 2> b)
    105         {
    106             return std::abs((int)(a[0]-b[0])) + std::abs((int)(a[1]-b[1]));
    107         }
    108     };
    109 
    110     template <typename ET> struct calcDist_<Vec<ET, 3> >
    111     {
    112         static inline int f(const Vec<ET, 3> a, const Vec<ET, 3> b)
    113         {
    114             return
    115                 std::abs((int)(a[0]-b[0])) +
    116                 std::abs((int)(a[1]-b[1])) +
    117                 std::abs((int)(a[2]-b[2]));
    118         }
    119     };
    120 
    121     template <typename ET> struct calcDist_<Vec<ET, 4> >
    122     {
    123         static inline int f(const Vec<ET, 4> a, const Vec<ET, 4> b)
    124         {
    125             return
    126                 std::abs((int)(a[0]-b[0])) +
    127                 std::abs((int)(a[1]-b[1])) +
    128                 std::abs((int)(a[2]-b[2])) +
    129                 std::abs((int)(a[3]-b[3]));
    130         }
    131     };
    132 
    133     template <typename T, typename WT> struct calcWeight_
    134     {
    135         static inline WT f(double dist, const float *h, WT fixed_point_mult)
    136         {
    137             double w = std::exp(-dist*dist / (h[0]*h[0] * pixelInfo<T>::channels));
    138             if (std::isnan(w)) w = 1.0; // Handle h = 0.0
    139 
    140             static const double WEIGHT_THRESHOLD = 0.001;
    141             WT weight = (WT)cvRound(fixed_point_mult * w);
    142             if (weight < WEIGHT_THRESHOLD * fixed_point_mult) weight = 0;
    143 
    144             return weight;
    145         }
    146     };
    147 
    148     template <typename T, typename ET, int n> struct calcWeight_<T, Vec<ET, n> >
    149     {
    150         static inline Vec<ET, n> f(double dist, const float *h, ET fixed_point_mult)
    151         {
    152             Vec<ET, n> res;
    153             for (int i=0; i<n; i++)
    154                 res[i] = calcWeight<T, ET>(dist, &h[i], fixed_point_mult);
    155             return res;
    156         }
    157     };
    158 
    159 public:
    160     template <typename T> static inline int calcDist(const T a, const T b)
    161     {
    162         return calcDist_<T>::f(a, b);
    163     }
    164 
    165     template <typename T>
    166     static inline int calcDist(const Mat& m, int i1, int j1, int i2, int j2)
    167     {
    168         const T a = m.at<T>(i1, j1);
    169         const T b = m.at<T>(i2, j2);
    170         return calcDist<T>(a,b);
    171     }
    172 
    173     template <typename T>
    174     static inline int calcUpDownDist(T a_up, T a_down, T b_up, T b_down)
    175     {
    176         return calcDist<T>(a_down, b_down) - calcDist<T>(a_up, b_up);
    177     };
    178 
    179     template <typename T, typename WT>
    180     static inline WT calcWeight(double dist, const float *h,
    181                                 typename pixelInfo<WT>::sampleType fixed_point_mult)
    182     {
    183         return calcWeight_<T, WT>::f(dist, h, fixed_point_mult);
    184     }
    185 
    186     template <typename T>
    187     static inline int maxDist()
    188     {
    189         return (int)pixelInfo<T>::sampleMax() * pixelInfo<T>::channels;
    190     }
    191 };
    192 
    193 class DistSquared
    194 {
    195     template <typename T> struct calcDist_
    196     {
    197         static inline int f(const T a, const T b)
    198         {
    199             return (int)(a-b) * (int)(a-b);
    200         }
    201     };
    202 
    203     template <typename ET> struct calcDist_<Vec<ET, 2> >
    204     {
    205         static inline int f(const Vec<ET, 2> a, const Vec<ET, 2> b)
    206         {
    207             return (int)(a[0]-b[0])*(int)(a[0]-b[0]) + (int)(a[1]-b[1])*(int)(a[1]-b[1]);
    208         }
    209     };
    210 
    211     template <typename ET> struct calcDist_<Vec<ET, 3> >
    212     {
    213         static inline int f(const Vec<ET, 3> a, const Vec<ET, 3> b)
    214         {
    215             return
    216                 (int)(a[0]-b[0])*(int)(a[0]-b[0]) +
    217                 (int)(a[1]-b[1])*(int)(a[1]-b[1]) +
    218                 (int)(a[2]-b[2])*(int)(a[2]-b[2]);
    219         }
    220     };
    221 
    222     template <typename ET> struct calcDist_<Vec<ET, 4> >
    223     {
    224         static inline int f(const Vec<ET, 4> a, const Vec<ET, 4> b)
    225         {
    226             return
    227                 (int)(a[0]-b[0])*(int)(a[0]-b[0]) +
    228                 (int)(a[1]-b[1])*(int)(a[1]-b[1]) +
    229                 (int)(a[2]-b[2])*(int)(a[2]-b[2]) +
    230                 (int)(a[3]-b[3])*(int)(a[3]-b[3]);
    231         }
    232     };
    233 
    234     template <typename T> struct calcUpDownDist_
    235     {
    236         static inline int f(T a_up, T a_down, T b_up, T b_down)
    237         {
    238             int A = a_down - b_down;
    239             int B = a_up - b_up;
    240             return (A-B)*(A+B);
    241         }
    242     };
    243 
    244     template <typename ET, int n> struct calcUpDownDist_<Vec<ET, n> >
    245     {
    246     private:
    247         typedef Vec<ET, n> T;
    248     public:
    249         static inline int f(T a_up, T a_down, T b_up, T b_down)
    250         {
    251             return calcDist<T>(a_down, b_down) - calcDist<T>(a_up, b_up);
    252         }
    253     };
    254 
    255     template <typename T, typename WT> struct calcWeight_
    256     {
    257         static inline WT f(double dist, const float *h, WT fixed_point_mult)
    258         {
    259             double w = std::exp(-dist / (h[0]*h[0] * pixelInfo<T>::channels));
    260             if (std::isnan(w)) w = 1.0; // Handle h = 0.0
    261 
    262             static const double WEIGHT_THRESHOLD = 0.001;
    263             WT weight = (WT)cvRound(fixed_point_mult * w);
    264             if (weight < WEIGHT_THRESHOLD * fixed_point_mult) weight = 0;
    265 
    266             return weight;
    267         }
    268     };
    269 
    270     template <typename T, typename ET, int n> struct calcWeight_<T, Vec<ET, n> >
    271     {
    272         static inline Vec<ET, n> f(double dist, const float *h, ET fixed_point_mult)
    273         {
    274             Vec<ET, n> res;
    275             for (int i=0; i<n; i++)
    276                 res[i] = calcWeight<T, ET>(dist, &h[i], fixed_point_mult);
    277             return res;
    278         }
    279     };
    280 
    281 public:
    282     template <typename T> static inline int calcDist(const T a, const T b)
    283     {
    284         return calcDist_<T>::f(a, b);
    285     }
    286 
    287     template <typename T>
    288     static inline int calcDist(const Mat& m, int i1, int j1, int i2, int j2)
    289     {
    290         const T a = m.at<T>(i1, j1);
    291         const T b = m.at<T>(i2, j2);
    292         return calcDist<T>(a,b);
    293     }
    294 
    295     template <typename T>
    296     static inline int calcUpDownDist(T a_up, T a_down, T b_up, T b_down)
    297     {
    298         return calcUpDownDist_<T>::f(a_up, a_down, b_up, b_down);
    299     };
    300 
    301     template <typename T, typename WT>
    302     static inline WT calcWeight(double dist, const float *h,
    303                                 typename pixelInfo<WT>::sampleType fixed_point_mult)
    304     {
    305         return calcWeight_<T, WT>::f(dist, h, fixed_point_mult);
    306     }
    307 
    308     template <typename T>
    309     static inline int maxDist()
    310     {
    311         return (int)pixelInfo<T>::sampleMax() * (int)pixelInfo<T>::sampleMax() *
    312             pixelInfo<T>::channels;
    313     }
    314 };
    315 
    316 template <typename T, typename IT, typename WT> struct incWithWeight_
    317 {
    318     static inline void f(IT* estimation, IT* weights_sum, WT weight, T p)
    319     {
    320         estimation[0] += (IT)weight * p;
    321         weights_sum[0] += (IT)weight;
    322     }
    323 };
    324 
    325 template <typename ET, typename IT, typename WT> struct incWithWeight_<Vec<ET, 2>, IT, WT>
    326 {
    327     static inline void f(IT* estimation, IT* weights_sum, WT weight, Vec<ET, 2> p)
    328     {
    329         estimation[0] += (IT)weight * p[0];
    330         estimation[1] += (IT)weight * p[1];
    331         weights_sum[0] += (IT)weight;
    332     }
    333 };
    334 
    335 template <typename ET, typename IT, typename WT> struct incWithWeight_<Vec<ET, 3>, IT, WT>
    336 {
    337     static inline void f(IT* estimation, IT* weights_sum, WT weight, Vec<ET, 3> p)
    338     {
    339         estimation[0] += (IT)weight * p[0];
    340         estimation[1] += (IT)weight * p[1];
    341         estimation[2] += (IT)weight * p[2];
    342         weights_sum[0] += (IT)weight;
    343     }
    344 };
    345 
    346 template <typename ET, typename IT, typename WT> struct incWithWeight_<Vec<ET, 4>, IT, WT>
    347 {
    348     static inline void f(IT* estimation, IT* weights_sum, WT weight, Vec<ET, 4> p)
    349     {
    350         estimation[0] += (IT)weight * p[0];
    351         estimation[1] += (IT)weight * p[1];
    352         estimation[2] += (IT)weight * p[2];
    353         estimation[3] += (IT)weight * p[3];
    354         weights_sum[0] += (IT)weight;
    355     }
    356 };
    357 
    358 template <typename ET, typename IT, typename EW> struct incWithWeight_<Vec<ET, 2>, IT, Vec<EW, 2> >
    359 {
    360     static inline void f(IT* estimation, IT* weights_sum, Vec<EW, 2> weight, Vec<ET, 2> p)
    361     {
    362         estimation[0] += (IT)weight[0] * p[0];
    363         estimation[1] += (IT)weight[1] * p[1];
    364         weights_sum[0] += (IT)weight[0];
    365         weights_sum[1] += (IT)weight[1];
    366     }
    367 };
    368 
    369 template <typename ET, typename IT, typename EW> struct incWithWeight_<Vec<ET, 3>, IT, Vec<EW, 3> >
    370 {
    371     static inline void f(IT* estimation, IT* weights_sum, Vec<EW, 3> weight, Vec<ET, 3> p)
    372     {
    373         estimation[0] += (IT)weight[0] * p[0];
    374         estimation[1] += (IT)weight[1] * p[1];
    375         estimation[2] += (IT)weight[2] * p[2];
    376         weights_sum[0] += (IT)weight[0];
    377         weights_sum[1] += (IT)weight[1];
    378         weights_sum[2] += (IT)weight[2];
    379     }
    380 };
    381 
    382 template <typename ET, typename IT, typename EW> struct incWithWeight_<Vec<ET, 4>, IT, Vec<EW, 4> >
    383 {
    384     static inline void f(IT* estimation, IT* weights_sum, Vec<EW, 4> weight, Vec<ET, 4> p)
    385     {
    386         estimation[0] += (IT)weight[0] * p[0];
    387         estimation[1] += (IT)weight[1] * p[1];
    388         estimation[2] += (IT)weight[2] * p[2];
    389         estimation[3] += (IT)weight[3] * p[3];
    390         weights_sum[0] += (IT)weight[0];
    391         weights_sum[1] += (IT)weight[1];
    392         weights_sum[2] += (IT)weight[2];
    393         weights_sum[3] += (IT)weight[3];
    394     }
    395 };
    396 
    397 template <typename T, typename IT, typename WT>
    398 static inline void incWithWeight(IT* estimation, IT* weights_sum, WT weight, T p)
    399 {
    400     return incWithWeight_<T, IT, WT>::f(estimation, weights_sum, weight, p);
    401 }
    402 
    403 template <typename IT, typename UIT, int nc, int nw> struct divByWeightsSum_
    404 {
    405     static inline void f(IT* estimation, IT* weights_sum);
    406 };
    407 
    408 template <typename IT, typename UIT> struct divByWeightsSum_<IT, UIT, 1, 1>
    409 {
    410     static inline void f(IT* estimation, IT* weights_sum)
    411     {
    412         estimation[0] = (static_cast<UIT>(estimation[0]) + weights_sum[0]/2) / weights_sum[0];
    413     }
    414 };
    415 
    416 template <typename IT, typename UIT, int n> struct divByWeightsSum_<IT, UIT, n, 1>
    417 {
    418     static inline void f(IT* estimation, IT* weights_sum)
    419     {
    420         for (size_t i = 0; i < n; i++)
    421             estimation[i] = (static_cast<UIT>(estimation[i]) + weights_sum[0]/2) / weights_sum[0];
    422     }
    423 };
    424 
    425 template <typename IT, typename UIT, int n> struct divByWeightsSum_<IT, UIT, n, n>
    426 {
    427     static inline void f(IT* estimation, IT* weights_sum)
    428     {
    429         for (size_t i = 0; i < n; i++)
    430             estimation[i] = (static_cast<UIT>(estimation[i]) + weights_sum[i]/2) / weights_sum[i];
    431     }
    432 };
    433 
    434 template <typename IT, typename UIT, int nc, int nw>
    435 static inline void divByWeightsSum(IT* estimation, IT* weights_sum)
    436 {
    437     return divByWeightsSum_<IT, UIT, nc, nw>::f(estimation, weights_sum);
    438 }
    439 
    440 template <typename T, typename IT> struct saturateCastFromArray_
    441 {
    442     static inline T f(IT* estimation)
    443     {
    444         return saturate_cast<T>(estimation[0]);
    445     }
    446 };
    447 
    448 template <typename ET, typename IT> struct saturateCastFromArray_<Vec<ET, 2>, IT>
    449 {
    450     static inline Vec<ET, 2> f(IT* estimation)
    451     {
    452         Vec<ET, 2> res;
    453         res[0] = saturate_cast<ET>(estimation[0]);
    454         res[1] = saturate_cast<ET>(estimation[1]);
    455         return res;
    456     }
    457 };
    458 
    459 template <typename ET, typename IT> struct saturateCastFromArray_<Vec<ET, 3>, IT>
    460 {
    461     static inline Vec<ET, 3> f(IT* estimation)
    462     {
    463         Vec<ET, 3> res;
    464         res[0] = saturate_cast<ET>(estimation[0]);
    465         res[1] = saturate_cast<ET>(estimation[1]);
    466         res[2] = saturate_cast<ET>(estimation[2]);
    467         return res;
    468     }
    469 };
    470 
    471 template <typename ET, typename IT> struct saturateCastFromArray_<Vec<ET, 4>, IT>
    472 {
    473     static inline Vec<ET, 4> f(IT* estimation)
    474     {
    475         Vec<ET, 4> res;
    476         res[0] = saturate_cast<ET>(estimation[0]);
    477         res[1] = saturate_cast<ET>(estimation[1]);
    478         res[2] = saturate_cast<ET>(estimation[2]);
    479         res[3] = saturate_cast<ET>(estimation[3]);
    480         return res;
    481     }
    482 };
    483 
    484 template <typename T, typename IT> static inline T saturateCastFromArray(IT* estimation)
    485 {
    486     return saturateCastFromArray_<T, IT>::f(estimation);
    487 }
    488 
    489 #endif
    490