\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
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
//! 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
\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
}\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
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
--- /dev/null
+/*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