merged the trunk r8704:8716
[profile/ivi/opencv.git] / modules / gpu / src / opencv2 / gpu / device / filters.hpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////\r
2 //\r
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.\r
4 //\r
5 //  By downloading, copying, installing or using the software you agree to this license.\r
6 //  If you do not agree to this license, do not download, install,\r
7 //  copy or use the software.\r
8 //\r
9 //\r
10 //                           License Agreement\r
11 //                For Open Source Computer Vision Library\r
12 //\r
13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.\r
14 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.\r
15 // Third party copyrights are property of their respective owners.\r
16 //\r
17 // Redistribution and use in source and binary forms, with or without modification,\r
18 // are permitted provided that the following conditions are met:\r
19 //\r
20 //   * Redistribution's of source code must retain the above copyright notice,\r
21 //     this list of conditions and the following disclaimer.\r
22 //\r
23 //   * Redistribution's in binary form must reproduce the above copyright notice,\r
24 //     this list of conditions and the following disclaimer in the documentation\r
25 //     and/or other materials provided with the distribution.\r
26 //\r
27 //   * The name of the copyright holders may not be used to endorse or promote products\r
28 //     derived from this software without specific prior written permission.\r
29 //\r
30 // This software is provided by the copyright holders and contributors "as is" and\r
31 // any express or implied warranties, including, but not limited to, the implied\r
32 // warranties of merchantability and fitness for a particular purpose are disclaimed.\r
33 // In no event shall the Intel Corporation or contributors be liable for any direct,\r
34 // indirect, incidental, special, exemplary, or consequential damages\r
35 // (including, but not limited to, procurement of substitute goods or services;\r
36 // loss of use, data, or profits; or business interruption) however caused\r
37 // and on any theory of liability, whether in contract, strict liability,\r
38 // or tort (including negligence or otherwise) arising in any way out of\r
39 // the use of this software, even if advised of the possibility of such damage.\r
40 //\r
41 //M*/\r
42 \r
43 #ifndef __OPENCV_GPU_FILTERS_HPP__\r
44 #define __OPENCV_GPU_FILTERS_HPP__\r
45 \r
46 #include "saturate_cast.hpp"\r
47 #include "vec_traits.hpp"\r
48 #include "vec_math.hpp"\r
49 #include "type_traits.hpp"\r
50 \r
51 namespace cv { namespace gpu { namespace device\r
52 {\r
53     template <typename Ptr2D> struct PointFilter\r
54     {\r
55         typedef typename Ptr2D::elem_type elem_type;\r
56         typedef float index_type;\r
57 \r
58         explicit __host__ __device__ __forceinline__ PointFilter(const Ptr2D& src_, float fx = 0.f, float fy = 0.f)\r
59         : src(src_)\r
60         {\r
61             (void)fx;\r
62             (void)fy;\r
63         }\r
64 \r
65         __device__ __forceinline__ elem_type operator ()(float y, float x) const\r
66         {\r
67             return src(__float2int_rn(y), __float2int_rn(x));\r
68         }\r
69 \r
70         const Ptr2D src;\r
71     };\r
72 \r
73     template <typename Ptr2D> struct LinearFilter\r
74     {\r
75         typedef typename Ptr2D::elem_type elem_type;\r
76         typedef float index_type;\r
77 \r
78         explicit __host__ __device__ __forceinline__ LinearFilter(const Ptr2D& src_, float fx = 0.f, float fy = 0.f)\r
79         : src(src_)\r
80         {\r
81             (void)fx;\r
82             (void)fy;\r
83         }\r
84         __device__ __forceinline__ elem_type operator ()(float y, float x) const\r
85         {\r
86             typedef typename TypeVec<float, VecTraits<elem_type>::cn>::vec_type work_type;\r
87 \r
88             work_type out = VecTraits<work_type>::all(0);\r
89 \r
90             const int x1 = __float2int_rd(x);\r
91             const int y1 = __float2int_rd(y);\r
92             const int x2 = x1 + 1;\r
93             const int y2 = y1 + 1;\r
94 \r
95             elem_type src_reg = src(y1, x1);\r
96             out = out + src_reg * ((x2 - x) * (y2 - y));\r
97 \r
98             src_reg = src(y1, x2);\r
99             out = out + src_reg * ((x - x1) * (y2 - y));\r
100 \r
101             src_reg = src(y2, x1);\r
102             out = out + src_reg * ((x2 - x) * (y - y1));\r
103 \r
104             src_reg = src(y2, x2);\r
105             out = out + src_reg * ((x - x1) * (y - y1));\r
106 \r
107             return saturate_cast<elem_type>(out);\r
108         }\r
109 \r
110         const Ptr2D src;\r
111     };\r
112 \r
113     template <typename Ptr2D> struct CubicFilter\r
114     {\r
115         typedef typename Ptr2D::elem_type elem_type;\r
116         typedef float index_type;\r
117         typedef typename TypeVec<float, VecTraits<elem_type>::cn>::vec_type work_type;\r
118 \r
119         explicit __host__ __device__ __forceinline__ CubicFilter(const Ptr2D& src_, float fx = 0.f, float fy = 0.f) \r
120         : src(src_)\r
121         {\r
122             (void)fx;\r
123             (void)fy;\r
124         }\r
125 \r
126         static __device__ __forceinline__ float bicubicCoeff(float x_)\r
127         {\r
128             float x = fabsf(x_);\r
129             if (x <= 1.0f)\r
130             {\r
131                 return x * x * (1.5f * x - 2.5f) + 1.0f;\r
132             }\r
133             else if (x < 2.0f)\r
134             {\r
135                 return x * (x * (-0.5f * x + 2.5f) - 4.0f) + 2.0f;\r
136             }\r
137             else\r
138             {\r
139                 return 0.0f;\r
140             }\r
141         }\r
142 \r
143         __device__ elem_type operator ()(float y, float x) const\r
144         {\r
145             const float xmin = ::ceilf(x - 2.0f);\r
146             const float xmax = ::floorf(x + 2.0f);\r
147 \r
148             const float ymin = ::ceilf(y - 2.0f);\r
149             const float ymax = ::floorf(y + 2.0f);\r
150 \r
151             work_type sum = VecTraits<work_type>::all(0);\r
152             float wsum = 0.0f;\r
153 \r
154             for (float cy = ymin; cy <= ymax; cy += 1.0f)\r
155             {\r
156                 for (float cx = xmin; cx <= xmax; cx += 1.0f)\r
157                 {\r
158                     const float w = bicubicCoeff(x - cx) * bicubicCoeff(y - cy);\r
159                     sum = sum + w * src(__float2int_rd(cy), __float2int_rd(cx));\r
160                     wsum += w;\r
161                 }\r
162             }\r
163 \r
164             work_type res = (!wsum)? VecTraits<work_type>::all(0) : sum / wsum;\r
165 \r
166             return saturate_cast<elem_type>(res);\r
167         }\r
168 \r
169         const Ptr2D src;\r
170     };\r
171     // for integer scaling\r
172     template <typename Ptr2D> struct IntegerAreaFilter\r
173     {\r
174         typedef typename Ptr2D::elem_type elem_type;\r
175         typedef float index_type;\r
176 \r
177         explicit __host__ __device__ __forceinline__ IntegerAreaFilter(const Ptr2D& src_, float scale_x_, float scale_y_)\r
178             : src(src_), scale_x(scale_x_), scale_y(scale_y_), scale(1.f / (scale_x * scale_y)) {}\r
179 \r
180         __device__ __forceinline__ elem_type operator ()(float y, float x) const\r
181         {\r
182             float fsx1 = x * scale_x;\r
183             float fsx2 = fsx1 + scale_x;\r
184 \r
185             int sx1 = __float2int_ru(fsx1);\r
186             int sx2 = __float2int_rd(fsx2);\r
187 \r
188             float fsy1 = y * scale_y;\r
189             float fsy2 = fsy1 + scale_y;\r
190 \r
191             int sy1 = __float2int_ru(fsy1);\r
192             int sy2 = __float2int_rd(fsy2);\r
193 \r
194             typedef typename TypeVec<float, VecTraits<elem_type>::cn>::vec_type work_type;\r
195             work_type out = VecTraits<work_type>::all(0.f);\r
196 \r
197             for(int dy = sy1; dy < sy2; ++dy)\r
198                 for(int dx = sx1; dx < sx2; ++dx)\r
199                 {\r
200                     out = out + src(dy, dx) * scale;\r
201                 }\r
202 \r
203             return saturate_cast<elem_type>(out);\r
204         }\r
205 \r
206         const Ptr2D src;\r
207         float scale_x, scale_y ,scale;\r
208     };\r
209 \r
210     template <typename Ptr2D> struct AreaFilter\r
211     {\r
212         typedef typename Ptr2D::elem_type elem_type;\r
213         typedef float index_type;\r
214 \r
215         explicit __host__ __device__ __forceinline__ AreaFilter(const Ptr2D& src_, float scale_x_, float scale_y_)\r
216             : src(src_), scale_x(scale_x_), scale_y(scale_y_){}\r
217 \r
218         __device__ __forceinline__ elem_type operator ()(float y, float x) const\r
219         {\r
220             float fsx1 = x * scale_x;\r
221             float fsx2 = fsx1 + scale_x;\r
222 \r
223             int sx1 = __float2int_ru(fsx1);\r
224             int sx2 = __float2int_rd(fsx2);\r
225 \r
226             float fsy1 = y * scale_y;\r
227             float fsy2 = fsy1 + scale_y;\r
228 \r
229             int sy1 = __float2int_ru(fsy1);\r
230             int sy2 = __float2int_rd(fsy2);\r
231 \r
232             float scale = 1.f / (fminf(scale_x, src.width - fsx1) * fminf(scale_y, src.height - fsy1));\r
233 \r
234             typedef typename TypeVec<float, VecTraits<elem_type>::cn>::vec_type work_type;\r
235             work_type out = VecTraits<work_type>::all(0.f);\r
236 \r
237             for (int dy = sy1; dy < sy2; ++dy)\r
238             {\r
239                 for (int dx = sx1; dx < sx2; ++dx)\r
240                     out = out + src(dy, dx) * scale;\r
241 \r
242                 if (sx1 > fsx1)\r
243                     out = out + src(dy, (sx1 -1) ) * ((sx1 - fsx1) * scale);\r
244 \r
245                 if (sx2 < fsx2)\r
246                     out = out + src(dy, sx2) * ((fsx2 -sx2) * scale);\r
247             }\r
248 \r
249             if (sy1 > fsy1)\r
250                 for (int dx = sx1; dx < sx2; ++dx)\r
251                     out = out + src( (sy1 - 1) , dx) * ((sy1 -fsy1) * scale);\r
252 \r
253             if (sy2 < fsy2)\r
254                 for (int dx = sx1; dx < sx2; ++dx)\r
255                     out = out + src(sy2, dx) * ((fsy2 -sy2) * scale);\r
256 \r
257             if ((sy1 > fsy1) &&  (sx1 > fsx1))\r
258                 out = out + src( (sy1 - 1) , (sx1 - 1)) * ((sy1 -fsy1) * (sx1 -fsx1) * scale);\r
259 \r
260             if ((sy1 > fsy1) &&  (sx2 < fsx2))\r
261                 out = out + src( (sy1 - 1) , sx2) * ((sy1 -fsy1) * (fsx2 -sx2) * scale);\r
262 \r
263             if ((sy2 < fsy2) &&  (sx2 < fsx2))\r
264                 out = out + src(sy2, sx2) * ((fsy2 -sy2) * (fsx2 -sx2) * scale);\r
265 \r
266             if ((sy2 < fsy2) &&  (sx1 > fsx1))\r
267                 out = out + src(sy2, (sx1 - 1)) * ((fsy2 -sy2) * (sx1 -fsx1) * scale);\r
268 \r
269             return saturate_cast<elem_type>(out);\r
270         }\r
271 \r
272         const Ptr2D src;\r
273         float scale_x, scale_y;\r
274         int width, haight;\r
275     };\r
276 }}} // namespace cv { namespace gpu { namespace device\r
277 \r
278 #endif // __OPENCV_GPU_FILTERS_HPP__\r