Path: blob/master/modules/photo/src/fast_nlmeans_denoising_invoker_commons.hpp
16347 views
/*M///////////////////////////////////////////////////////////////////////////////////////1//2// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.3//4// By downloading, copying, installing or using the software you agree to this license.5// If you do not agree to this license, do not download, install,6// copy or use the software.7//8//9// Intel License Agreement10// For Open Source Computer Vision Library11//12// Copyright (C) 2000, Intel Corporation, all rights reserved.13// Third party copyrights are property of their respective icvers.14//15// Redistribution and use in source and binary forms, with or without modification,16// are permitted provided that the following conditions are met:17//18// * Redistribution's of source code must retain the above copyright notice,19// this list of conditions and the following disclaimer.20//21// * Redistribution's in binary form must reproduce the above copyright notice,22// this list of conditions and the following disclaimer in the documentation23// and/or other materials provided with the distribution.24//25// * The name of Intel Corporation may not be used to endorse or promote products26// derived from this software without specific prior written permission.27//28// This software is provided by the copyright holders and contributors "as is" and29// any express or implied warranties, including, but not limited to, the implied30// warranties of merchantability and fitness for a particular purpose are disclaimed.31// In no event shall the Intel Corporation or contributors be liable for any direct,32// indirect, incidental, special, exemplary, or consequential damages33// (including, but not limited to, procurement of substitute goods or services;34// loss of use, data, or profits; or business interruption) however caused35// and on any theory of liability, whether in contract, strict liability,36// or tort (including negligence or otherwise) arising in any way out of37// the use of this software, even if advised of the possibility of such damage.38//39//M*/4041#ifndef __OPENCV_FAST_NLMEANS_DENOISING_INVOKER_COMMONS_HPP__42#define __OPENCV_FAST_NLMEANS_DENOISING_INVOKER_COMMONS_HPP__4344using namespace cv;4546// std::isnan is a part of C++11 and it is not supported in MSVS2010/201247#if defined _MSC_VER && _MSC_VER < 1800 /* MSVC 2013 */48#include <float.h>49namespace std {50template <typename T> bool isnan(T value) { return _isnan(value) != 0; }51}52#endif5354template <typename T> struct pixelInfo_55{56static const int channels = 1;57typedef T sampleType;58};5960template <typename ET, int n> struct pixelInfo_<Vec<ET, n> >61{62static const int channels = n;63typedef ET sampleType;64};6566template <typename T> struct pixelInfo: public pixelInfo_<T>67{68typedef typename pixelInfo_<T>::sampleType sampleType;6970static inline sampleType sampleMax()71{72return std::numeric_limits<sampleType>::max();73}7475static inline sampleType sampleMin()76{77return std::numeric_limits<sampleType>::min();78}7980static inline size_t sampleBytes()81{82return sizeof(sampleType);83}8485static inline size_t sampleBits()86{87return 8*sampleBytes();88}89};9091class DistAbs92{93template <typename T> struct calcDist_94{95static inline int f(const T a, const T b)96{97return std::abs((int)(a-b));98}99};100101template <typename ET> struct calcDist_<Vec<ET, 2> >102{103static inline int f(const Vec<ET, 2> a, const Vec<ET, 2> b)104{105return std::abs((int)(a[0]-b[0])) + std::abs((int)(a[1]-b[1]));106}107};108109template <typename ET> struct calcDist_<Vec<ET, 3> >110{111static inline int f(const Vec<ET, 3> a, const Vec<ET, 3> b)112{113return114std::abs((int)(a[0]-b[0])) +115std::abs((int)(a[1]-b[1])) +116std::abs((int)(a[2]-b[2]));117}118};119120template <typename ET> struct calcDist_<Vec<ET, 4> >121{122static inline int f(const Vec<ET, 4> a, const Vec<ET, 4> b)123{124return125std::abs((int)(a[0]-b[0])) +126std::abs((int)(a[1]-b[1])) +127std::abs((int)(a[2]-b[2])) +128std::abs((int)(a[3]-b[3]));129}130};131132template <typename T, typename WT> struct calcWeight_133{134static inline WT f(double dist, const float *h, WT fixed_point_mult)135{136double w = std::exp(-dist*dist / (h[0]*h[0] * pixelInfo<T>::channels));137if (std::isnan(w)) w = 1.0; // Handle h = 0.0138139static const double WEIGHT_THRESHOLD = 0.001;140WT weight = (WT)cvRound(fixed_point_mult * w);141if (weight < WEIGHT_THRESHOLD * fixed_point_mult) weight = 0;142143return weight;144}145};146147template <typename T, typename ET, int n> struct calcWeight_<T, Vec<ET, n> >148{149static inline Vec<ET, n> f(double dist, const float *h, ET fixed_point_mult)150{151Vec<ET, n> res;152for (int i=0; i<n; i++)153res[i] = calcWeight<T, ET>(dist, &h[i], fixed_point_mult);154return res;155}156};157158public:159template <typename T> static inline int calcDist(const T a, const T b)160{161return calcDist_<T>::f(a, b);162}163164template <typename T>165static inline int calcDist(const Mat& m, int i1, int j1, int i2, int j2)166{167const T a = m.at<T>(i1, j1);168const T b = m.at<T>(i2, j2);169return calcDist<T>(a,b);170}171172template <typename T>173static inline int calcUpDownDist(T a_up, T a_down, T b_up, T b_down)174{175return calcDist<T>(a_down, b_down) - calcDist<T>(a_up, b_up);176};177178template <typename T, typename WT>179static inline WT calcWeight(double dist, const float *h,180typename pixelInfo<WT>::sampleType fixed_point_mult)181{182return calcWeight_<T, WT>::f(dist, h, fixed_point_mult);183}184185template <typename T>186static inline int maxDist()187{188return (int)pixelInfo<T>::sampleMax() * pixelInfo<T>::channels;189}190};191192class DistSquared193{194template <typename T> struct calcDist_195{196static inline int f(const T a, const T b)197{198return (int)(a-b) * (int)(a-b);199}200};201202template <typename ET> struct calcDist_<Vec<ET, 2> >203{204static inline int f(const Vec<ET, 2> a, const Vec<ET, 2> b)205{206return (int)(a[0]-b[0])*(int)(a[0]-b[0]) + (int)(a[1]-b[1])*(int)(a[1]-b[1]);207}208};209210template <typename ET> struct calcDist_<Vec<ET, 3> >211{212static inline int f(const Vec<ET, 3> a, const Vec<ET, 3> b)213{214return215(int)(a[0]-b[0])*(int)(a[0]-b[0]) +216(int)(a[1]-b[1])*(int)(a[1]-b[1]) +217(int)(a[2]-b[2])*(int)(a[2]-b[2]);218}219};220221template <typename ET> struct calcDist_<Vec<ET, 4> >222{223static inline int f(const Vec<ET, 4> a, const Vec<ET, 4> b)224{225return226(int)(a[0]-b[0])*(int)(a[0]-b[0]) +227(int)(a[1]-b[1])*(int)(a[1]-b[1]) +228(int)(a[2]-b[2])*(int)(a[2]-b[2]) +229(int)(a[3]-b[3])*(int)(a[3]-b[3]);230}231};232233template <typename T> struct calcUpDownDist_234{235static inline int f(T a_up, T a_down, T b_up, T b_down)236{237int A = a_down - b_down;238int B = a_up - b_up;239return (A-B)*(A+B);240}241};242243template <typename ET, int n> struct calcUpDownDist_<Vec<ET, n> >244{245private:246typedef Vec<ET, n> T;247public:248static inline int f(T a_up, T a_down, T b_up, T b_down)249{250return calcDist<T>(a_down, b_down) - calcDist<T>(a_up, b_up);251}252};253254template <typename T, typename WT> struct calcWeight_255{256static inline WT f(double dist, const float *h, WT fixed_point_mult)257{258double w = std::exp(-dist / (h[0]*h[0] * pixelInfo<T>::channels));259if (std::isnan(w)) w = 1.0; // Handle h = 0.0260261static const double WEIGHT_THRESHOLD = 0.001;262WT weight = (WT)cvRound(fixed_point_mult * w);263if (weight < WEIGHT_THRESHOLD * fixed_point_mult) weight = 0;264265return weight;266}267};268269template <typename T, typename ET, int n> struct calcWeight_<T, Vec<ET, n> >270{271static inline Vec<ET, n> f(double dist, const float *h, ET fixed_point_mult)272{273Vec<ET, n> res;274for (int i=0; i<n; i++)275res[i] = calcWeight<T, ET>(dist, &h[i], fixed_point_mult);276return res;277}278};279280public:281template <typename T> static inline int calcDist(const T a, const T b)282{283return calcDist_<T>::f(a, b);284}285286template <typename T>287static inline int calcDist(const Mat& m, int i1, int j1, int i2, int j2)288{289const T a = m.at<T>(i1, j1);290const T b = m.at<T>(i2, j2);291return calcDist<T>(a,b);292}293294template <typename T>295static inline int calcUpDownDist(T a_up, T a_down, T b_up, T b_down)296{297return calcUpDownDist_<T>::f(a_up, a_down, b_up, b_down);298};299300template <typename T, typename WT>301static inline WT calcWeight(double dist, const float *h,302typename pixelInfo<WT>::sampleType fixed_point_mult)303{304return calcWeight_<T, WT>::f(dist, h, fixed_point_mult);305}306307template <typename T>308static inline int maxDist()309{310return (int)pixelInfo<T>::sampleMax() * (int)pixelInfo<T>::sampleMax() *311pixelInfo<T>::channels;312}313};314315template <typename T, typename IT, typename WT> struct incWithWeight_316{317static inline void f(IT* estimation, IT* weights_sum, WT weight, T p)318{319estimation[0] += (IT)weight * p;320weights_sum[0] += (IT)weight;321}322};323324template <typename ET, typename IT, typename WT> struct incWithWeight_<Vec<ET, 2>, IT, WT>325{326static inline void f(IT* estimation, IT* weights_sum, WT weight, Vec<ET, 2> p)327{328estimation[0] += (IT)weight * p[0];329estimation[1] += (IT)weight * p[1];330weights_sum[0] += (IT)weight;331}332};333334template <typename ET, typename IT, typename WT> struct incWithWeight_<Vec<ET, 3>, IT, WT>335{336static inline void f(IT* estimation, IT* weights_sum, WT weight, Vec<ET, 3> p)337{338estimation[0] += (IT)weight * p[0];339estimation[1] += (IT)weight * p[1];340estimation[2] += (IT)weight * p[2];341weights_sum[0] += (IT)weight;342}343};344345template <typename ET, typename IT, typename WT> struct incWithWeight_<Vec<ET, 4>, IT, WT>346{347static inline void f(IT* estimation, IT* weights_sum, WT weight, Vec<ET, 4> p)348{349estimation[0] += (IT)weight * p[0];350estimation[1] += (IT)weight * p[1];351estimation[2] += (IT)weight * p[2];352estimation[3] += (IT)weight * p[3];353weights_sum[0] += (IT)weight;354}355};356357template <typename ET, typename IT, typename EW> struct incWithWeight_<Vec<ET, 2>, IT, Vec<EW, 2> >358{359static inline void f(IT* estimation, IT* weights_sum, Vec<EW, 2> weight, Vec<ET, 2> p)360{361estimation[0] += (IT)weight[0] * p[0];362estimation[1] += (IT)weight[1] * p[1];363weights_sum[0] += (IT)weight[0];364weights_sum[1] += (IT)weight[1];365}366};367368template <typename ET, typename IT, typename EW> struct incWithWeight_<Vec<ET, 3>, IT, Vec<EW, 3> >369{370static inline void f(IT* estimation, IT* weights_sum, Vec<EW, 3> weight, Vec<ET, 3> p)371{372estimation[0] += (IT)weight[0] * p[0];373estimation[1] += (IT)weight[1] * p[1];374estimation[2] += (IT)weight[2] * p[2];375weights_sum[0] += (IT)weight[0];376weights_sum[1] += (IT)weight[1];377weights_sum[2] += (IT)weight[2];378}379};380381template <typename ET, typename IT, typename EW> struct incWithWeight_<Vec<ET, 4>, IT, Vec<EW, 4> >382{383static inline void f(IT* estimation, IT* weights_sum, Vec<EW, 4> weight, Vec<ET, 4> p)384{385estimation[0] += (IT)weight[0] * p[0];386estimation[1] += (IT)weight[1] * p[1];387estimation[2] += (IT)weight[2] * p[2];388estimation[3] += (IT)weight[3] * p[3];389weights_sum[0] += (IT)weight[0];390weights_sum[1] += (IT)weight[1];391weights_sum[2] += (IT)weight[2];392weights_sum[3] += (IT)weight[3];393}394};395396template <typename T, typename IT, typename WT>397static inline void incWithWeight(IT* estimation, IT* weights_sum, WT weight, T p)398{399incWithWeight_<T, IT, WT>::f(estimation, weights_sum, weight, p);400}401402template <typename IT, typename UIT, int nc, int nw> struct divByWeightsSum_403{404static inline void f(IT* estimation, IT* weights_sum);405};406407template <typename IT, typename UIT> struct divByWeightsSum_<IT, UIT, 1, 1>408{409static inline void f(IT* estimation, IT* weights_sum)410{411estimation[0] = (static_cast<UIT>(estimation[0]) + weights_sum[0]/2) / weights_sum[0];412}413};414415template <typename IT, typename UIT, int n> struct divByWeightsSum_<IT, UIT, n, 1>416{417static inline void f(IT* estimation, IT* weights_sum)418{419for (size_t i = 0; i < n; i++)420estimation[i] = (static_cast<UIT>(estimation[i]) + weights_sum[0]/2) / weights_sum[0];421}422};423424template <typename IT, typename UIT, int n> struct divByWeightsSum_<IT, UIT, n, n>425{426static inline void f(IT* estimation, IT* weights_sum)427{428for (size_t i = 0; i < n; i++)429estimation[i] = (static_cast<UIT>(estimation[i]) + weights_sum[i]/2) / weights_sum[i];430}431};432433template <typename IT, typename UIT, int nc, int nw>434static inline void divByWeightsSum(IT* estimation, IT* weights_sum)435{436divByWeightsSum_<IT, UIT, nc, nw>::f(estimation, weights_sum);437}438439template <typename T, typename IT> struct saturateCastFromArray_440{441static inline T f(IT* estimation)442{443return saturate_cast<T>(estimation[0]);444}445};446447template <typename ET, typename IT> struct saturateCastFromArray_<Vec<ET, 2>, IT>448{449static inline Vec<ET, 2> f(IT* estimation)450{451Vec<ET, 2> res;452res[0] = saturate_cast<ET>(estimation[0]);453res[1] = saturate_cast<ET>(estimation[1]);454return res;455}456};457458template <typename ET, typename IT> struct saturateCastFromArray_<Vec<ET, 3>, IT>459{460static inline Vec<ET, 3> f(IT* estimation)461{462Vec<ET, 3> res;463res[0] = saturate_cast<ET>(estimation[0]);464res[1] = saturate_cast<ET>(estimation[1]);465res[2] = saturate_cast<ET>(estimation[2]);466return res;467}468};469470template <typename ET, typename IT> struct saturateCastFromArray_<Vec<ET, 4>, IT>471{472static inline Vec<ET, 4> f(IT* estimation)473{474Vec<ET, 4> res;475res[0] = saturate_cast<ET>(estimation[0]);476res[1] = saturate_cast<ET>(estimation[1]);477res[2] = saturate_cast<ET>(estimation[2]);478res[3] = saturate_cast<ET>(estimation[3]);479return res;480}481};482483template <typename T, typename IT> static inline T saturateCastFromArray(IT* estimation)484{485return saturateCastFromArray_<T, IT>::f(estimation);486}487488#endif489490491