diff --git a/modules/gpu/doc/per_element_operations.rst b/modules/gpu/doc/per_element_operations.rst index a59875e64..2670ba323 100644 --- a/modules/gpu/doc/per_element_operations.rst +++ b/modules/gpu/doc/per_element_operations.rst @@ -276,6 +276,8 @@ Compares elements of two matrices. .. ocv:function:: void gpu::compare( const GpuMat& a, const GpuMat& b, GpuMat& c, int cmpop, Stream& stream=Stream::Null() ) +.. ocv:function:: void gpu::compare(const GpuMat& a, Scalar sc, GpuMat& c, int cmpop, Stream& stream = Stream::Null()) + :param a: First source matrix. :param b: Second source matrix with the same size and type as ``a`` . diff --git a/modules/gpu/include/opencv2/gpu/gpu.hpp b/modules/gpu/include/opencv2/gpu/gpu.hpp index 7493d83b5..4eb339e7e 100644 --- a/modules/gpu/include/opencv2/gpu/gpu.hpp +++ b/modules/gpu/include/opencv2/gpu/gpu.hpp @@ -533,6 +533,7 @@ CV_EXPORTS void pow(const GpuMat& src, double power, GpuMat& dst, Stream& stream //! compares elements of two arrays (c = a b) CV_EXPORTS void compare(const GpuMat& a, const GpuMat& b, GpuMat& c, int cmpop, Stream& stream = Stream::Null()); +CV_EXPORTS void compare(const GpuMat& a, Scalar sc, GpuMat& c, int cmpop, Stream& stream = Stream::Null()); //! performs per-elements bit-wise inversion CV_EXPORTS void bitwise_not(const GpuMat& src, GpuMat& dst, const GpuMat& mask=GpuMat(), Stream& stream = Stream::Null()); diff --git a/modules/gpu/perf/perf_core.cpp b/modules/gpu/perf/perf_core.cpp index cfd572dc1..c78bfd6e2 100644 --- a/modules/gpu/perf/perf_core.cpp +++ b/modules/gpu/perf/perf_core.cpp @@ -647,6 +647,39 @@ PERF_TEST_P(Sz_Depth_Code, Core_CompareMat, Combine(GPU_TYPICAL_MAT_SIZES, ARITH } } +////////////////////////////////////////////////////////////////////// +// CompareScalar + +PERF_TEST_P(Sz_Depth_Code, Core_CompareScalar, Combine(GPU_TYPICAL_MAT_SIZES, ARITHM_MAT_DEPTH, ALL_CMP_CODES)) +{ + const cv::Size size = GET_PARAM(0); + const int depth = GET_PARAM(1); + const int cmp_code = GET_PARAM(2); + + cv::Mat src(size, depth); + fillRandom(src); + + cv::Scalar s = cv::Scalar::all(100); + + if (PERF_RUN_GPU()) + { + cv::gpu::GpuMat d_src(src); + cv::gpu::GpuMat d_dst; + + TEST_CYCLE() cv::gpu::compare(d_src, s, d_dst, cmp_code); + + GPU_SANITY_CHECK(d_dst); + } + else + { + cv::Mat dst; + + TEST_CYCLE() cv::compare(src, s, dst, cmp_code); + + CPU_SANITY_CHECK(dst); + } +} + ////////////////////////////////////////////////////////////////////// // BitwiseNot diff --git a/modules/gpu/src/cuda/element_operations.cu b/modules/gpu/src/cuda/element_operations.cu index 4b52cc7dd..27fb61ff7 100644 --- a/modules/gpu/src/cuda/element_operations.cu +++ b/modules/gpu/src/cuda/element_operations.cu @@ -1954,6 +1954,226 @@ namespace arithm template void cmpMatLe(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); } +////////////////////////////////////////////////////////////////////////////////////// +// cmpScalar + +namespace arithm +{ +#define TYPE_VEC(type, cn) typename TypeVec::vec_type + + template struct CmpScalar; + template + struct CmpScalar : unary_function + { + const T val; + + __host__ explicit CmpScalar(T val_) : val(val_) {} + + __device__ __forceinline__ uchar operator()(T src) const + { + Cmp op; + return op(src, val); + } + }; + template + struct CmpScalar : unary_function + { + const TYPE_VEC(T, 2) val; + + __host__ explicit CmpScalar(TYPE_VEC(T, 2) val_) : val(val_) {} + + __device__ __forceinline__ TYPE_VEC(uchar, 2) operator()(const TYPE_VEC(T, 2) & src) const + { + Cmp op; + return VecTraits::make(op(src.x, val.x), op(src.y, val.y)); + } + }; + template + struct CmpScalar : unary_function + { + const TYPE_VEC(T, 3) val; + + __host__ explicit CmpScalar(TYPE_VEC(T, 3) val_) : val(val_) {} + + __device__ __forceinline__ TYPE_VEC(uchar, 3) operator()(const TYPE_VEC(T, 3) & src) const + { + Cmp op; + return VecTraits::make(op(src.x, val.x), op(src.y, val.y), op(src.z, val.z)); + } + }; + template + struct CmpScalar : unary_function + { + const TYPE_VEC(T, 4) val; + + __host__ explicit CmpScalar(TYPE_VEC(T, 4) val_) : val(val_) {} + + __device__ __forceinline__ TYPE_VEC(uchar, 4) operator()(const TYPE_VEC(T, 4) & src) const + { + Cmp op; + return VecTraits::make(op(src.x, val.x), op(src.y, val.y), op(src.z, val.z), op(src.w, val.w)); + } + }; + +#undef TYPE_VEC +} + +namespace cv { namespace gpu { namespace device +{ + template struct TransformFunctorTraits< arithm::CmpScalar > : arithm::ArithmFuncTraits + { + }; +}}} + +namespace arithm +{ + template