added Filter Engine to gpu module.
authorVladislav Vinogradov <no@email>
Wed, 6 Oct 2010 14:32:13 +0000 (14:32 +0000)
committerVladislav Vinogradov <no@email>
Wed, 6 Oct 2010 14:32:13 +0000 (14:32 +0000)
disabled gpu::sum, gpu::minMax, gpu:Canny until fix crash.

modules/gpu/include/opencv2/gpu/gpu.hpp
modules/gpu/src/arithm.cpp
modules/gpu/src/filtering_npp.cpp
modules/gpu/src/imgproc_gpu.cpp
tests/gpu/src/filters.cpp [new file with mode: 0644]
tests/gpu/src/gputest_main.cpp
tests/gpu/src/imgproc_gpu.cpp
tests/gpu/src/morf_filters.cpp [deleted file]

index d8dc5bf..e2bb5de 100644 (file)
@@ -407,10 +407,12 @@ namespace cv
 \r
         //! computes sum of array elements\r
         //! supports CV_8UC1, CV_8UC4 types\r
+        //! disabled until fix crash\r
         CV_EXPORTS Scalar sum(const GpuMat& m);\r
 \r
         //! finds global minimum and maximum array elements and returns their values\r
         //! supports only CV_8UC1 type\r
+        //! disabled until fix npp bug\r
         CV_EXPORTS void minMax(const GpuMat& src, double* minVal, double* maxVal = 0);\r
 \r
         //! transforms 8-bit unsigned integers using lookup table: dst(i)=lut(src(i))\r
@@ -451,8 +453,10 @@ namespace cv
         CV_EXPORTS void log(const GpuMat& a, GpuMat& b);\r
 \r
         //! computes magnitude (magnitude(i)) of each (x(i), y(i)) vector\r
+        //! supports only CV_32FC1 type\r
         CV_EXPORTS void magnitude(const GpuMat& x, const GpuMat& y, GpuMat& magnitude);\r
         //! computes magnitude (magnitude(i)) of complex (x(i).re, x(i).im) vector\r
+        //! supports only CV_32FC2 type\r
         CV_EXPORTS void magnitude(const GpuMat& x, GpuMat& magnitude);\r
 \r
         ////////////////////////////// Image processing //////////////////////////////\r
@@ -517,34 +521,169 @@ namespace cv
         //! supports only CV_32FC1 source type\r
         CV_EXPORTS void integral(GpuMat& src, GpuMat& sum, GpuMat& sqsum);\r
 \r
+        //! applies Canny edge detector and produces the edge map\r
+        //! supprots only CV_8UC1 source type\r
+        //! disabled until fix crash\r
+        CV_EXPORTS void Canny(const GpuMat& image, GpuMat& edges, double threshold1, double threshold2, int apertureSize = 3);\r
+\r
+        //////////////////////////////// Filter Engine ////////////////////////////////\r
+\r
+        /*!\r
+         The Base Class for 1D or Row-wise Filters\r
+         \r
+         This is the base class for linear or non-linear filters that process 1D data.\r
+         In particular, such filters are used for the "horizontal" filtering parts in separable filters.\r
+         */\r
+        class CV_EXPORTS BaseRowFilter_GPU\r
+        {\r
+        public:\r
+            BaseRowFilter_GPU(int ksize_, int anchor_) : ksize(ksize_), anchor(anchor_) {}\r
+            virtual ~BaseRowFilter_GPU() {}\r
+            virtual void operator()(const GpuMat& src, GpuMat& dst) = 0;\r
+            int ksize, anchor;\r
+        };\r
+\r
+        /*!\r
+         The Base Class for Column-wise Filters\r
+         \r
+         This is the base class for linear or non-linear filters that process columns of 2D arrays.\r
+         Such filters are used for the "vertical" filtering parts in separable filters.\r
+         */ \r
+        class CV_EXPORTS BaseColumnFilter_GPU\r
+        {\r
+        public:\r
+            BaseColumnFilter_GPU(int ksize_, int anchor_) : ksize(ksize_), anchor(anchor_) {}\r
+            virtual ~BaseColumnFilter_GPU() {}\r
+            virtual void operator()(const GpuMat& src, GpuMat& dst) = 0;\r
+            int ksize, anchor;\r
+        };\r
+\r
+        /*!\r
+         The Base Class for Non-Separable 2D Filters.\r
+         \r
+         This is the base class for linear or non-linear 2D filters.\r
+         */ \r
+        class CV_EXPORTS BaseFilter_GPU\r
+        {\r
+        public:\r
+            BaseFilter_GPU(const Size& ksize_, const Point& anchor_) : ksize(ksize_), anchor(anchor_) {}\r
+            virtual ~BaseFilter_GPU() {}\r
+            virtual void operator()(const GpuMat& src, GpuMat& dst) = 0;\r
+            Size ksize;\r
+            Point anchor;\r
+        };\r
+\r
+        /*!\r
+         The Base Class for Filter Engine.\r
+         \r
+         The class can be used to apply an arbitrary filtering operation to an image.\r
+         It contains all the necessary intermediate buffers.\r
+        */\r
+        class CV_EXPORTS FilterEngine_GPU\r
+        {\r
+        public:\r
+            virtual ~FilterEngine_GPU() {}\r
+\r
+            virtual void apply(const GpuMat& src, GpuMat& dst, Rect roi = Rect(0,0,-1,-1)) = 0;\r
+        };\r
+\r
+        //! returns the non-separable filter engine with the specified filter\r
+        CV_EXPORTS Ptr<FilterEngine_GPU> createFilter2D_GPU(const Ptr<BaseFilter_GPU> filter2D);\r
+\r
+        //! returns the separable filter engine with the specified filters\r
+        CV_EXPORTS Ptr<FilterEngine_GPU> createSeparableFilter_GPU(const Ptr<BaseRowFilter_GPU>& rowFilter, \r
+            const Ptr<BaseColumnFilter_GPU>& columnFilter);\r
+\r
+        //! returns horizontal 1D box filter\r
+        //! supports only CV_8UC1 source type and CV_32FC1 sum type\r
+        CV_EXPORTS Ptr<BaseRowFilter_GPU> getRowSumFilter_GPU(int srcType, int sumType, int ksize, int anchor = -1);\r
+\r
+        //! returns vertical 1D box filter\r
+        //! supports only CV_8UC1 sum type and CV_32FC1 dst type\r
+        CV_EXPORTS Ptr<BaseColumnFilter_GPU> getColumnSumFilter_GPU(int sumType, int dstType, int ksize, int anchor = -1);\r
+\r
+        //! returns 2D box filter\r
+        //! supports CV_8UC1 and CV_8UC4 source type, dst type must be the same as source type\r
+        CV_EXPORTS Ptr<BaseFilter_GPU> getBoxFilter_GPU(int srcType, int dstType, const Size& ksize, Point anchor = Point(-1, -1));\r
+\r
+        //! returns box filter engine\r
+        CV_EXPORTS Ptr<FilterEngine_GPU> createBoxFilter_GPU(int srcType, int dstType, const Size& ksize, \r
+            const Point& anchor = Point(-1,-1));\r
+\r
+        //! returns 2D morphological filter\r
+        //! only MORPH_ERODE and MORPH_DILATE are supported\r
+        //! supports CV_8UC1 and CV_8UC4 types\r
+        //! kernel must have CV_8UC1 type, one rows and cols == ksize.width * ksize.height\r
+        CV_EXPORTS Ptr<BaseFilter_GPU> getMorphologyFilter_GPU(int op, int type, const GpuMat& kernel, const Size& ksize, \r
+            Point anchor=Point(-1,-1));\r
+\r
+        //! returns morphological filter engine. Only MORPH_ERODE and MORPH_DILATE are supported.\r
+        CV_EXPORTS Ptr<FilterEngine_GPU> createMorphologyFilter_GPU(int op, int type, const Mat& kernel, \r
+            const Point& anchor = Point(-1,-1), int iterations = 1);\r
+\r
+        //! returns 2D filter with the specified kernel\r
+        //! supports CV_8UC1 and CV_8UC4 types\r
+        //! kernel must have CV_8UC1 type, one rows and cols == ksize.width * ksize.height\r
+        CV_EXPORTS Ptr<BaseFilter_GPU> getLinearFilter_GPU(int srcType, int dstType, const GpuMat& kernel, const Size& ksize, \r
+            Point anchor = Point(-1, -1), int nDivisor = 1);\r
+\r
+        //! returns the non-separable linear filter engine\r
+        CV_EXPORTS Ptr<FilterEngine_GPU> createLinearFilter_GPU(int srcType, int dstType, const Mat& kernel, \r
+            const Point& anchor = Point(-1,-1));\r
+\r
+        //! returns the primitive row filter with the specified kernel\r
+        CV_EXPORTS Ptr<BaseRowFilter_GPU> getLinearRowFilter_GPU(int srcType, int bufType, const GpuMat& rowKernel, \r
+            int anchor = -1, int nDivisor = 1);\r
+\r
+        //! returns the primitive column filter with the specified kernel\r
+        CV_EXPORTS Ptr<BaseColumnFilter_GPU> getLinearColumnFilter_GPU(int bufType, int dstType, const GpuMat& columnKernel, \r
+            int anchor = -1, int nDivisor = 1);\r
+\r
+        //! returns the separable linear filter engine\r
+        CV_EXPORTS Ptr<FilterEngine_GPU> createSeparableLinearFilter_GPU(int srcType, int dstType, const Mat& rowKernel, \r
+            const Mat& columnKernel, const Point& anchor = Point(-1,-1));\r
+\r
+        //! returns filter engine for the generalized Sobel operator\r
+        CV_EXPORTS Ptr<FilterEngine_GPU> createDerivFilter_GPU(int srcType, int dstType, int dx, int dy, int ksize);\r
+\r
+        //! returns the Gaussian filter engine\r
+        CV_EXPORTS Ptr<FilterEngine_GPU> createGaussianFilter_GPU(int type, Size ksize, double sigma1, double sigma2 = 0);\r
+\r
         //! smooths the image using the normalized box filter\r
-        //! supports CV_8UC1, CV_8UC4 types and kernel size 3, 5, 7\r
-        CV_EXPORTS void boxFilter(const GpuMat& src, GpuMat& dst, Size ksize, Point anchor = Point(-1,-1));\r
+        //! supports CV_8UC1, CV_8UC4 types\r
+        CV_EXPORTS void boxFilter(const GpuMat& src, GpuMat& dst, int ddepth, Size ksize, Point anchor = Point(-1,-1));\r
 \r
         //! a synonym for normalized box filter\r
-        static inline void blur(const GpuMat& src, GpuMat& dst, Size ksize, Point anchor = Point(-1,-1)) { boxFilter(src, dst, ksize, anchor); }\r
-\r
+        static inline void blur(const GpuMat& src, GpuMat& dst, Size ksize, Point anchor = Point(-1,-1)) { boxFilter(src, dst, -1, ksize, anchor); }\r
+        \r
         //! erodes the image (applies the local minimum operator)\r
-        CV_EXPORTS void erode( const GpuMat& src, GpuMat& dst, const Mat& kernel, Point anchor, int iterations);\r
+        CV_EXPORTS void erode( const GpuMat& src, GpuMat& dst, const Mat& kernel, Point anchor = Point(-1, -1), int iterations = 1);\r
 \r
         //! dilates the image (applies the local maximum operator)\r
-        CV_EXPORTS void dilate( const GpuMat& src, GpuMat& dst, const Mat& kernel, Point anchor, int iterations);\r
+        CV_EXPORTS void dilate( const GpuMat& src, GpuMat& dst, const Mat& kernel, Point anchor = Point(-1, -1), int iterations = 1);\r
 \r
         //! applies an advanced morphological operation to the image\r
-        CV_EXPORTS void morphologyEx( const GpuMat& src, GpuMat& dst, int op, const Mat& kernel, Point anchor, int iterations);\r
+        CV_EXPORTS void morphologyEx( const GpuMat& src, GpuMat& dst, int op, const Mat& kernel, Point anchor = Point(-1, -1), int iterations = 1);\r
+\r
+        //! applies non-separable 2D linear filter to the image\r
+        CV_EXPORTS void filter2D(const GpuMat& src, GpuMat& dst, int ddepth, const Mat& kernel, Point anchor=Point(-1,-1));\r
 \r
-        //! 1D mask Window Sum for 8 bit images\r
-        CV_EXPORTS void sumWindowColumn(const GpuMat& src, GpuMat& dst, int ksize, int anchor = -1);\r
-        CV_EXPORTS void sumWindowRow(const GpuMat& src, GpuMat& dst, int ksize, int anchor = -1);\r
+        //! applies separable 2D linear filter to the image\r
+        CV_EXPORTS void sepFilter2D(const GpuMat& src, GpuMat& dst, int ddepth, const Mat& kernelX, const Mat& kernelY, \r
+            Point anchor = Point(-1,-1));\r
 \r
         //! applies generalized Sobel operator to the image\r
         CV_EXPORTS void Sobel(const GpuMat& src, GpuMat& dst, int ddepth, int dx, int dy, int ksize = 3, double scale = 1);\r
 \r
+        //! applies the vertical or horizontal Scharr operator to the image\r
+        CV_EXPORTS void Scharr(const GpuMat& src, GpuMat& dst, int ddepth, int dx, int dy, double scale = 1);\r
+        \r
         //! smooths the image using Gaussian filter.\r
         CV_EXPORTS void GaussianBlur(const GpuMat& src, GpuMat& dst, Size ksize, double sigma1, double sigma2 = 0);\r
 \r
-        //! applies Canny edge detector and produces the edge map.\r
-        CV_EXPORTS void Canny(const GpuMat& image, GpuMat& edges, double threshold1, double threshold2, int apertureSize = 3);\r
+        //! applies Laplacian operator to the image\r
+        //! supports only ksize = 1 and ksize = 3\r
+        CV_EXPORTS void Laplacian(const GpuMat& src, GpuMat& dst, int ddepth, int ksize = 1, double scale = 1);\r
 \r
         //////////////////////////////// Image Labeling ////////////////////////////////\r
 \r
index 00e08a1..4104cb0 100644 (file)
@@ -387,6 +387,7 @@ void cv::gpu::flip(const GpuMat& src, GpuMat& dst, int flipCode)
 \r
 Scalar cv::gpu::sum(const GpuMat& src)\r
 {\r
+    CV_Assert(!"disabled until fix crash");\r
     CV_Assert(src.type() == CV_8UC1 || src.type() == CV_8UC4);    \r
 \r
     NppiSize sz;\r
@@ -420,6 +421,7 @@ Scalar cv::gpu::sum(const GpuMat& src)
 \r
 void cv::gpu::minMax(const GpuMat& src, double* minVal, double* maxVal) \r
 {\r
+    CV_Assert(!"disabled until fix npp bug");\r
     CV_Assert(src.type() == CV_8UC1);\r
 \r
     NppiSize sz;\r
index 1100db7..1ca51e1 100644 (file)
@@ -48,82 +48,413 @@ using namespace cv::gpu;
 \r
 #if !defined (HAVE_CUDA)\r
 \r
+Ptr<FilterEngine_GPU> cv::gpu::createFilter2D_GPU(const Ptr<BaseFilter_GPU>) { throw_nogpu(); return Ptr<FilterEngine_GPU>(0); }\r
+Ptr<FilterEngine_GPU> cv::gpu::createSeparableFilter_GPU(const Ptr<BaseRowFilter_GPU>&, const Ptr<BaseColumnFilter_GPU>&) { throw_nogpu(); return Ptr<FilterEngine_GPU>(0); }\r
+Ptr<BaseRowFilter_GPU> cv::gpu::getRowSumFilter_GPU(int, int, int, int) { throw_nogpu(); return Ptr<BaseRowFilter_GPU>(0); }\r
+Ptr<BaseColumnFilter_GPU> cv::gpu::getColumnSumFilter_GPU(int, int, int, int) { throw_nogpu(); return Ptr<BaseColumnFilter_GPU>(0); }\r
+Ptr<BaseFilter_GPU> cv::gpu::getBoxFilter_GPU(int, int, const Size&, Point) { throw_nogpu(); return Ptr<BaseFilter_GPU>(0); }\r
+Ptr<FilterEngine_GPU> cv::gpu::createBoxFilter_GPU(int, int, const Size&, const Point&) { throw_nogpu(); return Ptr<FilterEngine_GPU>(0); }\r
+Ptr<BaseFilter_GPU> cv::gpu::getMorphologyFilter_GPU(int, int, const GpuMat&, const Size&, Point) { throw_nogpu(); return Ptr<BaseFilter_GPU>(0); }\r
+Ptr<FilterEngine_GPU> cv::gpu::createMorphologyFilter_GPU(int, int, const Mat&, const Point&, int) { throw_nogpu(); return Ptr<FilterEngine_GPU>(0); }\r
+Ptr<BaseFilter_GPU> cv::gpu::getLinearFilter_GPU(int, int, const GpuMat&, const Size&, Point, int) { throw_nogpu(); return Ptr<BaseFilter_GPU>(0); }\r
+Ptr<FilterEngine_GPU> cv::gpu::createLinearFilter_GPU(int, int, const Mat&, const Point&) { throw_nogpu(); return Ptr<FilterEngine_GPU>(0); }\r
+Ptr<BaseRowFilter_GPU> cv::gpu::getLinearRowFilter_GPU(int, int, const GpuMat&, int, int) { throw_nogpu(); return Ptr<BaseRowFilter_GPU>(0); }\r
+Ptr<BaseColumnFilter_GPU> cv::gpu::getLinearColumnFilter_GPU(int, int, const GpuMat&, int, int) { throw_nogpu(); return Ptr<BaseColumnFilter_GPU>(0); }\r
+Ptr<FilterEngine_GPU> cv::gpu::createSeparableLinearFilter_GPU(int, int, const Mat&, const Mat&, const Point&) { throw_nogpu(); return Ptr<FilterEngine_GPU>(0); }\r
+Ptr<FilterEngine_GPU> cv::gpu::createDerivFilter_GPU(int, int, int, int, int) { throw_nogpu(); return Ptr<FilterEngine_GPU>(0); }\r
+Ptr<FilterEngine_GPU> cv::gpu::createGaussianFilter_GPU(int, Size, double, double) { throw_nogpu(); return Ptr<FilterEngine_GPU>(0); }\r
+void cv::gpu::boxFilter(const GpuMat&, GpuMat&, int, Size, Point) { throw_nogpu(); }\r
 void cv::gpu::erode( const GpuMat&, GpuMat&, const Mat&, Point, int) { throw_nogpu(); }\r
 void cv::gpu::dilate( const GpuMat&, GpuMat&, const Mat&, Point, int) { throw_nogpu(); }\r
 void cv::gpu::morphologyEx( const GpuMat&, GpuMat&, int, const Mat&, Point, int) { throw_nogpu(); }\r
-void cv::gpu::boxFilter(const GpuMat&, GpuMat&, Size, Point) { throw_nogpu(); }\r
-void cv::gpu::sumWindowColumn(const GpuMat&, GpuMat&, int, int) { throw_nogpu(); }\r
-void cv::gpu::sumWindowRow(const GpuMat&, GpuMat&, int, int) { throw_nogpu(); }\r
+void cv::gpu::filter2D(const GpuMat&, GpuMat&, int, const Mat&, Point) { throw_nogpu(); }\r
+void cv::gpu::sepFilter2D(const GpuMat&, GpuMat&, int, const Mat&, const Mat&, Point) { throw_nogpu(); }\r
 void cv::gpu::Sobel(const GpuMat&, GpuMat&, int, int, int, int, double) { throw_nogpu(); }\r
+void cv::gpu::Scharr(const GpuMat&, GpuMat&, int, int, int, double) { throw_nogpu(); }\r
 void cv::gpu::GaussianBlur(const GpuMat&, GpuMat&, Size, double, double) { throw_nogpu(); }\r
+void cv::gpu::Laplacian(const GpuMat&, GpuMat&, int, int, double) { throw_nogpu(); }\r
 \r
 #else\r
 \r
-namespace \r
+namespace\r
 {\r
-    typedef NppStatus (*npp_morf_func)(const Npp8u*, Npp32s, Npp8u*, Npp32s, NppiSize, const Npp8u*, NppiSize, NppiPoint);\r
+    inline void normalizeAnchor(int& anchor, int ksize)\r
+    {\r
+        if (anchor < 0)\r
+            anchor = ksize >> 1;\r
 \r
+        CV_Assert(0 <= anchor && anchor < ksize);\r
+    }\r
 \r
-    void morphoogy_caller(npp_morf_func func, const GpuMat& src, GpuMat& dst, const Mat& kernel, Point anchor, int iterations)\r
+    inline void normalizeAnchor(Point& anchor, const Size& ksize)\r
     {\r
-        CV_Assert(src.type() == CV_8U || src.type() == CV_8UC4);        \r
-        CV_Assert(kernel.type() == CV_8U && (kernel.cols & 1) != 0 && (kernel.rows & 1) != 0);\r
+        normalizeAnchor(anchor.x, ksize.width);\r
+        normalizeAnchor(anchor.y, ksize.height);\r
+    }\r
 \r
-        if( anchor.x == -1 )\r
-            anchor.x = kernel.cols / 2;\r
-        if( anchor.y == -1 )\r
-            anchor.y = kernel.rows / 2;\r
+    inline void normalizeROI(Rect& roi, const Size& ksize, const Size& src_size)\r
+    {\r
+        if (roi == Rect(0,0,-1,-1))\r
+            roi = Rect(ksize.width, ksize.height, src_size.width - 2 * ksize.width, src_size.height - 2 * ksize.height);\r
 \r
-        // in NPP for Cuda 3.1 only such anchor is supported.\r
-        CV_Assert(anchor.x == 0 && anchor.y == 0);\r
+        CV_Assert(roi.x >= 0 && roi.y >= 0 && roi.width <= src_size.width && roi.height <= src_size.height);\r
+    }\r
 \r
-        if (iterations == 0)\r
+    inline void normalizeKernel(const Mat& kernel, GpuMat& gpu_krnl, int type = CV_8U, int* nDivisor = 0, bool reverse = false)\r
+    {\r
+        int scale = nDivisor && (kernel.depth() == CV_32F || kernel.depth() == CV_64F) ? 256 : 1;\r
+        if (nDivisor) *nDivisor = scale;\r
+        \r
+        Mat cont_krnl = (kernel.isContinuous() ? kernel : kernel.clone()).reshape(1, 1);\r
+        Mat temp;\r
+        cont_krnl.convertTo(temp, type, scale);\r
+\r
+        if (reverse)\r
         {\r
-            src.copyTo(dst);\r
-            return;\r
+            int count = temp.cols >> 1;\r
+            for (int i = 0; i < count; ++i)\r
+            {\r
+                std::swap(temp.at<int>(0, i), temp.at<int>(0, temp.cols - 1 - i));\r
+            }\r
         }\r
 \r
-        const Mat& cont_krnl = (kernel.isContinuous() ? kernel : kernel.clone()).reshape(1, 1);\r
-        GpuMat gpu_krnl(cont_krnl);\r
-                \r
-        NppiSize sz;\r
-        sz.width = src.cols;\r
-        sz.height = src.rows;\r
+        gpu_krnl.upload(temp);\r
+    } \r
+}\r
 \r
-        NppiSize mask_sz;\r
-        mask_sz.width = kernel.cols;\r
-        mask_sz.height = kernel.rows;\r
+////////////////////////////////////////////////////////////////////////////////////////////////////\r
+// Filter2D\r
 \r
-        NppiPoint anc;\r
-        anc.x = anchor.x;\r
-        anc.y = anchor.y;\r
-        \r
-        dst.create(src.size(), src.type());\r
+namespace\r
+{\r
+    class Filter2DEngine_GPU : public FilterEngine_GPU\r
+    {\r
+    public:\r
+        Filter2DEngine_GPU(const Ptr<BaseFilter_GPU>& filter2D_) : filter2D(filter2D_) {}\r
+\r
+        virtual void apply(const GpuMat& src, GpuMat& dst, Rect roi = Rect(0,0,-1,-1))\r
+        {\r
+            Size src_size = src.size();\r
+\r
+            dst.create(src_size, src.type());\r
+\r
+            normalizeROI(roi, filter2D->ksize, src_size);\r
+\r
+            GpuMat srcROI = src(roi);\r
+            GpuMat dstROI = dst(roi);\r
+\r
+            (*filter2D)(srcROI, dstROI);\r
+        }\r
+\r
+        Ptr<BaseFilter_GPU> filter2D;\r
+    };\r
+}\r
+\r
+Ptr<FilterEngine_GPU> cv::gpu::createFilter2D_GPU(const Ptr<BaseFilter_GPU> filter2D)\r
+{\r
+    return Ptr<FilterEngine_GPU>(new Filter2DEngine_GPU(filter2D));\r
+}\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////\r
+// SeparableFilter\r
+\r
+namespace\r
+{\r
+    class SeparableFilterEngine_GPU : public FilterEngine_GPU\r
+    {\r
+    public:\r
+        SeparableFilterEngine_GPU(const Ptr<BaseRowFilter_GPU>& rowFilter_, const Ptr<BaseColumnFilter_GPU>& columnFilter_) :\r
+            rowFilter(rowFilter_), columnFilter(columnFilter_)\r
+        {\r
+            ksize = Size(rowFilter->ksize, columnFilter->ksize);\r
+        }\r
+\r
+        virtual void apply(const GpuMat& src, GpuMat& dst, Rect roi = Rect(0,0,-1,-1))\r
+        {\r
+            Size src_size = src.size();\r
+            int src_type = src.type();\r
+\r
+            dst.create(src_size, src_type);\r
+            dstBuf.create(src_size, src_type);\r
+\r
+            normalizeROI(roi, ksize, src_size);\r
+\r
+            GpuMat srcROI = src(roi);\r
+            GpuMat dstROI = dst(roi);\r
+            GpuMat dstBufROI = dstBuf(roi);\r
+\r
+            (*rowFilter)(srcROI, dstBufROI);\r
+            (*columnFilter)(dstBufROI, dstROI);\r
+        }\r
+\r
+        Ptr<BaseRowFilter_GPU> rowFilter;\r
+        Ptr<BaseColumnFilter_GPU> columnFilter;\r
+        Size ksize;\r
         GpuMat dstBuf;\r
-        if (iterations > 1)\r
-            dstBuf.create(src.size(), src.type());\r
+    };\r
+}\r
+\r
+Ptr<FilterEngine_GPU> cv::gpu::createSeparableFilter_GPU(const Ptr<BaseRowFilter_GPU>& rowFilter, \r
+    const Ptr<BaseColumnFilter_GPU>& columnFilter)\r
+{\r
+    return Ptr<FilterEngine_GPU>(new SeparableFilterEngine_GPU(rowFilter, columnFilter));\r
+}\r
 \r
-        nppSafeCall( func(src.ptr<Npp8u>(), src.step, dst.ptr<Npp8u>(), dst.step, sz, gpu_krnl.ptr<Npp8u>(), mask_sz, anc) );\r
-        for(int i = 1; i < iterations; ++i)\r
+////////////////////////////////////////////////////////////////////////////////////////////////////\r
+// 1D Sum Filter\r
+\r
+namespace\r
+{\r
+    class NppRowSumFilter : public BaseRowFilter_GPU\r
+    {\r
+    public:\r
+        NppRowSumFilter(int ksize_, int anchor_) : BaseRowFilter_GPU(ksize_, anchor_) {}\r
+\r
+        virtual void operator()(const GpuMat& src, GpuMat& dst)\r
         {\r
-            dst.swap(dstBuf);\r
-            nppSafeCall( func(dstBuf.ptr<Npp8u>(), dstBuf.step, dst.ptr<Npp8u>(), dst.step, sz, gpu_krnl.ptr<Npp8u>(), mask_sz, anc) );\r
+            NppiSize sz;\r
+            sz.width = src.cols;\r
+            sz.height = src.rows;\r
+\r
+            nppSafeCall( nppiSumWindowRow_8u32f_C1R(src.ptr<Npp8u>(), src.step, dst.ptr<Npp32f>(), dst.step, sz, ksize, anchor) );\r
         }\r
-    }\r
+    };\r
+}\r
+\r
+Ptr<BaseRowFilter_GPU> cv::gpu::getRowSumFilter_GPU(int srcType, int sumType, int ksize, int anchor)\r
+{\r
+    CV_Assert(srcType == CV_8UC1 && sumType == CV_32FC1);\r
+\r
+    normalizeAnchor(anchor, ksize);\r
+\r
+    return Ptr<BaseRowFilter_GPU>(new NppRowSumFilter(ksize, anchor));\r
 }\r
 \r
+namespace\r
+{\r
+    class NppColumnSumFilter : public BaseColumnFilter_GPU\r
+    {\r
+    public:\r
+        NppColumnSumFilter(int ksize_, int anchor_) : BaseColumnFilter_GPU(ksize_, anchor_) {}\r
 \r
-void cv::gpu::erode( const GpuMat& src, GpuMat& dst, const Mat& kernel, Point anchor, int iterations)\r
+        virtual void operator()(const GpuMat& src, GpuMat& dst)\r
+        {\r
+            NppiSize sz;\r
+            sz.width = src.cols;\r
+            sz.height = src.rows;\r
+\r
+            nppSafeCall( nppiSumWindowColumn_8u32f_C1R(src.ptr<Npp8u>(), src.step, dst.ptr<Npp32f>(), dst.step, sz, ksize, anchor) );\r
+        }\r
+    };\r
+}\r
+\r
+Ptr<BaseColumnFilter_GPU> cv::gpu::getColumnSumFilter_GPU(int sumType, int dstType, int ksize, int anchor)\r
+{\r
+    CV_Assert(sumType == CV_8UC1 && dstType == CV_32FC1);\r
+\r
+    normalizeAnchor(anchor, ksize);\r
+\r
+    return Ptr<BaseColumnFilter_GPU>(new NppColumnSumFilter(ksize, anchor));\r
+}\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////\r
+// Box Filter\r
+\r
+namespace\r
+{\r
+    typedef NppStatus (*nppFilterBox_t)(const Npp8u * pSrc, Npp32s nSrcStep, Npp8u * pDst, Npp32s nDstStep, NppiSize oSizeROI, \r
+        NppiSize oMaskSize, NppiPoint oAnchor);\r
+\r
+    class NPPBoxFilter : public BaseFilter_GPU\r
+    {\r
+    public:\r
+        NPPBoxFilter(const Size& ksize_, const Point& anchor_, nppFilterBox_t func_) : BaseFilter_GPU(ksize_, anchor_), func(func_) {}\r
+\r
+        virtual void operator()(const GpuMat& src, GpuMat& dst)\r
+        {\r
+            NppiSize sz;\r
+            sz.width = src.cols;\r
+            sz.height = src.rows;\r
+            NppiSize oKernelSize;\r
+            oKernelSize.height = ksize.height;\r
+            oKernelSize.width = ksize.width;\r
+            NppiPoint oAnchor;\r
+            oAnchor.x = anchor.x;\r
+            oAnchor.y = anchor.y;\r
+            \r
+            nppSafeCall( func(src.ptr<Npp8u>(), src.step, dst.ptr<Npp8u>(), dst.step, sz, oKernelSize, oAnchor) );\r
+        }\r
+\r
+        nppFilterBox_t func;\r
+    };\r
+}\r
+\r
+Ptr<BaseFilter_GPU> cv::gpu::getBoxFilter_GPU(int srcType, int dstType, const Size& ksize, Point anchor)\r
+{\r
+    static const nppFilterBox_t nppFilterBox_callers[] = {0, nppiFilterBox_8u_C1R, 0, 0, nppiFilterBox_8u_C4R};\r
+\r
+    CV_Assert((srcType == CV_8UC1 || srcType == CV_8UC4) && dstType == srcType); \r
+\r
+    normalizeAnchor(anchor, ksize);\r
+\r
+    return Ptr<BaseFilter_GPU>(new NPPBoxFilter(ksize, anchor, nppFilterBox_callers[CV_MAT_CN(srcType)]));\r
+}\r
+\r
+Ptr<FilterEngine_GPU> cv::gpu::createBoxFilter_GPU(int srcType, int dstType, const Size& ksize, const Point& anchor)\r
+{\r
+    Ptr<BaseFilter_GPU> boxFilter = getBoxFilter_GPU(srcType, dstType, ksize, anchor);\r
+    return createFilter2D_GPU(boxFilter);\r
+}\r
+\r
+void cv::gpu::boxFilter(const GpuMat& src, GpuMat& dst, int ddepth, Size ksize, Point anchor)\r
+{\r
+    int sdepth = src.depth(), cn = src.channels();\r
+    if( ddepth < 0 )\r
+        ddepth = sdepth;\r
+\r
+    dst.create(src.size(), CV_MAKETYPE(ddepth, cn));\r
+\r
+    Ptr<FilterEngine_GPU> f = createBoxFilter_GPU(src.type(), dst.type(), ksize, anchor);\r
+    f->apply(src, dst);\r
+}\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////\r
+// Morphology Filter\r
+\r
+namespace\r
+{\r
+    typedef NppStatus (*nppMorfFilter_t)(const Npp8u*, Npp32s, Npp8u*, Npp32s, NppiSize, const Npp8u*, NppiSize, NppiPoint);\r
+\r
+    class NPPMorphFilter : public BaseFilter_GPU\r
+    {\r
+    public:\r
+        NPPMorphFilter(const Size& ksize_, const Point& anchor_, const GpuMat& kernel_, nppMorfFilter_t func_) : \r
+            BaseFilter_GPU(ksize_, anchor_), kernel(kernel_), func(func_) {}\r
+\r
+        virtual void operator()(const GpuMat& src, GpuMat& dst)\r
+        {\r
+            NppiSize sz;\r
+            sz.width = src.cols;\r
+            sz.height = src.rows;\r
+            NppiSize oKernelSize;\r
+            oKernelSize.height = ksize.height;\r
+            oKernelSize.width = ksize.width;\r
+            NppiPoint oAnchor;\r
+            oAnchor.x = anchor.x;\r
+            oAnchor.y = anchor.y;\r
+\r
+            nppSafeCall( func(src.ptr<Npp8u>(), src.step, dst.ptr<Npp8u>(), dst.step, sz, kernel.ptr<Npp8u>(), oKernelSize, oAnchor) );\r
+        }\r
+\r
+        GpuMat kernel;\r
+        nppMorfFilter_t func;\r
+    };\r
+}\r
+\r
+Ptr<BaseFilter_GPU> cv::gpu::getMorphologyFilter_GPU(int op, int type, const GpuMat& kernel, const Size& ksize, Point anchor)\r
+{\r
+    static const nppMorfFilter_t nppMorfFilter_callers[2][5] = \r
+    {\r
+        {0, nppiErode_8u_C1R, 0, 0, nppiErode_8u_C4R },\r
+        {0, nppiDilate_8u_C1R, 0, 0, nppiDilate_8u_C4R }\r
+    };\r
\r
+    CV_Assert(op == MORPH_ERODE || op == MORPH_DILATE);   \r
+    CV_Assert(type == CV_8UC1 || type == CV_8UC4); \r
+    CV_Assert(kernel.type() == CV_8UC1 && kernel.rows == 1 && kernel.cols == ksize.area());\r
+    \r
+    normalizeAnchor(anchor, ksize);\r
+    \r
+    return Ptr<BaseFilter_GPU>(new NPPMorphFilter(ksize, anchor, kernel, nppMorfFilter_callers[op][CV_MAT_CN(type)]));\r
+}\r
+\r
+namespace\r
+{\r
+    class MorphologyFilterEngine_GPU : public Filter2DEngine_GPU\r
+    {\r
+    public:\r
+        MorphologyFilterEngine_GPU(const Ptr<BaseFilter_GPU>& filter2D_, int iters_) : \r
+          Filter2DEngine_GPU(filter2D_), iters(iters_) {}\r
+\r
+        virtual void apply(const GpuMat& src, GpuMat& dst, Rect roi = Rect(0,0,-1,-1))\r
+        {\r
+            if (iters > 1)\r
+                dstBuf.create(src.size(), src.type());\r
+\r
+            Filter2DEngine_GPU::apply(src, dst);\r
+            for(int i = 1; i < iters; ++i)\r
+            {\r
+                dst.swap(dstBuf);\r
+                Filter2DEngine_GPU::apply(dst, dst);\r
+            }\r
+        }\r
+\r
+        int iters;\r
+        GpuMat dstBuf;\r
+    };\r
+}\r
+\r
+Ptr<FilterEngine_GPU> cv::gpu::createMorphologyFilter_GPU(int op, int type, const Mat& kernel, const Point& anchor, int iterations)\r
+{\r
+    CV_Assert(iterations > 0);\r
+\r
+    Size ksize = kernel.size();\r
+\r
+    GpuMat gpu_krnl;\r
+    normalizeKernel(kernel, gpu_krnl);\r
+\r
+    Ptr<BaseFilter_GPU> filter2D = getMorphologyFilter_GPU(op, type, gpu_krnl, ksize, anchor);\r
+\r
+    return Ptr<FilterEngine_GPU>(new MorphologyFilterEngine_GPU(filter2D, iterations));\r
+}\r
+\r
+namespace\r
 {\r
-    static npp_morf_func funcs[] = {0, nppiErode_8u_C1R, 0, 0, nppiErode_8u_C4R };\r
+    void morphOp(int op, const GpuMat& src, GpuMat& dst, const Mat& _kernel, Point anchor, int iterations)\r
+    {\r
+        Mat kernel;\r
+        Size ksize = _kernel.data ? _kernel.size() : Size(3, 3);\r
+\r
+        normalizeAnchor(anchor, ksize);\r
 \r
-    morphoogy_caller(funcs[src.channels()], src, dst, kernel, anchor, iterations);    \r
+        if (iterations == 0 || _kernel.rows * _kernel.cols == 1)\r
+        {\r
+            src.copyTo(dst);\r
+            return;\r
+        }\r
+\r
+        dst.create(src.size(), src.type());\r
+\r
+        if (!_kernel.data)\r
+        {\r
+            kernel = getStructuringElement(MORPH_RECT, Size(1 + iterations * 2, 1 + iterations * 2));\r
+            anchor = Point(iterations, iterations);\r
+            iterations = 1;\r
+        }\r
+        else if (iterations > 1 && countNonZero(_kernel) == _kernel.rows * _kernel.cols)\r
+        {\r
+            anchor = Point(anchor.x * iterations, anchor.y * iterations);\r
+            kernel = getStructuringElement(MORPH_RECT, Size(ksize.width + iterations * (ksize.width - 1), \r
+                ksize.height + iterations * (ksize.height - 1)), anchor);\r
+            iterations = 1;\r
+        }\r
+        else\r
+            kernel = _kernel;\r
+\r
+        Ptr<FilterEngine_GPU> f = createMorphologyFilter_GPU(op, src.type(), kernel, anchor, iterations);\r
+\r
+        f->apply(src, dst);\r
+    }\r
+}\r
+\r
+void cv::gpu::erode( const GpuMat& src, GpuMat& dst, const Mat& kernel, Point anchor, int iterations)\r
+{\r
+    morphOp(MORPH_ERODE, src, dst, kernel, anchor, iterations);\r
 }\r
 \r
 void cv::gpu::dilate( const GpuMat& src, GpuMat& dst, const Mat& kernel, Point anchor, int iterations)\r
 {\r
-    static npp_morf_func funcs[] = {0, nppiDilate_8u_C1R, 0, 0, nppiDilate_8u_C4R };\r
-    morphoogy_caller(funcs[src.channels()], src, dst, kernel, anchor, iterations);\r
+    morphOp(MORPH_DILATE, src, dst, kernel, anchor, iterations);\r
 }\r
 \r
 void cv::gpu::morphologyEx( const GpuMat& src, GpuMat& dst, int op, const Mat& kernel, Point anchor, int iterations)\r
@@ -165,195 +496,197 @@ void cv::gpu::morphologyEx( const GpuMat& src, GpuMat& dst, int op, const Mat& k
     }\r
 }\r
 \r
-////////////////////////////////////////////////////////////////////////\r
-// boxFilter\r
+////////////////////////////////////////////////////////////////////////////////////////////////////\r
+// Linear Filter\r
 \r
-void cv::gpu::boxFilter(const GpuMat& src, GpuMat& dst, Size ksize, Point anchor)\r
+namespace\r
 {\r
-    CV_Assert(src.type() == CV_8UC1 || src.type() == CV_8UC4);\r
-    CV_Assert(ksize.height == 3 || ksize.height == 5 || ksize.height == 7);\r
-    CV_Assert(ksize.height == ksize.width);\r
-\r
-    if (anchor.x == -1)\r
-        anchor.x = 0;\r
-    if (anchor.y == -1)\r
-        anchor.y = 0;\r
+    typedef NppStatus (*nppFilter2D_t)(const Npp8u * pSrc, Npp32s nSrcStep, Npp8u * pDst, Npp32s nDstStep, NppiSize oSizeROI, \r
+        const Npp32s * pKernel, NppiSize oKernelSize, NppiPoint oAnchor, Npp32s nDivisor);\r
 \r
-    CV_Assert(anchor.x == 0 && anchor.y == 0);\r
+    class NPPLinearFilter : public BaseFilter_GPU\r
+    {\r
+    public:\r
+        NPPLinearFilter(const Size& ksize_, const Point& anchor_, const GpuMat& kernel_, Npp32s nDivisor_, nppFilter2D_t func_) : \r
+            BaseFilter_GPU(ksize_, anchor_), kernel(kernel_), nDivisor(nDivisor_), func(func_) {}\r
 \r
-    dst.create(src.size(), src.type());\r
+        virtual void operator()(const GpuMat& src, GpuMat& dst)\r
+        {\r
+            NppiSize sz;\r
+            sz.width = src.cols;\r
+            sz.height = src.rows;\r
+            NppiSize oKernelSize;\r
+            oKernelSize.height = ksize.height;\r
+            oKernelSize.width = ksize.width;\r
+            NppiPoint oAnchor;\r
+            oAnchor.x = anchor.x;\r
+            oAnchor.y = anchor.y;\r
+                                  \r
+            nppSafeCall( func(src.ptr<Npp8u>(), src.step, dst.ptr<Npp8u>(), dst.step, sz, \r
+                kernel.ptr<Npp32s>(), oKernelSize, oAnchor, nDivisor) );\r
+        }\r
 \r
-    NppiSize srcsz;\r
-    srcsz.height = src.rows;\r
-    srcsz.width = src.cols;\r
-    NppiSize masksz;\r
-    masksz.height = ksize.height;\r
-    masksz.width = ksize.width;\r
-    NppiPoint anc;\r
-    anc.x = anchor.x;\r
-    anc.y = anchor.y;\r
-\r
-    if (src.type() == CV_8UC1)\r
-    {\r
-        nppSafeCall( nppiFilterBox_8u_C1R(src.ptr<Npp8u>(), src.step, dst.ptr<Npp8u>(), dst.step, srcsz, masksz, anc) );\r
-    }\r
-    else\r
-    {\r
-        nppSafeCall( nppiFilterBox_8u_C4R(src.ptr<Npp8u>(), src.step, dst.ptr<Npp8u>(), dst.step, srcsz, masksz, anc) );\r
-    }\r
+        GpuMat kernel;\r
+        Npp32s nDivisor;\r
+        nppFilter2D_t func;\r
+    };\r
 }\r
 \r
-////////////////////////////////////////////////////////////////////////\r
-// sumWindow Filter\r
-\r
-namespace\r
+Ptr<BaseFilter_GPU> cv::gpu::getLinearFilter_GPU(int srcType, int dstType, const GpuMat& kernel, const Size& ksize, Point anchor, int nDivisor)\r
 {\r
-    typedef NppStatus (*nppSumWindow_t)(const Npp8u * pSrc, Npp32s nSrcStep, \r
-                                        Npp32f * pDst, Npp32s nDstStep, NppiSize oROI, \r
-                                        Npp32s nMaskSize, Npp32s nAnchor);\r
-\r
-    inline void sumWindowCaller(nppSumWindow_t func, const GpuMat& src, GpuMat& dst, int ksize, int anchor)\r
-    {\r
-        CV_Assert(src.type() == CV_8UC1);\r
-        \r
-        if (anchor == -1)\r
-            anchor = ksize / 2;\r
+    static const nppFilter2D_t cppFilter2D_callers[] = {0, nppiFilter_8u_C1R, 0, 0, nppiFilter_8u_C4R};\r
 \r
-        NppiSize sz;\r
-        sz.width = src.cols;\r
-        sz.height = src.rows;\r
+    CV_Assert((srcType == CV_8UC1 || srcType == CV_8UC4) && dstType == srcType); \r
+    CV_Assert(kernel.type() == CV_32SC1 && kernel.rows == 1 && kernel.cols == ksize.area());\r
 \r
-        dst.create(src.size(), CV_32FC1);\r
+    normalizeAnchor(anchor, ksize);\r
 \r
-        nppSafeCall( func(src.ptr<Npp8u>(), src.step, dst.ptr<Npp32f>(), dst.step, sz, ksize, anchor) );\r
-    }\r
-}\r
+    return Ptr<BaseFilter_GPU>(new NPPLinearFilter(ksize, anchor, kernel, nDivisor, cppFilter2D_callers[CV_MAT_CN(srcType)]));\r
+}    \r
 \r
-void cv::gpu::sumWindowColumn(const GpuMat& src, GpuMat& dst, int ksize, int anchor)\r
+Ptr<FilterEngine_GPU> cv::gpu::createLinearFilter_GPU(int srcType, int dstType, const Mat& kernel, const Point& anchor)\r
 {\r
-    sumWindowCaller(nppiSumWindowColumn_8u32f_C1R, src, dst, ksize, anchor);\r
+    Size ksize = kernel.size();\r
+\r
+    GpuMat gpu_krnl;\r
+    int nDivisor;\r
+    normalizeKernel(kernel, gpu_krnl, CV_32S, &nDivisor, true);\r
+\r
+    Ptr<BaseFilter_GPU> linearFilter = getLinearFilter_GPU(srcType, dstType, gpu_krnl, ksize, anchor, nDivisor);\r
+\r
+    return createFilter2D_GPU(linearFilter);\r
 }\r
 \r
-void cv::gpu::sumWindowRow(const GpuMat& src, GpuMat& dst, int ksize, int anchor)\r
+void cv::gpu::filter2D(const GpuMat& src, GpuMat& dst, int ddepth, const Mat& kernel, Point anchor)\r
 {\r
-    sumWindowCaller(nppiSumWindowRow_8u32f_C1R, src, dst, ksize, anchor);\r
+    if( ddepth < 0 )\r
+        ddepth = src.depth();\r
+\r
+    dst.create(src.size(), CV_MAKETYPE(ddepth, src.channels()));\r
+\r
+    Ptr<FilterEngine_GPU> f = createLinearFilter_GPU(src.type(), dst.type(), kernel, anchor);\r
+    f->apply(src, dst);\r
 }\r
 \r
-////////////////////////////////////////////////////////////////////////\r
-// Filter Engine\r
+////////////////////////////////////////////////////////////////////////////////////////////////////\r
+// Separable Linear Filter\r
 \r
 namespace\r
 {\r
     typedef NppStatus (*nppFilter1D_t)(const Npp8u * pSrc, Npp32s nSrcStep, Npp8u * pDst, Npp32s nDstStep, NppiSize oROI, \r
-                     const Npp32s * pKernel, Npp32s nMaskSize, Npp32s nAnchor, Npp32s nDivisor);\r
-    typedef NppStatus (*nppFilter2D_t)(const Npp8u * pSrc, Npp32s nSrcStep, Npp8u * pDst, Npp32s nDstStep, NppiSize oSizeROI, \r
-                  const Npp32s * pKernel, NppiSize oKernelSize, NppiPoint oAnchor, Npp32s nDivisor);\r
+        const Npp32s * pKernel, Npp32s nMaskSize, Npp32s nAnchor, Npp32s nDivisor);\r
 \r
-    void applyRowFilter(const GpuMat& src, GpuMat& dst, const GpuMat& rowKernel, Npp32s anchor = -1, Npp32s nDivisor = 1)\r
+    class NppLinearRowFilter : public BaseRowFilter_GPU\r
     {\r
-        static const nppFilter1D_t nppFilter1D_callers[] = {nppiFilterRow_8u_C1R, nppiFilterRow_8u_C4R};\r
+    public:\r
+        NppLinearRowFilter(int ksize_, int anchor_, const GpuMat& kernel_, Npp32s nDivisor_, nppFilter1D_t func_) : \r
+            BaseRowFilter_GPU(ksize_, anchor_), kernel(kernel_), nDivisor(nDivisor_), func(func_) {}\r
 \r
-        CV_Assert(src.type() == CV_8UC1 || src.type() == CV_8UC4);\r
+        virtual void operator()(const GpuMat& src, GpuMat& dst)\r
+        {\r
+            NppiSize sz;\r
+            sz.width = src.cols;\r
+            sz.height = src.rows;\r
 \r
-        int kRowSize = rowKernel.cols;\r
+            nppSafeCall( func(src.ptr<Npp8u>(), src.step, dst.ptr<Npp8u>(), dst.step, sz, kernel.ptr<Npp32s>(), ksize, anchor, nDivisor) );\r
+        }\r
 \r
-        dst.create(src.size(), src.type());\r
-        dst = Scalar();\r
+        GpuMat kernel;\r
+        Npp32s nDivisor;\r
+        nppFilter1D_t func;\r
+    };\r
+}\r
 \r
-        NppiSize oROI;\r
-        oROI.width = src.cols - kRowSize + 1;\r
-        oROI.height = src.rows;\r
+Ptr<BaseRowFilter_GPU> cv::gpu::getLinearRowFilter_GPU(int srcType, int bufType, const GpuMat& rowKernel, int anchor, int nDivisor)\r
+{\r
+    static const nppFilter1D_t nppFilter1D_callers[] = {0, nppiFilterRow_8u_C1R, 0, 0, nppiFilterRow_8u_C4R};\r
 \r
-        if (anchor < 0)\r
-            anchor = kRowSize >> 1;\r
+    CV_Assert((srcType == CV_8UC1 || srcType == CV_8UC4) && bufType == srcType);\r
+    CV_Assert(rowKernel.type() == CV_32SC1 && rowKernel.rows == 1);\r
 \r
-        GpuMat srcROI = src.colRange(kRowSize-1, oROI.width);\r
-        GpuMat dstROI = dst.colRange(kRowSize-1, oROI.width);\r
+    int ksize = rowKernel.cols;\r
 \r
-        nppFilter1D_callers[src.channels() >> 2](srcROI.ptr<Npp8u>(), srcROI.step, dstROI.ptr<Npp8u>(), dstROI.step, oROI, \r
-                rowKernel.ptr<Npp32s>(), kRowSize, anchor, nDivisor);\r
-    }\r
+    normalizeAnchor(anchor, ksize);\r
+\r
+    return Ptr<BaseRowFilter_GPU>(new NppLinearRowFilter(ksize, anchor, rowKernel, nDivisor, nppFilter1D_callers[CV_MAT_CN(srcType)]));\r
+}\r
 \r
-    void applyColumnFilter(const GpuMat& src, GpuMat& dst, const GpuMat& columnKernel, Npp32s anchor = -1, Npp32s nDivisor = 1)\r
+namespace\r
+{\r
+    class NppLinearColumnFilter : public BaseColumnFilter_GPU\r
     {\r
-        static const nppFilter1D_t nppFilter1D_callers[] = {nppiFilterColumn_8u_C1R, nppiFilterColumn_8u_C4R};\r
+    public:\r
+        NppLinearColumnFilter(int ksize_, int anchor_, const GpuMat& kernel_, Npp32s nDivisor_, nppFilter1D_t func_) : \r
+            BaseColumnFilter_GPU(ksize_, anchor_), kernel(kernel_), nDivisor(nDivisor_), func(func_) {}\r
 \r
-        CV_Assert(src.type() == CV_8UC1 || src.type() == CV_8UC4);\r
+        virtual void operator()(const GpuMat& src, GpuMat& dst)\r
+        {\r
+            NppiSize sz;\r
+            sz.width = src.cols;\r
+            sz.height = src.rows;\r
 \r
-        int kColSize = columnKernel.cols;\r
+            nppSafeCall( func(src.ptr<Npp8u>(), src.step, dst.ptr<Npp8u>(), dst.step, sz, kernel.ptr<Npp32s>(), ksize, anchor, nDivisor) );\r
+        }\r
 \r
-        dst.create(src.size(), src.type());\r
-        dst = Scalar();\r
+        GpuMat kernel;\r
+        Npp32s nDivisor;\r
+        nppFilter1D_t func;\r
+    };\r
+}\r
 \r
-        NppiSize oROI;\r
-        oROI.width = src.cols;\r
-        oROI.height = src.rows - kColSize + 1;\r
+Ptr<BaseColumnFilter_GPU> cv::gpu::getLinearColumnFilter_GPU(int bufType, int dstType, const GpuMat& columnKernel, int anchor, int nDivisor)\r
+{\r
+    static const nppFilter1D_t nppFilter1D_callers[] = {0, nppiFilterColumn_8u_C1R, 0, 0, nppiFilterColumn_8u_C4R};\r
 \r
-        if (anchor < 0)\r
-            anchor = kColSize >> 1;\r
+    CV_Assert((bufType == CV_8UC1 || bufType == CV_8UC4) && dstType == bufType);\r
+    CV_Assert(columnKernel.type() == CV_32SC1 && columnKernel.rows == 1);\r
 \r
-        GpuMat srcROI = src.rowRange(kColSize-1, oROI.height);\r
-        GpuMat dstROI = dst.rowRange(kColSize-1, oROI.height);\r
-        \r
-        nppFilter1D_callers[src.channels() >> 2](srcROI.ptr<Npp8u>(), srcROI.step, dstROI.ptr<Npp8u>(), dstROI.step, oROI, \r
-                columnKernel.ptr<Npp32s>(), kColSize, anchor, nDivisor);\r
-    }\r
+    int ksize = columnKernel.cols;\r
 \r
-    inline void applySeparableFilter(const GpuMat& src, GpuMat& dst, const GpuMat& rowKernel, const GpuMat& columnKernel, \r
-        const cv::Point& anchor = cv::Point(-1, -1), Npp32s nDivisor = 1)\r
-    {\r
-        GpuMat dstBuf;\r
-        applyRowFilter(src, dstBuf, rowKernel, anchor.x, nDivisor);\r
-        applyColumnFilter(dstBuf, dst, columnKernel, anchor.y, nDivisor);\r
-    }\r
+    normalizeAnchor(anchor, ksize);\r
 \r
-    void makeNppKernel(Mat kernel, GpuMat& dst)\r
-    {\r
-        kernel.convertTo(kernel, CV_32S); \r
-        kernel = kernel.t();\r
-        int ksize = kernel.cols;\r
-        for (int i = 0; i < ksize / 2; ++i)\r
-        {\r
-            std::swap(kernel.at<int>(0, i), kernel.at<int>(0, ksize - 1 - i));\r
-        }\r
-        dst.upload(kernel);\r
-    }\r
+    return Ptr<BaseColumnFilter_GPU>(new NppLinearColumnFilter(ksize, anchor, columnKernel, nDivisor, nppFilter1D_callers[CV_MAT_CN(bufType)]));\r
+}\r
 \r
-    void applyFilter2D(const GpuMat& src, GpuMat& dst, const GpuMat& kernel, cv::Point anchor = cv::Point(-1, -1), Npp32s nDivisor = 1)\r
-    {\r
-        static const nppFilter2D_t nppFilter2D_callers[] = {nppiFilter_8u_C1R, nppiFilter_8u_C4R};        \r
+Ptr<FilterEngine_GPU> cv::gpu::createSeparableLinearFilter_GPU(int srcType, int dstType, const Mat& rowKernel, const Mat& columnKernel, \r
+    const Point& anchor)\r
+{\r
+    int sdepth = CV_MAT_DEPTH(srcType), ddepth = CV_MAT_DEPTH(dstType);\r
+    int cn = CV_MAT_CN(srcType);\r
+    int bdepth = std::max(sdepth, ddepth);\r
+    int bufType = CV_MAKETYPE(bdepth, cn);\r
 \r
-        CV_Assert(src.type() == CV_8UC1 || src.type() == CV_8UC4);\r
+    GpuMat gpu_row_krnl, gpu_col_krnl;\r
+    int nRowDivisor, nColDivisor;\r
+    normalizeKernel(rowKernel, gpu_row_krnl, CV_32S, &nRowDivisor, true);\r
+    normalizeKernel(columnKernel, gpu_col_krnl, CV_32S, &nColDivisor, true);\r
 \r
-        dst.create(src.size(), src.type());\r
-        dst = Scalar();\r
-\r
-        NppiSize oROI;\r
-        oROI.width = src.cols - kernel.cols + 1;\r
-        oROI.height = src.rows - kernel.rows + 1;\r
-\r
-        if (anchor.x < 0)\r
-            anchor.x = kernel.cols >> 1;\r
-        if (anchor.y < 0)\r
-            anchor.y = kernel.rows >> 1;\r
-\r
-        GpuMat srcROI = src(Range(kernel.rows-1, oROI.height), Range(kernel.cols-1, oROI.width));\r
-        GpuMat dstROI = dst(Range(kernel.rows-1, oROI.height), Range(kernel.cols-1, oROI.width));\r
-\r
-        NppiSize oKernelSize;\r
-        oKernelSize.height = kernel.rows;\r
-        oKernelSize.width = kernel.cols;\r
-        NppiPoint oAnchor;\r
-        oAnchor.x = anchor.x;\r
-        oAnchor.y = anchor.y;\r
-        \r
-        nppFilter2D_callers[src.channels() >> 2](srcROI.ptr<Npp8u>(), srcROI.step, dstROI.ptr<Npp8u>(), dstROI.step, oROI, \r
-                kernel.ptr<Npp32s>(), oKernelSize, oAnchor, nDivisor);\r
-    }\r
+    Ptr<BaseRowFilter_GPU> rowFilter = getLinearRowFilter_GPU(srcType, bufType, gpu_row_krnl, anchor.x, nRowDivisor);\r
+    Ptr<BaseColumnFilter_GPU> columnFilter = getLinearColumnFilter_GPU(bufType, dstType, gpu_col_krnl, anchor.y, nColDivisor);\r
+\r
+    return createSeparableFilter_GPU(rowFilter, columnFilter);\r
+}\r
+\r
+void cv::gpu::sepFilter2D(const GpuMat& src, GpuMat& dst, int ddepth, const Mat& kernelX, const Mat& kernelY, Point anchor)\r
+{\r
+    if( ddepth < 0 )\r
+        ddepth = src.depth();\r
+\r
+    dst.create(src.size(), CV_MAKETYPE(ddepth, src.channels()));\r
+\r
+    Ptr<FilterEngine_GPU> f = createSeparableLinearFilter_GPU(src.type(), dst.type(), kernelX, kernelY, anchor);\r
+    f->apply(src, dst);\r
 }\r
 \r
-////////////////////////////////////////////////////////////////////////\r
-// Sobel\r
+////////////////////////////////////////////////////////////////////////////////////////////////////\r
+// Deriv Filter\r
+\r
+Ptr<FilterEngine_GPU> cv::gpu::createDerivFilter_GPU(int srcType, int dstType, int dx, int dy, int ksize)\r
+{\r
+    Mat kx, ky;\r
+    getDerivKernels(kx, ky, dx, dy, ksize, false, CV_32F);\r
+    return createSeparableLinearFilter_GPU(srcType, dstType, kx, ky);\r
+}\r
 \r
 void cv::gpu::Sobel(const GpuMat& src, GpuMat& dst, int ddepth, int dx, int dy, int ksize, double scale)\r
 {\r
@@ -370,55 +703,86 @@ void cv::gpu::Sobel(const GpuMat& src, GpuMat& dst, int ddepth, int dx, int dy,
             ky *= scale;\r
     }\r
     \r
-    GpuMat rowKernel; makeNppKernel(kx, rowKernel);\r
-    GpuMat columnKernel; makeNppKernel(ky, columnKernel);\r
-\r
-    applySeparableFilter(src, dst, rowKernel, columnKernel);\r
+    sepFilter2D(src, dst, ddepth, kx, ky, Point(-1,-1));\r
 }\r
 \r
-////////////////////////////////////////////////////////////////////////\r
-// GaussianBlur\r
-\r
-void cv::gpu::GaussianBlur(const GpuMat& src, GpuMat& dst, Size ksize, double sigma1, double sigma2)\r
+void cv::gpu::Scharr(const GpuMat& src, GpuMat& dst, int ddepth, int dx, int dy, double scale)\r
 {\r
-    if (ksize.width == 1 && ksize.height == 1)\r
+    Mat kx, ky;\r
+    getDerivKernels(kx, ky, dx, dy, -1, false, CV_32F);\r
+\r
+    if( scale != 1 )\r
     {\r
-        src.copyTo(dst);\r
-        return;\r
+        // usually the smoothing part is the slowest to compute,\r
+        // so try to scale it instead of the faster differenciating part\r
+        if( dx == 0 )\r
+            kx *= scale;\r
+        else\r
+            ky *= scale;\r
     }\r
 \r
-    int depth = src.depth();\r
+    sepFilter2D(src, dst, ddepth, kx, ky, Point(-1,-1));\r
+}\r
+\r
+void cv::gpu::Laplacian(const GpuMat& src, GpuMat& dst, int ddepth, int ksize, double scale)\r
+{\r
+    CV_Assert(ksize == 1 || ksize == 3);\r
+\r
+    static const int K[2][9] =\r
+    {\r
+        {0, 1, 0, 1, -4, 1, 0, 1, 0},\r
+        {2, 0, 2, 0, -8, 0, 2, 0, 2}\r
+    };\r
+    Mat kernel(3, 3, CV_32S, (void*)K[ksize == 3]);\r
+    if (scale != 1)\r
+        kernel *= scale;\r
+    \r
+    filter2D(src, dst, ddepth, kernel, Point(-1,-1));\r
+}\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////\r
+// Gaussian Filter\r
+\r
+Ptr<FilterEngine_GPU> cv::gpu::createGaussianFilter_GPU(int type, Size ksize, double sigma1, double sigma2)\r
+{        \r
+    int depth = CV_MAT_DEPTH(type);\r
+\r
     if (sigma2 <= 0)\r
         sigma2 = sigma1;\r
 \r
     // automatic detection of kernel size from sigma\r
     if (ksize.width <= 0 && sigma1 > 0)\r
-        ksize.width = cvRound(sigma1 * (depth == CV_8U ? 3 : 4) * 2 + 1) | 1;\r
+        ksize.width = cvRound(sigma1 * (depth == CV_8U ? 3 : 4)*2 + 1) | 1;\r
     if (ksize.height <= 0 && sigma2 > 0)\r
-        ksize.height = cvRound(sigma2 * (depth == CV_8U ? 3 : 4) * 2 + 1) | 1;\r
+        ksize.height = cvRound(sigma2 * (depth == CV_8U ? 3 : 4)*2 + 1) | 1;\r
 \r
-    CV_Assert(ksize.width > 0 && ksize.width % 2 == 1 && ksize.height > 0 && ksize.height % 2 == 1);\r
+    CV_Assert( ksize.width > 0 && ksize.width % 2 == 1 && ksize.height > 0 && ksize.height % 2 == 1 );\r
 \r
     sigma1 = std::max(sigma1, 0.0);\r
     sigma2 = std::max(sigma2, 0.0);\r
-    \r
-    const int scaleFactor = 256;\r
 \r
-    Mat kx = getGaussianKernel(ksize.width, sigma1, std::max(depth, CV_32F));\r
-    kx.convertTo(kx, kx.depth(), scaleFactor);\r
+    Mat kx = getGaussianKernel( ksize.width, sigma1, std::max(depth, CV_32F) );\r
     Mat ky;\r
-    if (ksize.height == ksize.width && std::abs(sigma1 - sigma2) < DBL_EPSILON)\r
+    if( ksize.height == ksize.width && std::abs(sigma1 - sigma2) < DBL_EPSILON )\r
         ky = kx;\r
     else\r
+        ky = getGaussianKernel( ksize.height, sigma2, std::max(depth, CV_32F) );\r
+\r
+    return createSeparableLinearFilter_GPU(type, type, kx, ky);\r
+}\r
+\r
+void cv::gpu::GaussianBlur(const GpuMat& src, GpuMat& dst, Size ksize, double sigma1, double sigma2)\r
+{\r
+    if (ksize.width == 1 && ksize.height == 1)\r
     {\r
-        ky = getGaussianKernel(ksize.height, sigma2, std::max(depth, CV_32F));        \r
-        ky.convertTo(ky, ky.depth(), scaleFactor);\r
+        src.copyTo(dst);\r
+        return;\r
     }\r
 \r
-    GpuMat rowKernel; makeNppKernel(kx, rowKernel);\r
-    GpuMat columnKernel; makeNppKernel(ky, columnKernel);\r
-\r
-    applySeparableFilter(src, dst, rowKernel, columnKernel, cv::Point(-1, -1), scaleFactor);\r
+    dst.create(src.size(), src.type());\r
+    \r
+    Ptr<FilterEngine_GPU> f = createGaussianFilter_GPU(src.type(), ksize, sigma1, sigma2);\r
+    f->apply(src, dst);\r
 }\r
 \r
 #endif\r
index a786a62..9c88f3e 100644 (file)
@@ -992,6 +992,7 @@ void cv::gpu::integral(GpuMat& src, GpuMat& sum, GpuMat& sqsum)
 \r
 void cv::gpu::Canny(const GpuMat& image, GpuMat& edges, double threshold1, double threshold2, int apertureSize)\r
 {\r
+    CV_Assert(!"disabled until fix crash");\r
     CV_Assert(image.type() == CV_8UC1);\r
 \r
     GpuMat srcDx, srcDy;\r
diff --git a/tests/gpu/src/filters.cpp b/tests/gpu/src/filters.cpp
new file mode 100644 (file)
index 0000000..b73d052
--- /dev/null
@@ -0,0 +1,383 @@
+/*M///////////////////////////////////////////////////////////////////////////////////////\r
+//\r
+//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.\r
+//\r
+//  By downloading, copying, installing or using the software you agree to this license.\r
+//  If you do not agree to this license, do not download, install,\r
+//  copy or use the software.\r
+//\r
+//\r
+//                        Intel License Agreement\r
+//                For Open Source Computer Vision Library\r
+//\r
+// Copyright (C) 2000, Intel Corporation, all rights reserved.\r
+// Third party copyrights are property of their respective owners.\r
+//\r
+// Redistribution and use in source and binary forms, with or without modification,\r
+// are permitted provided that the following conditions are met:\r
+//\r
+//   * Redistribution's of source code must retain the above copyright notice,\r
+//     this list of conditions and the following disclaimer.\r
+//\r
+//   * Redistribution's in binary form must reproduce the above copyright notice,\r
+//     this list of conditions and the following disclaimer in the documentation\r
+//     and/or other materials provided with the distribution.\r
+//\r
+//   * The name of Intel Corporation may not be used to endorse or promote products\r
+//     derived from this software without specific prior written permission.\r
+//\r
+// This software is provided by the copyright holders and contributors "as is" and\r
+// any express or implied warranties, including, but not limited to, the implied\r
+// warranties of merchantability and fitness for a particular purpose are disclaimed.\r
+// In no event shall the Intel Corporation or contributors be liable for any direct,\r
+// indirect, incidental, special, exemplary, or consequential damages\r
+// (including, but not limited to, procurement of substitute goods or services;\r
+// loss of use, data, or profits; or business interruption) however caused\r
+// and on any theory of liability, whether in contract, strict liability,\r
+// or tort (including negligence or otherwise) arising in any way out of\r
+// the use of this software, even if advised of the possibility of such damage.\r
+//\r
+//M*/\r
+\r
+#include <iostream>\r
+#include <cmath>\r
+#include <limits>\r
+#include "gputest.hpp"\r
+#include "opencv2/imgproc/imgproc.hpp"\r
+#include "opencv2/highgui/highgui.hpp"\r
+\r
+using namespace cv;\r
+using namespace std;\r
+using namespace gpu;\r
+\r
+class CV_GpuNppFilterTest : public CvTest\r
+{\r
+public:\r
+    CV_GpuNppFilterTest(const char* test_name, const char* test_funcs) : CvTest(test_name, test_funcs) {}\r
+    virtual ~CV_GpuNppFilterTest() {}\r
+\r
+protected:\r
+    void run(int);\r
+    virtual int test(const Mat& img) = 0;\r
+    \r
+    int test8UC1(const Mat& img)\r
+    {\r
+        cv::Mat img_C1;\r
+        cvtColor(img, img_C1, CV_BGR2GRAY);\r
+        return test(img_C1);\r
+    }\r
+\r
+    int test8UC4(const Mat& img)\r
+    {\r
+        cv::Mat img_C4;\r
+        cvtColor(img, img_C4, CV_BGR2BGRA);\r
+        return test(img_C4);\r
+    }\r
+        \r
+    int CheckNorm(const Mat& m1, const Mat& m2, const Size& ksize)\r
+    {\r
+        Rect roi = Rect(ksize.width, ksize.height, m1.cols - 2 * ksize.width, m1.rows - 2 * ksize.height);\r
+        Mat m1ROI = m1(roi);\r
+        Mat m2ROI = m2(roi);\r
+\r
+        double res = norm(m1ROI, m2ROI, NORM_INF);\r
+\r
+        if (res <= 1)\r
+            return CvTS::OK;\r
+        \r
+        ts->printf(CvTS::LOG, "\nNorm: %f\n", res);\r
+        return CvTS::FAIL_GENERIC;\r
+    }\r
+};\r
+\r
+void CV_GpuNppFilterTest::run( int )\r
+{    \r
+    cv::Mat img = cv::imread(std::string(ts->get_data_path()) + "stereobp/aloe-L.png");\r
+    \r
+    if (img.empty())\r
+    {\r
+        ts->set_failed_test_info(CvTS::FAIL_MISSING_TEST_DATA);\r
+        return;\r
+    }\r
+\r
+    try\r
+    {\r
+        //run tests\r
+        int testResult = CvTS::OK;\r
+\r
+        if (test8UC1(img) != CvTS::OK)\r
+            testResult = CvTS::FAIL_GENERIC;\r
+\r
+        if (test8UC4(img) != CvTS::OK)\r
+            testResult = CvTS::FAIL_GENERIC;\r
+\r
+        ts->set_failed_test_info(testResult);\r
+    }\r
+    catch(const cv::Exception& e)\r
+    {\r
+        if (!check_and_treat_gpu_exception(e, ts))\r
+            throw;\r
+        return;\r
+    }\r
+\r
+    ts->set_failed_test_info(CvTS::OK);\r
+}\r
+\r
+////////////////////////////////////////////////////////////////////////////////\r
+// blur\r
+struct CV_GpuNppImageBlurTest : public CV_GpuNppFilterTest\r
+{\r
+    CV_GpuNppImageBlurTest() : CV_GpuNppFilterTest( "GPU-NppImageBlur", "blur" ) {}\r
+\r
+    int test(const Mat& img)\r
+    {\r
+        int ksizes[] = {3, 5, 7};\r
+        int ksizes_num = sizeof(ksizes) / sizeof(int);\r
+\r
+        int test_res = CvTS::OK;\r
+\r
+        for (int i = 0; i < ksizes_num; ++i)\r
+        {\r
+            for (int j = 0; j < ksizes_num; ++j)\r
+            {\r
+                Size ksize(ksizes[i], ksizes[j]);\r
+\r
+                ts->printf(CvTS::LOG, "\nksize = (%dx%d)\n", ksizes[i], ksizes[j]);\r
+\r
+                Mat cpudst;\r
+                cv::blur(img, cpudst, ksize);\r
+\r
+                GpuMat gpu1(img);\r
+                GpuMat gpudst;\r
+                cv::gpu::blur(gpu1, gpudst, ksize);\r
+\r
+                if (CheckNorm(cpudst, gpudst, ksize) != CvTS::OK)\r
+                    test_res = CvTS::FAIL_GENERIC;\r
+            }\r
+        }\r
+\r
+        return test_res;\r
+    }\r
+};\r
+\r
+////////////////////////////////////////////////////////////////////////////////\r
+// Sobel\r
+struct CV_GpuNppImageSobelTest : public CV_GpuNppFilterTest\r
+{\r
+    CV_GpuNppImageSobelTest() : CV_GpuNppFilterTest( "GPU-NppImageSobel", "Sobel" ) {}\r
+\r
+    int test(const Mat& img)\r
+    {\r
+        int ksizes[] = {3, 5, 7};\r
+        int ksizes_num = sizeof(ksizes) / sizeof(int);\r
+\r
+        int dx = 1, dy = 0;\r
+\r
+        int test_res = CvTS::OK;\r
+\r
+        for (int i = 0; i < ksizes_num; ++i)\r
+        {\r
+            ts->printf(CvTS::LOG, "\nksize = %d\n", ksizes[i]);\r
+\r
+            Mat cpudst;\r
+            cv::Sobel(img, cpudst, -1, dx, dy, ksizes[i]);\r
+\r
+            GpuMat gpu1(img);\r
+            GpuMat gpudst;\r
+            cv::gpu::Sobel(gpu1, gpudst, -1, dx, dy, ksizes[i]);\r
+\r
+            if (CheckNorm(cpudst, gpudst, Size(ksizes[i], ksizes[i])) != CvTS::OK)\r
+                test_res = CvTS::FAIL_GENERIC;\r
+        }\r
+\r
+        return test_res;\r
+    }\r
+};\r
+\r
+////////////////////////////////////////////////////////////////////////////////\r
+// Scharr\r
+struct CV_GpuNppImageScharrTest : public CV_GpuNppFilterTest\r
+{\r
+    CV_GpuNppImageScharrTest() : CV_GpuNppFilterTest( "GPU-NppImageScharr", "Scharr" ) {}\r
+\r
+    int test(const Mat& img)\r
+    {\r
+        int dx = 1, dy = 0;\r
+\r
+        Mat cpudst;\r
+        cv::Scharr(img, cpudst, -1, dx, dy);\r
+\r
+        GpuMat gpu1(img);\r
+        GpuMat gpudst;\r
+        cv::gpu::Scharr(gpu1, gpudst, -1, dx, dy);\r
+\r
+        return CheckNorm(cpudst, gpudst, Size(3, 3));\r
+    }\r
+};\r
+\r
+\r
+////////////////////////////////////////////////////////////////////////////////\r
+// GaussianBlur\r
+struct CV_GpuNppImageGaussianBlurTest : public CV_GpuNppFilterTest\r
+{\r
+    CV_GpuNppImageGaussianBlurTest() : CV_GpuNppFilterTest( "GPU-NppImageGaussianBlur", "GaussianBlur" ) {}\r
+\r
+    int test(const Mat& img)\r
+    {\r
+        int ksizes[] = {3, 5, 7};\r
+        int ksizes_num = sizeof(ksizes) / sizeof(int);\r
+\r
+        int test_res = CvTS::OK;\r
+\r
+        const double sigma1 = 3.0;\r
+\r
+        for (int i = 0; i < ksizes_num; ++i)\r
+        {\r
+            for (int j = 0; j < ksizes_num; ++j)\r
+            {\r
+                cv::Size ksize(ksizes[i], ksizes[j]);\r
+\r
+                ts->printf(CvTS::LOG, "\nksize = (%dx%d)\n", ksizes[i], ksizes[j]);\r
+\r
+                Mat cpudst;\r
+                cv::GaussianBlur(img, cpudst, ksize, sigma1);\r
+\r
+                GpuMat gpu1(img);\r
+                GpuMat gpudst;\r
+                cv::gpu::GaussianBlur(gpu1, gpudst, ksize, sigma1);\r
+\r
+                if (CheckNorm(cpudst, gpudst, ksize) != CvTS::OK)\r
+                    test_res = CvTS::FAIL_GENERIC;\r
+            }\r
+        }\r
+\r
+        return test_res;\r
+    }\r
+};\r
+\r
+////////////////////////////////////////////////////////////////////////////////\r
+// Laplacian\r
+struct CV_GpuNppImageLaplacianTest : public CV_GpuNppFilterTest\r
+{\r
+    CV_GpuNppImageLaplacianTest() : CV_GpuNppFilterTest( "GPU-NppImageLaplacian", "Laplacian" ) {}\r
+\r
+    int test(const Mat& img)\r
+    {\r
+        int ksizes[] = {1, 3};\r
+        int ksizes_num = sizeof(ksizes) / sizeof(int);\r
+\r
+        int test_res = CvTS::OK;\r
+\r
+        for (int i = 0; i < ksizes_num; ++i)\r
+        {\r
+            ts->printf(CvTS::LOG, "\nksize = %d\n", ksizes[i]);\r
+\r
+            Mat cpudst;\r
+            cv::Laplacian(img, cpudst, -1, ksizes[i]);\r
+\r
+            GpuMat gpu1(img);\r
+            GpuMat gpudst;\r
+            cv::gpu::Laplacian(gpu1, gpudst, -1, ksizes[i]);\r
+\r
+            if (CheckNorm(cpudst, gpudst, Size(3, 3)) != CvTS::OK)\r
+                test_res = CvTS::FAIL_GENERIC;\r
+        }\r
+\r
+        return test_res;\r
+    }\r
+};\r
+\r
+////////////////////////////////////////////////////////////////////////////////\r
+// Erode\r
+class CV_GpuErodeTest : public CV_GpuNppFilterTest\r
+{\r
+public:\r
+    CV_GpuErodeTest() : CV_GpuNppFilterTest( "GPU-NppErode", "erode" ) {} \r
+\r
+protected:\r
+       virtual int test(const Mat& img)\r
+    {\r
+        Mat kernel(Mat::ones(3, 3, CV_8U));\r
+\r
+           cv::Mat cpuRes;\r
+        cv::erode(img, cpuRes, kernel);\r
+\r
+           GpuMat gpuRes;\r
+        cv::gpu::erode(GpuMat(img), gpuRes, kernel);\r
+\r
+           return CheckNorm(cpuRes, gpuRes, Size(3, 3));\r
+    }\r
+};\r
+\r
+////////////////////////////////////////////////////////////////////////////////\r
+// Dilate\r
+class CV_GpuDilateTest : public CV_GpuNppFilterTest\r
+{\r
+public:\r
+    CV_GpuDilateTest() : CV_GpuNppFilterTest( "GPU-NppDilate", "dilate" ) {} \r
+\r
+protected:\r
+       virtual int test(const Mat& img)\r
+    {\r
+        Mat kernel(Mat::ones(3, 3, CV_8U));\r
+\r
+           cv::Mat cpuRes;\r
+        cv::dilate(img, cpuRes, kernel);\r
+\r
+           GpuMat gpuRes;\r
+        cv::gpu::dilate(GpuMat(img), gpuRes, kernel);\r
+       \r
+           return CheckNorm(cpuRes, gpuRes, Size(3, 3));\r
+    }\r
+};\r
+\r
+////////////////////////////////////////////////////////////////////////////////\r
+// MorphologyEx\r
+class CV_GpuMorphExTest : public CV_GpuNppFilterTest\r
+{\r
+public:\r
+    CV_GpuMorphExTest() : CV_GpuNppFilterTest( "GPU-NppMorphologyEx", "morphologyEx" ) {} \r
+\r
+protected:\r
+       virtual int test(const Mat& img)\r
+    {\r
+        static int ops[] = { MORPH_OPEN, CV_MOP_CLOSE, CV_MOP_GRADIENT, CV_MOP_TOPHAT, CV_MOP_BLACKHAT};\r
+        const char *names[] = { "MORPH_OPEN", "CV_MOP_CLOSE", "CV_MOP_GRADIENT", "CV_MOP_TOPHAT", "CV_MOP_BLACKHAT"};\r
+        int num = sizeof(ops)/sizeof(ops[0]);\r
+\r
+        GpuMat kernel(Mat::ones(3, 3, CV_8U));\r
+\r
+        int res = CvTS::OK;\r
+\r
+        for(int i = 0; i < num; ++i)\r
+        {\r
+            ts->printf(CvTS::LOG, "Tesing %s\n", names[i]);\r
+\r
+               cv::Mat cpuRes;\r
+            cv::morphologyEx(img, cpuRes, ops[i], kernel);\r
+\r
+               GpuMat gpuRes;\r
+            cv::gpu::morphologyEx(GpuMat(img), gpuRes, ops[i], kernel);\r
+\r
+            if (CvTS::OK != CheckNorm(cpuRes, gpuRes, Size(3, 3)))\r
+                res = CvTS::FAIL_GENERIC;\r
+        }\r
+        return res;\r
+    }\r
+};\r
+\r
+\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////////////\r
+/////////////////// tests registration  /////////////////////////////////////\r
+/////////////////////////////////////////////////////////////////////////////\r
+\r
+CV_GpuNppImageBlurTest CV_GpuNppImageBlur_test;\r
+CV_GpuNppImageSobelTest CV_GpuNppImageSobel_test;\r
+CV_GpuNppImageScharrTest CV_GpuNppImageScharr_test;\r
+CV_GpuNppImageGaussianBlurTest CV_GpuNppImageGaussianBlur_test;\r
+CV_GpuNppImageLaplacianTest CV_GpuNppImageLaplacian_test;\r
+CV_GpuErodeTest CV_GpuErode_test;\r
+CV_GpuDilateTest CV_GpuDilate_test;\r
+CV_GpuMorphExTest CV_GpuMorphEx_test;
\ No newline at end of file
index 5012c4b..3d547cf 100644 (file)
@@ -45,25 +45,27 @@ CvTS test_system;
 
 const char* blacklist[] =
 {    
-    "GPU-NppImageSum",              // crash
     "GPU-MatOperatorAsyncCall",     // crash
-    //"GPU-NppErode",                 // different border interpolation
-    //"GPU-NppMorphologyEx",          // different border interpolation
+
+    "GPU-NppImageSum",              // crash, probably npp bug
+    "GPU-NppImageMinNax",           // npp bug - don't find min/max near right border
     //"GPU-NppImageDivide",           // different round mode
     //"GPU-NppImageMeanStdDev",       // different precision
-    //"GPU-NppImageMinNax",           // npp bug - don't find min/max near right border
-    //"GPU-NppImageResize",           // different precision in interpolation
-    //"GPU-NppImageWarpAffine",       // different precision in interpolation
-    //"GPU-NppImageWarpPerspective",  // different precision in interpolation
-    //"GPU-NppImageIntegral",         // different precision
-    //"GPU-NppImageBlur",             // different precision
     //"GPU-NppImageExp",              // different precision
     //"GPU-NppImageLog",              // different precision
     //"GPU-NppImageMagnitude",        // different precision
-    //"GPU-NppImageSumWindow",        // different border interpolation
-    //"GPU-NppImageSobel",            // ???
-    //"GPU-NppImageGaussianBlur",     // different border interpolation
+    
     "GPU-NppImageCanny",            // NPP_TEXTURE_BIND_ERROR
+    //"GPU-NppImageResize",           // different precision
+    //"GPU-NppImageWarpAffine",       // different precision
+    //"GPU-NppImageWarpPerspective",  // different precision
+    //"GPU-NppImageIntegral",         // different precision
+    
+    //"GPU-NppImageSobel",            // ???
+    //"GPU-NppImageScharr",           // ???
+    
+    //"GPU-NppImageGaussianBlur",     // different precision    
+    //"GPU-NppMorphologyEx",          // different precision?
     0
 };
 
index 7b07312..b199acb 100644 (file)
@@ -414,167 +414,6 @@ struct CV_GpuNppImageIntegralTest : public CV_GpuImageProcTest
 };\r
 \r
 ////////////////////////////////////////////////////////////////////////////////\r
-// blur\r
-struct CV_GpuNppImageBlurTest : public CV_GpuImageProcTest\r
-{\r
-    CV_GpuNppImageBlurTest() : CV_GpuImageProcTest( "GPU-NppImageBlur", "blur" ) {}\r
-\r
-    int test(const Mat& img)\r
-    {\r
-        if (img.type() != CV_8UC1 && img.type() != CV_8UC4)\r
-        {\r
-            ts->printf(CvTS::LOG, "\nUnsupported type\n");\r
-            return CvTS::OK;\r
-        }\r
-\r
-        int ksizes[] = {3, 5, 7};\r
-        int ksizes_num = sizeof(ksizes) / sizeof(int);\r
-\r
-        int test_res = CvTS::OK;\r
-\r
-        for (int i = 0; i < ksizes_num; ++i)\r
-        {\r
-            ts->printf(CvTS::LOG, "\nksize = %d\n", ksizes[i]);\r
-\r
-            Mat cpudst;\r
-            cv::blur(img, cpudst, Size(ksizes[i], ksizes[i]));\r
-\r
-            GpuMat gpu1(img);\r
-            GpuMat gpudst;\r
-            cv::gpu::blur(gpu1, gpudst, Size(ksizes[i], ksizes[i]));\r
-\r
-            if (CheckNorm(cpudst, gpudst) != CvTS::OK)\r
-                test_res = CvTS::FAIL_GENERIC;\r
-        }\r
-\r
-        return test_res;\r
-    }\r
-};\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-// sumWindow\r
-struct CV_GpuNppImageSumWindowTest : public CV_GpuImageProcTest\r
-{\r
-    CV_GpuNppImageSumWindowTest() : CV_GpuImageProcTest( "GPU-NppImageSumWindow", "sumWindow" ) {}\r
-\r
-    int test(const Mat& img)\r
-    {\r
-        if (img.type() != CV_8UC1)\r
-        {\r
-            ts->printf(CvTS::LOG, "\nUnsupported type\n");\r
-            return CvTS::OK;\r
-        }\r
-\r
-        int ksizes[] = {3, 5, 7};\r
-        int ksizes_num = sizeof(ksizes) / sizeof(int);\r
-\r
-        int test_res = CvTS::OK;        \r
-\r
-        for (int i = 0; i < ksizes_num; ++i)\r
-        {\r
-            ts->printf(CvTS::LOG, "\nksize = %d\n", ksizes[i]);\r
-\r
-            Mat cpudst(img.size(), CV_64FC1, Scalar());\r
-            cv::Ptr<cv::BaseRowFilter> ft = cv::getRowSumFilter(CV_8UC1, CV_64FC1, ksizes[i], 0);\r
-            for (int y = 0; y < img.rows; ++y)\r
-                (*ft)(img.ptr(y), cpudst.ptr(y), img.cols, 1);\r
-            cpudst.convertTo(cpudst, CV_32F);\r
-\r
-            GpuMat gpu1(img);\r
-            GpuMat gpudst;\r
-            cv::gpu::sumWindowRow(gpu1, gpudst, ksizes[i], 0);\r
-\r
-            if (CheckNorm(cpudst, gpudst) != CvTS::OK)\r
-                test_res = CvTS::FAIL_GENERIC;\r
-        }\r
-\r
-        return test_res;\r
-    }\r
-};\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-// Sobel\r
-struct CV_GpuNppImageSobelTest : public CV_GpuImageProcTest\r
-{\r
-    CV_GpuNppImageSobelTest() : CV_GpuImageProcTest( "GPU-NppImageSobel", "Sobel" ) {}\r
-\r
-    int test(const Mat& img)\r
-    {\r
-        if (img.type() != CV_8UC1 && img.type() != CV_8UC4)\r
-        {\r
-            ts->printf(CvTS::LOG, "\nUnsupported type\n");\r
-            return CvTS::OK;\r
-        }\r
-\r
-        int ksizes[] = {3, 5, 7};\r
-        int ksizes_num = sizeof(ksizes) / sizeof(int);\r
-\r
-        int dx = 1, dy = 0;\r
-\r
-        int test_res = CvTS::OK;\r
-\r
-        for (int i = 0; i < ksizes_num; ++i)\r
-        {\r
-            ts->printf(CvTS::LOG, "\nksize = %d\n", ksizes[i]);\r
-\r
-            Mat cpudst;\r
-            cv::Sobel(img, cpudst, -1, dx, dy, ksizes[i]);\r
-\r
-            GpuMat gpu1(img);\r
-            GpuMat gpudst;\r
-            cv::gpu::Sobel(gpu1, gpudst, -1, dx, dy, ksizes[i]);\r
-\r
-            if (CheckNorm(cpudst, gpudst) != CvTS::OK)\r
-                test_res = CvTS::FAIL_GENERIC;\r
-        }\r
-\r
-        return test_res;\r
-    }\r
-};\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-// GaussianBlur\r
-struct CV_GpuNppImageGaussianBlurTest : public CV_GpuImageProcTest\r
-{\r
-    CV_GpuNppImageGaussianBlurTest() : CV_GpuImageProcTest( "GPU-NppImageGaussianBlur", "GaussianBlur" ) {}\r
-\r
-    int test(const Mat& img)\r
-    {\r
-        if (img.type() != CV_8UC1 && img.type() != CV_8UC4)\r
-        {\r
-            ts->printf(CvTS::LOG, "\nUnsupported type\n");\r
-            return CvTS::OK;\r
-        }\r
-\r
-        int ksizes[] = {3, 5, 7};\r
-        int ksizes_num = sizeof(ksizes) / sizeof(int);\r
-\r
-        int test_res = CvTS::OK;\r
-\r
-        const double sigma1 = 3.0;\r
-\r
-        for (int i = 0; i < ksizes_num; ++i)\r
-        {\r
-            for (int j = 0; j < ksizes_num; ++j)\r
-            {\r
-                ts->printf(CvTS::LOG, "\nksize = (%dx%d)\n", ksizes[i], ksizes[j]);\r
-\r
-                Mat cpudst;\r
-                cv::GaussianBlur(img, cpudst, cv::Size(ksizes[i], ksizes[j]), sigma1);\r
-\r
-                GpuMat gpu1(img);\r
-                GpuMat gpudst;\r
-                cv::gpu::GaussianBlur(gpu1, gpudst, cv::Size(ksizes[i], ksizes[j]), sigma1);\r
-                if (CheckNorm(cpudst, gpudst) != CvTS::OK)\r
-                    test_res = CvTS::FAIL_GENERIC;\r
-            }\r
-        }\r
-\r
-        return test_res;\r
-    }\r
-};\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
 // Canny\r
 struct CV_GpuNppImageCannyTest : public CV_GpuImageProcTest\r
 {\r
@@ -705,9 +544,5 @@ CV_GpuNppImageCopyMakeBorderTest CV_GpuNppImageCopyMakeBorder_test;
 CV_GpuNppImageWarpAffineTest CV_GpuNppImageWarpAffine_test;\r
 CV_GpuNppImageWarpPerspectiveTest CV_GpuNppImageWarpPerspective_test;\r
 CV_GpuNppImageIntegralTest CV_GpuNppImageIntegral_test;\r
-CV_GpuNppImageBlurTest CV_GpuNppImageBlur_test;\r
-CV_GpuNppImageSumWindowTest CV_GpuNppImageSumWindow_test;\r
-CV_GpuNppImageSobelTest CV_GpuNppImageSobel_test;\r
-CV_GpuNppImageGaussianBlurTest CV_GpuNppImageGaussianBlur_test;\r
 CV_GpuNppImageCannyTest CV_GpuNppImageCanny_test;\r
 CV_GpuCvtColorTest CV_GpuCvtColor_test;
\ No newline at end of file
diff --git a/tests/gpu/src/morf_filters.cpp b/tests/gpu/src/morf_filters.cpp
deleted file mode 100644 (file)
index f27bc05..0000000
+++ /dev/null
@@ -1,219 +0,0 @@
-/*M///////////////////////////////////////////////////////////////////////////////////////
-//
-//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
-//
-//  By downloading, copying, installing or using the software you agree to this license.
-//  If you do not agree to this license, do not download, install,
-//  copy or use the software.
-//
-//
-//                        Intel License Agreement
-//                For Open Source Computer Vision Library
-//
-// Copyright (C) 2000, Intel Corporation, all rights reserved.
-// Third party copyrights are property of their respective owners.
-//
-// Redistribution and use in source and binary forms, with or without modification,
-// are permitted provided that the following conditions are met:
-//
-//   * Redistribution's of source code must retain the above copyright notice,
-//     this list of conditions and the following disclaimer.
-//
-//   * Redistribution's in binary form must reproduce the above copyright notice,
-//     this list of conditions and the following disclaimer in the documentation
-//     and/or other materials provided with the distribution.
-//
-//   * The name of Intel Corporation may not be used to endorse or promote products
-//     derived from this software without specific prior written permission.
-//
-// This software is provided by the copyright holders and contributors "as is" and
-// any express or implied warranties, including, but not limited to, the implied
-// warranties of merchantability and fitness for a particular purpose are disclaimed.
-// In no event shall the Intel Corporation or contributors be liable for any direct,
-// indirect, incidental, special, exemplary, or consequential damages
-// (including, but not limited to, procurement of substitute goods or services;
-// loss of use, data, or profits; or business interruption) however caused
-// and on any theory of liability, whether in contract, strict liability,
-// or tort (including negligence or otherwise) arising in any way out of
-// the use of this software, even if advised of the possibility of such damage.
-//
-//M*/
-
-#include <iostream>
-#include <cmath>
-#include <limits>
-#include "gputest.hpp"
-#include "opencv2/imgproc/imgproc.hpp"
-#include "opencv2/highgui/highgui.hpp"
-
-using namespace cv;
-using namespace std;
-using namespace gpu;
-
-class CV_GpuNppMorphogyTest : public CvTest
-{
-public:
-    CV_GpuNppMorphogyTest(const char* test_name, const char* test_funcs) : CvTest(test_name, test_funcs) {}
-    virtual ~CV_GpuNppMorphogyTest() {}
-
-protected:
-    void run(int);
-    virtual int test(const Mat& img) = 0;
-    
-    int test8UC1(const Mat& img)
-    {
-        cv::Mat img_C1;
-        cvtColor(img, img_C1, CV_BGR2GRAY);
-        return test(img_C1);
-    }
-
-    int test8UC4(const Mat& img)
-    {
-        cv::Mat img_C4;
-        cvtColor(img, img_C4, CV_BGR2BGRA);    
-        return test(img_C4);
-    }
-        
-    int CheckNorm(const Mat& m1, const Mat& m2)
-    {
-        double res = norm(m1, m2, NORM_INF);
-
-        if (res < std::numeric_limits<double>::epsilon())
-            return CvTS::OK;
-        
-        ts->printf(CvTS::LOG, "\nNorm: %f\n", res);
-        return CvTS::FAIL_GENERIC;
-    }
-};
-
-void CV_GpuNppMorphogyTest::run( int )
-{    
-    cv::Mat img = cv::imread(std::string(ts->get_data_path()) + "stereobp/aloe-L.png");
-    
-    if (img.empty())
-    {
-        ts->set_failed_test_info(CvTS::FAIL_MISSING_TEST_DATA);
-        return;
-    }
-
-    try
-    {
-        //run tests
-        int testResult = test8UC1(img);
-        if (testResult != CvTS::OK)
-        {
-            ts->set_failed_test_info(testResult);
-            return;
-        }
-
-        testResult = test8UC4(img);
-        if (testResult != CvTS::OK)
-        {
-            ts->set_failed_test_info(testResult);
-            return;
-        }    
-    }
-    catch(const cv::Exception& e)
-    {
-        if (!check_and_treat_gpu_exception(e, ts))
-            throw;
-        return;
-    }
-
-    ts->set_failed_test_info(CvTS::OK);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Erode
-class CV_GpuErodeTest : public CV_GpuNppMorphogyTest
-{
-public:
-    CV_GpuErodeTest() : CV_GpuNppMorphogyTest( "GPU-NppErode", "erode" ) {} 
-
-protected:
-       virtual int test(const Mat& img)
-    {
-        GpuMat kernel(Mat::ones(3, 3, CV_8U));
-        Point anchor(0, 0);
-        int iters = 1;
-
-           cv::Mat cpuRes, cpuRes1;
-        cv::erode(img, cpuRes, kernel, anchor, iters);
-
-           GpuMat gpuRes;
-        cv::gpu::erode(GpuMat(img), gpuRes, kernel, anchor, iters);
-       
-           return CheckNorm(cpuRes, gpuRes);
-    }
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// Dilate
-class CV_GpuDilateTest : public CV_GpuNppMorphogyTest
-{
-public:
-    CV_GpuDilateTest() : CV_GpuNppMorphogyTest( "GPU-NppDilate", "dilate" ) {} 
-
-protected:
-       virtual int test(const Mat& img)
-    {
-        GpuMat kernel(Mat::ones(3, 3, CV_8U));
-        Point anchor(0, 0);
-        int iters = 1;
-
-           cv::Mat cpuRes, cpuRes1;
-        cv::dilate(img, cpuRes, kernel, anchor, iters);
-
-           GpuMat gpuRes, gpuRes1;
-        cv::gpu::dilate(GpuMat(img), gpuRes, kernel, anchor, iters);
-       
-           return CheckNorm(cpuRes, gpuRes);
-    }
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// Dilate
-class CV_GpuMorphExTest : public CV_GpuNppMorphogyTest
-{
-public:
-    CV_GpuMorphExTest() : CV_GpuNppMorphogyTest( "GPU-NppMorphologyEx", "dmorphologyExilate" ) {} 
-
-protected:
-       virtual int test(const Mat& img)
-    {
-        static int ops[] = { MORPH_OPEN, CV_MOP_CLOSE, CV_MOP_GRADIENT, CV_MOP_TOPHAT, CV_MOP_BLACKHAT};
-        const char *names[] = { "MORPH_OPEN", "CV_MOP_CLOSE", "CV_MOP_GRADIENT", "CV_MOP_TOPHAT", "CV_MOP_BLACKHAT"};
-        int num = sizeof(ops)/sizeof(ops[0]);
-
-        GpuMat kernel(Mat::ones(3, 3, CV_8U));
-        Point anchor(0, 0);
-        int iters = 1;
-
-        for(int i = 0; i < num; ++i)
-        {
-            ts->printf(CvTS::LOG, "Tesing %s\n", names[i]);
-
-               cv::Mat cpuRes;
-            cv::morphologyEx(img, cpuRes, ops[i], kernel, anchor, iters);
-
-               GpuMat gpuRes;
-            cv::gpu::morphologyEx(GpuMat(img), gpuRes, ops[i], kernel, anchor, iters);
-       
-               int res = CheckNorm(cpuRes, gpuRes);
-            if (CvTS::OK != res)
-                return res;
-        }
-        return CvTS::OK;
-    }
-};
-
-
-
-
-/////////////////////////////////////////////////////////////////////////////
-/////////////////// tests registration  /////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////
-
-CV_GpuErodeTest CV_GpuErode_test;
-CV_GpuDilateTest CV_GpuDilate_test;
-CV_GpuMorphExTest CV_GpuMorphEx_test;
\ No newline at end of file