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 {
isnan(T value)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
sampleMaxpixelInfo71 static inline sampleType sampleMax()
72 {
73 return std::numeric_limits<sampleType>::max();
74 }
75
sampleMinpixelInfo76 static inline sampleType sampleMin()
77 {
78 return std::numeric_limits<sampleType>::min();
79 }
80
sampleBytespixelInfo81 static inline size_t sampleBytes()
82 {
83 return sizeof(sampleType);
84 }
85
sampleBitspixelInfo86 static inline size_t sampleBits()
87 {
88 return 8*sampleBytes();
89 }
90 };
91
92 class DistAbs
93 {
94 template <typename T> struct calcDist_
95 {
fDistAbs::calcDist_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 {
fDistAbs::calcDist_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 {
fDistAbs::calcDist_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 {
fDistAbs::calcDist_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 {
fDistAbs::calcWeight_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 {
fDistAbs::calcWeight_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:
calcDist(const T a,const T b)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>
calcDist(const Mat & m,int i1,int j1,int i2,int j2)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>
calcUpDownDist(T a_up,T a_down,T b_up,T b_down)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>
calcWeight(double dist,const float * h,typename pixelInfo<WT>::sampleType fixed_point_mult)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>
maxDist()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 {
fDistSquared::calcDist_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 {
fDistSquared::calcDist_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 {
fDistSquared::calcDist_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 {
fDistSquared::calcDist_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 {
fDistSquared::calcUpDownDist_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:
fDistSquared::calcUpDownDist_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 {
fDistSquared::calcWeight_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 {
fDistSquared::calcWeight_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:
calcDist(const T a,const T b)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>
calcDist(const Mat & m,int i1,int j1,int i2,int j2)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>
calcUpDownDist(T a_up,T a_down,T b_up,T b_down)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>
calcWeight(double dist,const float * h,typename pixelInfo<WT>::sampleType fixed_point_mult)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>
maxDist()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 {
fincWithWeight_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 {
fincWithWeight_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 {
fincWithWeight_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 {
fincWithWeight_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 {
fincWithWeight_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 {
fincWithWeight_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 {
fincWithWeight_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>
incWithWeight(IT * estimation,IT * weights_sum,WT weight,T p)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 {
fdivByWeightsSum_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 {
fdivByWeightsSum_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 {
fdivByWeightsSum_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>
divByWeightsSum(IT * estimation,IT * weights_sum)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 {
fsaturateCastFromArray_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 {
fsaturateCastFromArray_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 {
fsaturateCastFromArray_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 {
fsaturateCastFromArray_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
saturateCastFromArray(IT * estimation)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