From f6895e773897a26ba8da3b26486399a0b6d60565 Mon Sep 17 00:00:00 2001 From: Vladislav Vinogradov Date: Tue, 12 Oct 2010 08:33:06 +0000 Subject: [PATCH] fixed gpu filters (deriv filter and source roi calculation) --- modules/gpu/include/opencv2/gpu/gpu.hpp | 6 +- modules/gpu/src/filtering_npp.cpp | 120 ++++++++++++++++-------- tests/gpu/src/filters.cpp | 2 +- tests/gpu/src/gputest_main.cpp | 6 +- 4 files changed, 86 insertions(+), 48 deletions(-) diff --git a/modules/gpu/include/opencv2/gpu/gpu.hpp b/modules/gpu/include/opencv2/gpu/gpu.hpp index 041f6759c4..b8ee807e7c 100644 --- a/modules/gpu/include/opencv2/gpu/gpu.hpp +++ b/modules/gpu/include/opencv2/gpu/gpu.hpp @@ -596,7 +596,7 @@ namespace cv //! returns the separable filter engine with the specified filters CV_EXPORTS Ptr createSeparableFilter_GPU(const Ptr& rowFilter, - const Ptr& columnFilter); + const Ptr& columnFilter, bool rowFilterFirst = true); //! returns horizontal 1D box filter //! supports only CV_8UC1 source type and CV_32FC1 sum type @@ -645,7 +645,7 @@ namespace cv //! returns the separable linear filter engine CV_EXPORTS Ptr createSeparableLinearFilter_GPU(int srcType, int dstType, const Mat& rowKernel, - const Mat& columnKernel, const Point& anchor = Point(-1,-1)); + const Mat& columnKernel, const Point& anchor = Point(-1,-1), bool rowFilterFirst = true); //! returns filter engine for the generalized Sobel operator CV_EXPORTS Ptr createDerivFilter_GPU(int srcType, int dstType, int dx, int dy, int ksize); @@ -680,7 +680,7 @@ namespace cv //! applies separable 2D linear filter to the image CV_EXPORTS void sepFilter2D(const GpuMat& src, GpuMat& dst, int ddepth, const Mat& kernelX, const Mat& kernelY, - Point anchor = Point(-1,-1)); + Point anchor = Point(-1,-1), bool rowFilterFirst = true); //! applies generalized Sobel operator to the image CV_EXPORTS void Sobel(const GpuMat& src, GpuMat& dst, int ddepth, int dx, int dy, int ksize = 3, double scale = 1); diff --git a/modules/gpu/src/filtering_npp.cpp b/modules/gpu/src/filtering_npp.cpp index 97f08a7606..a9aceb50ef 100644 --- a/modules/gpu/src/filtering_npp.cpp +++ b/modules/gpu/src/filtering_npp.cpp @@ -49,7 +49,7 @@ using namespace cv::gpu; #if !defined (HAVE_CUDA) Ptr cv::gpu::createFilter2D_GPU(const Ptr) { throw_nogpu(); return Ptr(0); } -Ptr cv::gpu::createSeparableFilter_GPU(const Ptr&, const Ptr&) { throw_nogpu(); return Ptr(0); } +Ptr cv::gpu::createSeparableFilter_GPU(const Ptr&, const Ptr&, bool) { throw_nogpu(); return Ptr(0); } Ptr cv::gpu::getRowSumFilter_GPU(int, int, int, int) { throw_nogpu(); return Ptr(0); } Ptr cv::gpu::getColumnSumFilter_GPU(int, int, int, int) { throw_nogpu(); return Ptr(0); } Ptr cv::gpu::getBoxFilter_GPU(int, int, const Size&, Point) { throw_nogpu(); return Ptr(0); } @@ -60,7 +60,7 @@ Ptr cv::gpu::getLinearFilter_GPU(int, int, const GpuMat&, const Ptr cv::gpu::createLinearFilter_GPU(int, int, const Mat&, const Point&) { throw_nogpu(); return Ptr(0); } Ptr cv::gpu::getLinearRowFilter_GPU(int, int, const GpuMat&, int, int) { throw_nogpu(); return Ptr(0); } Ptr cv::gpu::getLinearColumnFilter_GPU(int, int, const GpuMat&, int, int) { throw_nogpu(); return Ptr(0); } -Ptr cv::gpu::createSeparableLinearFilter_GPU(int, int, const Mat&, const Mat&, const Point&) { throw_nogpu(); return Ptr(0); } +Ptr cv::gpu::createSeparableLinearFilter_GPU(int, int, const Mat&, const Mat&, const Point&, bool) { throw_nogpu(); return Ptr(0); } Ptr cv::gpu::createDerivFilter_GPU(int, int, int, int, int) { throw_nogpu(); return Ptr(0); } Ptr cv::gpu::createGaussianFilter_GPU(int, Size, double, double) { throw_nogpu(); return Ptr(0); } Ptr cv::gpu::getMaxFilter_GPU(int, int, const Size&, Point) { throw_nogpu(); return Ptr(0); } @@ -71,7 +71,7 @@ void cv::gpu::erode( const GpuMat&, GpuMat&, const Mat&, Point, int) { throw_nog void cv::gpu::dilate( const GpuMat&, GpuMat&, const Mat&, Point, int) { throw_nogpu(); } void cv::gpu::morphologyEx( const GpuMat&, GpuMat&, int, const Mat&, Point, int) { throw_nogpu(); } void cv::gpu::filter2D(const GpuMat&, GpuMat&, int, const Mat&, Point) { throw_nogpu(); } -void cv::gpu::sepFilter2D(const GpuMat&, GpuMat&, int, const Mat&, const Mat&, Point) { throw_nogpu(); } +void cv::gpu::sepFilter2D(const GpuMat&, GpuMat&, int, const Mat&, const Mat&, Point, bool) { throw_nogpu(); } void cv::gpu::Sobel(const GpuMat&, GpuMat&, int, int, int, int, double) { throw_nogpu(); } void cv::gpu::Scharr(const GpuMat&, GpuMat&, int, int, int, double) { throw_nogpu(); } void cv::gpu::GaussianBlur(const GpuMat&, GpuMat&, Size, double, double) { throw_nogpu(); } @@ -95,10 +95,10 @@ namespace normalizeAnchor(anchor.y, ksize.height); } - inline void normalizeROI(Rect& roi, const Size& ksize, const Size& src_size) + inline void normalizeROI(Rect& roi, const Size& ksize, const Point& anchor, const Size& src_size) { if (roi == Rect(0,0,-1,-1)) - roi = Rect(ksize.width, ksize.height, src_size.width - 2 * ksize.width, src_size.height - 2 * ksize.height); + roi = Rect(anchor.x, anchor.y, src_size.width - ksize.width, src_size.height - ksize.height); CV_Assert(roi.x >= 0 && roi.y >= 0 && roi.width <= src_size.width && roi.height <= src_size.height); } @@ -140,8 +140,9 @@ namespace Size src_size = src.size(); dst.create(src_size, src.type()); + dst = Scalar(0.0); - normalizeROI(roi, filter2D->ksize, src_size); + normalizeROI(roi, filter2D->ksize, filter2D->anchor, src_size); GpuMat srcROI = src(roi); GpuMat dstROI = dst(roi); @@ -163,13 +164,33 @@ Ptr cv::gpu::createFilter2D_GPU(const Ptr filt namespace { - class SeparableFilterEngine_GPU : public FilterEngine_GPU + struct RowColumnFilterApply + { + void operator()(Ptr& rowFilter, Ptr& columnFilter, + GpuMat& srcROI, GpuMat& dstROI, GpuMat& dstBufROI) + { + (*rowFilter)(srcROI, dstBufROI); + (*columnFilter)(dstBufROI, dstROI); + } + }; + struct ColumnRowFilterApply + { + void operator()(Ptr& rowFilter, Ptr& columnFilter, + GpuMat& srcROI, GpuMat& dstROI, GpuMat& dstBufROI) + { + (*columnFilter)(srcROI, dstBufROI); + (*rowFilter)(dstBufROI, dstROI); + } + }; + class SeparableFilterEngine_GPU_base : public FilterEngine_GPU { public: - SeparableFilterEngine_GPU(const Ptr& rowFilter_, const Ptr& columnFilter_) : + SeparableFilterEngine_GPU_base(const Ptr& rowFilter_, + const Ptr& columnFilter_) : rowFilter(rowFilter_), columnFilter(columnFilter_) { ksize = Size(rowFilter->ksize, columnFilter->ksize); + anchor = Point(rowFilter->anchor, columnFilter->anchor); } virtual void apply(const GpuMat& src, GpuMat& dst, Rect roi = Rect(0,0,-1,-1)) @@ -178,29 +199,52 @@ namespace int src_type = src.type(); dst.create(src_size, src_type); + dst = Scalar(0.0); dstBuf.create(src_size, src_type); + dstBuf = Scalar(0.0); - normalizeROI(roi, ksize, src_size); - - GpuMat srcROI = src(roi); - GpuMat dstROI = dst(roi); - GpuMat dstBufROI = dstBuf(roi); + normalizeROI(roi, ksize, anchor, src_size); - (*rowFilter)(srcROI, dstBufROI); - (*columnFilter)(dstBufROI, dstROI); + srcROI = src(roi); + dstROI = dst(roi); + dstBufROI = dstBuf(roi); } Ptr rowFilter; Ptr columnFilter; Size ksize; + Point anchor; GpuMat dstBuf; + GpuMat srcROI; + GpuMat dstROI; + GpuMat dstBufROI; + }; + template + class SeparableFilterEngine_GPU : public SeparableFilterEngine_GPU_base + { + public: + SeparableFilterEngine_GPU(const Ptr& rowFilter_, + const Ptr& columnFilter_, FA fa_) : + SeparableFilterEngine_GPU_base(rowFilter_, columnFilter_), fa(fa_) + { + } + + virtual void apply(const GpuMat& src, GpuMat& dst, Rect roi = Rect(0,0,-1,-1)) + { + SeparableFilterEngine_GPU_base::apply(src, dst, roi); + fa(rowFilter, columnFilter, srcROI, dstROI, dstBufROI); + } + + FA fa; }; } Ptr cv::gpu::createSeparableFilter_GPU(const Ptr& rowFilter, - const Ptr& columnFilter) + const Ptr& columnFilter, bool rowFilterFirst) { - return Ptr(new SeparableFilterEngine_GPU(rowFilter, columnFilter)); + if (rowFilterFirst) + return Ptr(new SeparableFilterEngine_GPU(rowFilter, columnFilter, RowColumnFilterApply())); + return Ptr(new SeparableFilterEngine_GPU(rowFilter, columnFilter, ColumnRowFilterApply())); } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -382,18 +426,18 @@ namespace virtual void apply(const GpuMat& src, GpuMat& dst, Rect roi = Rect(0,0,-1,-1)) { if (iters > 1) - dstBuf.create(src.size(), src.type()); + morfBuf.create(src.size(), src.type()); Filter2DEngine_GPU::apply(src, dst); for(int i = 1; i < iters; ++i) { - dst.swap(dstBuf); - Filter2DEngine_GPU::apply(dst, dst); + dst.swap(morfBuf); + Filter2DEngine_GPU::apply(morfBuf, dst); } } int iters; - GpuMat dstBuf; + GpuMat morfBuf; }; } @@ -468,12 +512,12 @@ void cv::gpu::morphologyEx( const GpuMat& src, GpuMat& dst, int op, const Mat& k case MORPH_ERODE: erode( src, dst, kernel, anchor, iterations); break; case MORPH_DILATE: dilate( src, dst, kernel, anchor, iterations); break; case MORPH_OPEN: - erode( src, dst, kernel, anchor, iterations); - dilate( dst, dst, kernel, anchor, iterations); + erode( src, temp, kernel, anchor, iterations); + dilate( temp, dst, kernel, anchor, iterations); break; case CV_MOP_CLOSE: - dilate( src, dst, kernel, anchor, iterations); - erode( dst, dst, kernel, anchor, iterations); + dilate( src, temp, kernel, anchor, iterations); + erode( temp, dst, kernel, anchor, iterations); break; case CV_MOP_GRADIENT: erode( src, temp, kernel, anchor, iterations); @@ -481,17 +525,13 @@ void cv::gpu::morphologyEx( const GpuMat& src, GpuMat& dst, int op, const Mat& k subtract(dst, temp, dst); break; case CV_MOP_TOPHAT: - if( src.data != dst.data ) - temp = dst; - erode( src, temp, kernel, anchor, iterations); - dilate( temp, temp, kernel, anchor, iterations); + erode( src, dst, kernel, anchor, iterations); + dilate( dst, temp, kernel, anchor, iterations); subtract(src, temp, dst); break; case CV_MOP_BLACKHAT: - if( src.data != dst.data ) - temp = dst; - dilate( src, temp, kernel, anchor, iterations); - erode( temp, temp, kernel, anchor, iterations); + dilate( src, dst, kernel, anchor, iterations); + erode( dst, temp, kernel, anchor, iterations); subtract(temp, src, dst); break; default: @@ -652,7 +692,7 @@ Ptr cv::gpu::getLinearColumnFilter_GPU(int bufType, int ds } Ptr cv::gpu::createSeparableLinearFilter_GPU(int srcType, int dstType, const Mat& rowKernel, const Mat& columnKernel, - const Point& anchor) + const Point& anchor, bool rowFilterFirst) { int sdepth = CV_MAT_DEPTH(srcType), ddepth = CV_MAT_DEPTH(dstType); int cn = CV_MAT_CN(srcType); @@ -667,17 +707,17 @@ Ptr cv::gpu::createSeparableLinearFilter_GPU(int srcType, int Ptr rowFilter = getLinearRowFilter_GPU(srcType, bufType, gpu_row_krnl, anchor.x, nRowDivisor); Ptr columnFilter = getLinearColumnFilter_GPU(bufType, dstType, gpu_col_krnl, anchor.y, nColDivisor); - return createSeparableFilter_GPU(rowFilter, columnFilter); + return createSeparableFilter_GPU(rowFilter, columnFilter, rowFilterFirst); } -void cv::gpu::sepFilter2D(const GpuMat& src, GpuMat& dst, int ddepth, const Mat& kernelX, const Mat& kernelY, Point anchor) +void cv::gpu::sepFilter2D(const GpuMat& src, GpuMat& dst, int ddepth, const Mat& kernelX, const Mat& kernelY, Point anchor, bool rowFilterFirst) { if( ddepth < 0 ) ddepth = src.depth(); dst.create(src.size(), CV_MAKETYPE(ddepth, src.channels())); - Ptr f = createSeparableLinearFilter_GPU(src.type(), dst.type(), kernelX, kernelY, anchor); + Ptr f = createSeparableLinearFilter_GPU(src.type(), dst.type(), kernelX, kernelY, anchor, rowFilterFirst); f->apply(src, dst); } @@ -688,7 +728,7 @@ Ptr cv::gpu::createDerivFilter_GPU(int srcType, int dstType, i { Mat kx, ky; getDerivKernels(kx, ky, dx, dy, ksize, false, CV_32F); - return createSeparableLinearFilter_GPU(srcType, dstType, kx, ky); + return createSeparableLinearFilter_GPU(srcType, dstType, kx, ky, Point(-1,-1), dx >= dy); } void cv::gpu::Sobel(const GpuMat& src, GpuMat& dst, int ddepth, int dx, int dy, int ksize, double scale) @@ -706,7 +746,7 @@ void cv::gpu::Sobel(const GpuMat& src, GpuMat& dst, int ddepth, int dx, int dy, ky *= scale; } - sepFilter2D(src, dst, ddepth, kx, ky, Point(-1,-1)); + sepFilter2D(src, dst, ddepth, kx, ky, Point(-1,-1), dx >= dy); } void cv::gpu::Scharr(const GpuMat& src, GpuMat& dst, int ddepth, int dx, int dy, double scale) @@ -724,7 +764,7 @@ void cv::gpu::Scharr(const GpuMat& src, GpuMat& dst, int ddepth, int dx, int dy, ky *= scale; } - sepFilter2D(src, dst, ddepth, kx, ky, Point(-1,-1)); + sepFilter2D(src, dst, ddepth, kx, ky, Point(-1,-1), dx >= dy); } void cv::gpu::Laplacian(const GpuMat& src, GpuMat& dst, int ddepth, int ksize, double scale) diff --git a/tests/gpu/src/filters.cpp b/tests/gpu/src/filters.cpp index b73d0529b5..1505da659a 100644 --- a/tests/gpu/src/filters.cpp +++ b/tests/gpu/src/filters.cpp @@ -359,7 +359,7 @@ protected: GpuMat gpuRes; cv::gpu::morphologyEx(GpuMat(img), gpuRes, ops[i], kernel); - if (CvTS::OK != CheckNorm(cpuRes, gpuRes, Size(3, 3))) + if (CvTS::OK != CheckNorm(cpuRes, gpuRes, Size(4, 4))) res = CvTS::FAIL_GENERIC; } return res; diff --git a/tests/gpu/src/gputest_main.cpp b/tests/gpu/src/gputest_main.cpp index 3d547cf570..ebcbf2c65e 100644 --- a/tests/gpu/src/gputest_main.cpp +++ b/tests/gpu/src/gputest_main.cpp @@ -62,10 +62,8 @@ const char* blacklist[] = //"GPU-NppImageIntegral", // different precision //"GPU-NppImageSobel", // ??? - //"GPU-NppImageScharr", // ??? - - //"GPU-NppImageGaussianBlur", // different precision - //"GPU-NppMorphologyEx", // different precision? + //"GPU-NppImageScharr", // ??? + //"GPU-NppImageGaussianBlur", // different precision 0 }; -- GitLab