include/opencv2/gpu/device/filters.hpp
Go to the documentation of this file.
00001 /*M///////////////////////////////////////////////////////////////////////////////////////
00002 //
00003 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
00004 //
00005 //  By downloading, copying, installing or using the software you agree to this license.
00006 //  If you do not agree to this license, do not download, install,
00007 //  copy or use the software.
00008 //
00009 //
00010 //                           License Agreement
00011 //                For Open Source Computer Vision Library
00012 //
00013 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
00014 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
00015 // Third party copyrights are property of their respective owners.
00016 //
00017 // Redistribution and use in source and binary forms, with or without modification,
00018 // are permitted provided that the following conditions are met:
00019 //
00020 //   * Redistribution's of source code must retain the above copyright notice,
00021 //     this list of conditions and the following disclaimer.
00022 //
00023 //   * Redistribution's in binary form must reproduce the above copyright notice,
00024 //     this list of conditions and the following disclaimer in the documentation
00025 //     and/or other materials provided with the distribution.
00026 //
00027 //   * The name of the copyright holders may not be used to endorse or promote products
00028 //     derived from this software without specific prior written permission.
00029 //
00030 // This software is provided by the copyright holders and contributors "as is" and
00031 // any express or implied warranties, including, but not limited to, the implied
00032 // warranties of merchantability and fitness for a particular purpose are disclaimed.
00033 // In no event shall the Intel Corporation or contributors be liable for any direct,
00034 // indirect, incidental, special, exemplary, or consequential damages
00035 // (including, but not limited to, procurement of substitute goods or services;
00036 // loss of use, data, or profits; or business interruption) however caused
00037 // and on any theory of liability, whether in contract, strict liability,
00038 // or tort (including negligence or otherwise) arising in any way out of
00039 // the use of this software, even if advised of the possibility of such damage.
00040 //
00041 //M*/
00042 
00043 #ifndef __OPENCV_GPU_FILTERS_HPP__
00044 #define __OPENCV_GPU_FILTERS_HPP__
00045 
00046 #include "saturate_cast.hpp"
00047 #include "vec_traits.hpp"
00048 #include "vec_math.hpp"
00049 #include "type_traits.hpp"
00050 
00051 namespace cv { namespace gpu { namespace device
00052 {
00053     template <typename Ptr2D> struct PointFilter
00054     {
00055         typedef typename Ptr2D::elem_type elem_type;
00056         typedef float index_type;
00057 
00058         explicit __host__ __device__ __forceinline__ PointFilter(const Ptr2D& src_, float fx = 0.f, float fy = 0.f)
00059         : src(src_)
00060         {
00061             (void)fx;
00062             (void)fy;
00063         }
00064 
00065         __device__ __forceinline__ elem_type operator ()(float y, float x) const
00066         {
00067             return src(__float2int_rz(y), __float2int_rz(x));
00068         }
00069 
00070         const Ptr2D src;
00071     };
00072 
00073     template <typename Ptr2D> struct LinearFilter
00074     {
00075         typedef typename Ptr2D::elem_type elem_type;
00076         typedef float index_type;
00077 
00078         explicit __host__ __device__ __forceinline__ LinearFilter(const Ptr2D& src_, float fx = 0.f, float fy = 0.f)
00079         : src(src_)
00080         {
00081             (void)fx;
00082             (void)fy;
00083         }
00084         __device__ __forceinline__ elem_type operator ()(float y, float x) const
00085         {
00086             typedef typename TypeVec<float, VecTraits<elem_type>::cn>::vec_type work_type;
00087 
00088             work_type out = VecTraits<work_type>::all(0);
00089 
00090             const int x1 = __float2int_rd(x);
00091             const int y1 = __float2int_rd(y);
00092             const int x2 = x1 + 1;
00093             const int y2 = y1 + 1;
00094 
00095             elem_type src_reg = src(y1, x1);
00096             out = out + src_reg * ((x2 - x) * (y2 - y));
00097 
00098             src_reg = src(y1, x2);
00099             out = out + src_reg * ((x - x1) * (y2 - y));
00100 
00101             src_reg = src(y2, x1);
00102             out = out + src_reg * ((x2 - x) * (y - y1));
00103 
00104             src_reg = src(y2, x2);
00105             out = out + src_reg * ((x - x1) * (y - y1));
00106 
00107             return saturate_cast<elem_type>(out);
00108         }
00109 
00110         const Ptr2D src;
00111     };
00112 
00113     template <typename Ptr2D> struct CubicFilter
00114     {
00115         typedef typename Ptr2D::elem_type elem_type;
00116         typedef float index_type;
00117         typedef typename TypeVec<float, VecTraits<elem_type>::cn>::vec_type work_type;
00118 
00119         explicit __host__ __device__ __forceinline__ CubicFilter(const Ptr2D& src_, float fx = 0.f, float fy = 0.f)
00120         : src(src_)
00121         {
00122             (void)fx;
00123             (void)fy;
00124         }
00125 
00126         static __device__ __forceinline__ float bicubicCoeff(float x_)
00127         {
00128             float x = fabsf(x_);
00129             if (x <= 1.0f)
00130             {
00131                 return x * x * (1.5f * x - 2.5f) + 1.0f;
00132             }
00133             else if (x < 2.0f)
00134             {
00135                 return x * (x * (-0.5f * x + 2.5f) - 4.0f) + 2.0f;
00136             }
00137             else
00138             {
00139                 return 0.0f;
00140             }
00141         }
00142 
00143         __device__ elem_type operator ()(float y, float x) const
00144         {
00145             const float xmin = ::ceilf(x - 2.0f);
00146             const float xmax = ::floorf(x + 2.0f);
00147 
00148             const float ymin = ::ceilf(y - 2.0f);
00149             const float ymax = ::floorf(y + 2.0f);
00150 
00151             work_type sum = VecTraits<work_type>::all(0);
00152             float wsum = 0.0f;
00153 
00154             for (float cy = ymin; cy <= ymax; cy += 1.0f)
00155             {
00156                 for (float cx = xmin; cx <= xmax; cx += 1.0f)
00157                 {
00158                     const float w = bicubicCoeff(x - cx) * bicubicCoeff(y - cy);
00159                     sum = sum + w * src(__float2int_rd(cy), __float2int_rd(cx));
00160                     wsum += w;
00161                 }
00162             }
00163 
00164             work_type res = (!wsum)? VecTraits<work_type>::all(0) : sum / wsum;
00165 
00166             return saturate_cast<elem_type>(res);
00167         }
00168 
00169         const Ptr2D src;
00170     };
00171     // for integer scaling
00172     template <typename Ptr2D> struct IntegerAreaFilter
00173     {
00174         typedef typename Ptr2D::elem_type elem_type;
00175         typedef float index_type;
00176 
00177         explicit __host__ __device__ __forceinline__ IntegerAreaFilter(const Ptr2D& src_, float scale_x_, float scale_y_)
00178             : src(src_), scale_x(scale_x_), scale_y(scale_y_), scale(1.f / (scale_x * scale_y)) {}
00179 
00180         __device__ __forceinline__ elem_type operator ()(float y, float x) const
00181         {
00182             float fsx1 = x * scale_x;
00183             float fsx2 = fsx1 + scale_x;
00184 
00185             int sx1 = __float2int_ru(fsx1);
00186             int sx2 = __float2int_rd(fsx2);
00187 
00188             float fsy1 = y * scale_y;
00189             float fsy2 = fsy1 + scale_y;
00190 
00191             int sy1 = __float2int_ru(fsy1);
00192             int sy2 = __float2int_rd(fsy2);
00193 
00194             typedef typename TypeVec<float, VecTraits<elem_type>::cn>::vec_type work_type;
00195             work_type out = VecTraits<work_type>::all(0.f);
00196 
00197             for(int dy = sy1; dy < sy2; ++dy)
00198                 for(int dx = sx1; dx < sx2; ++dx)
00199                 {
00200                     out = out + src(dy, dx) * scale;
00201                 }
00202 
00203             return saturate_cast<elem_type>(out);
00204         }
00205 
00206         const Ptr2D src;
00207         float scale_x, scale_y ,scale;
00208     };
00209 
00210     template <typename Ptr2D> struct AreaFilter
00211     {
00212         typedef typename Ptr2D::elem_type elem_type;
00213         typedef float index_type;
00214 
00215         explicit __host__ __device__ __forceinline__ AreaFilter(const Ptr2D& src_, float scale_x_, float scale_y_)
00216             : src(src_), scale_x(scale_x_), scale_y(scale_y_){}
00217 
00218         __device__ __forceinline__ elem_type operator ()(float y, float x) const
00219         {
00220             float fsx1 = x * scale_x;
00221             float fsx2 = fsx1 + scale_x;
00222 
00223             int sx1 = __float2int_ru(fsx1);
00224             int sx2 = __float2int_rd(fsx2);
00225 
00226             float fsy1 = y * scale_y;
00227             float fsy2 = fsy1 + scale_y;
00228 
00229             int sy1 = __float2int_ru(fsy1);
00230             int sy2 = __float2int_rd(fsy2);
00231 
00232             float scale = 1.f / (fminf(scale_x, src.width - fsx1) * fminf(scale_y, src.height - fsy1));
00233 
00234             typedef typename TypeVec<float, VecTraits<elem_type>::cn>::vec_type work_type;
00235             work_type out = VecTraits<work_type>::all(0.f);
00236 
00237             for (int dy = sy1; dy < sy2; ++dy)
00238             {
00239                 for (int dx = sx1; dx < sx2; ++dx)
00240                     out = out + src(dy, dx) * scale;
00241 
00242                 if (sx1 > fsx1)
00243                     out = out + src(dy, (sx1 -1) ) * ((sx1 - fsx1) * scale);
00244 
00245                 if (sx2 < fsx2)
00246                     out = out + src(dy, sx2) * ((fsx2 -sx2) * scale);
00247             }
00248 
00249             if (sy1 > fsy1)
00250                 for (int dx = sx1; dx < sx2; ++dx)
00251                     out = out + src( (sy1 - 1) , dx) * ((sy1 -fsy1) * scale);
00252 
00253             if (sy2 < fsy2)
00254                 for (int dx = sx1; dx < sx2; ++dx)
00255                     out = out + src(sy2, dx) * ((fsy2 -sy2) * scale);
00256 
00257             if ((sy1 > fsy1) &&  (sx1 > fsx1))
00258                 out = out + src( (sy1 - 1) , (sx1 - 1)) * ((sy1 -fsy1) * (sx1 -fsx1) * scale);
00259 
00260             if ((sy1 > fsy1) &&  (sx2 < fsx2))
00261                 out = out + src( (sy1 - 1) , sx2) * ((sy1 -fsy1) * (fsx2 -sx2) * scale);
00262 
00263             if ((sy2 < fsy2) &&  (sx2 < fsx2))
00264                 out = out + src(sy2, sx2) * ((fsy2 -sy2) * (fsx2 -sx2) * scale);
00265 
00266             if ((sy2 < fsy2) &&  (sx1 > fsx1))
00267                 out = out + src(sy2, (sx1 - 1)) * ((fsy2 -sy2) * (sx1 -fsx1) * scale);
00268 
00269             return saturate_cast<elem_type>(out);
00270         }
00271 
00272         const Ptr2D src;
00273         float scale_x, scale_y;
00274         int width, haight;
00275     };
00276 }}} // namespace cv { namespace gpu { namespace device
00277 
00278 #endif // __OPENCV_GPU_FILTERS_HPP__