/*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. // // // License Agreement // For Open Source Computer Vision Library // // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. // Copyright (C) 2009, Willow Garage Inc., 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 GpuMaterials provided with the distribution. // // * The name of the copyright holders 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 bpied warranties, including, but not limited to, the bpied // 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 "precomp.hpp" using namespace cv; using namespace cv::gpu; #if !defined (HAVE_CUDA) void cv::gpu::add(const GpuMat&, const GpuMat&, GpuMat&, const GpuMat&, int, Stream&) { throw_nogpu(); } void cv::gpu::add(const GpuMat&, const Scalar&, GpuMat&, const GpuMat&, int, Stream&) { throw_nogpu(); } void cv::gpu::subtract(const GpuMat&, const GpuMat&, GpuMat&, const GpuMat&, int, Stream&) { throw_nogpu(); } void cv::gpu::subtract(const GpuMat&, const Scalar&, GpuMat&, const GpuMat&, int, Stream&) { throw_nogpu(); } void cv::gpu::multiply(const GpuMat&, const GpuMat&, GpuMat&, double, int, Stream&) { throw_nogpu(); } void cv::gpu::multiply(const GpuMat&, const Scalar&, GpuMat&, double, int, Stream&) { throw_nogpu(); } void cv::gpu::divide(const GpuMat&, const GpuMat&, GpuMat&, double, int, Stream&) { throw_nogpu(); } void cv::gpu::divide(const GpuMat&, const Scalar&, GpuMat&, double, int, Stream&) { throw_nogpu(); } void cv::gpu::divide(double, const GpuMat&, GpuMat&, int, Stream&) { throw_nogpu(); } void cv::gpu::absdiff(const GpuMat&, const GpuMat&, GpuMat&, Stream&) { throw_nogpu(); } void cv::gpu::absdiff(const GpuMat&, const Scalar&, GpuMat&, Stream&) { throw_nogpu(); } void cv::gpu::abs(const GpuMat&, GpuMat&, Stream&) { throw_nogpu(); } void cv::gpu::sqr(const GpuMat&, GpuMat&, Stream&) { throw_nogpu(); } void cv::gpu::sqrt(const GpuMat&, GpuMat&, Stream&) { throw_nogpu(); } void cv::gpu::exp(const GpuMat&, GpuMat&, Stream&) { throw_nogpu(); } void cv::gpu::log(const GpuMat&, GpuMat&, Stream&) { throw_nogpu(); } void cv::gpu::compare(const GpuMat&, const GpuMat&, GpuMat&, int, Stream&) { throw_nogpu(); } void cv::gpu::bitwise_not(const GpuMat&, GpuMat&, const GpuMat&, Stream&) { throw_nogpu(); } void cv::gpu::bitwise_or(const GpuMat&, const GpuMat&, GpuMat&, const GpuMat&, Stream&) { throw_nogpu(); } void cv::gpu::bitwise_or(const GpuMat&, const Scalar&, GpuMat&, Stream&) { throw_nogpu(); } void cv::gpu::bitwise_and(const GpuMat&, const GpuMat&, GpuMat&, const GpuMat&, Stream&) { throw_nogpu(); } void cv::gpu::bitwise_and(const GpuMat&, const Scalar&, GpuMat&, Stream&) { throw_nogpu(); } void cv::gpu::bitwise_xor(const GpuMat&, const GpuMat&, GpuMat&, const GpuMat&, Stream&) { throw_nogpu(); } void cv::gpu::bitwise_xor(const GpuMat&, const Scalar&, GpuMat&, Stream&) { throw_nogpu(); } void cv::gpu::rshift(const GpuMat&, const Scalar&, GpuMat&, Stream&) { throw_nogpu(); } void cv::gpu::lshift(const GpuMat&, const Scalar&, GpuMat&, Stream&) { throw_nogpu(); } void cv::gpu::min(const GpuMat&, const GpuMat&, GpuMat&, Stream&) { throw_nogpu(); } void cv::gpu::min(const GpuMat&, double, GpuMat&, Stream&) { throw_nogpu(); } void cv::gpu::max(const GpuMat&, const GpuMat&, GpuMat&, Stream&) { throw_nogpu(); } void cv::gpu::max(const GpuMat&, double, GpuMat&, Stream&) { throw_nogpu(); } double cv::gpu::threshold(const GpuMat&, GpuMat&, double, double, int, Stream&) {throw_nogpu(); return 0.0;} void cv::gpu::pow(const GpuMat&, double, GpuMat&, Stream&) { throw_nogpu(); } void cv::gpu::alphaComp(const GpuMat&, const GpuMat&, GpuMat&, int, Stream&) { throw_nogpu(); } void cv::gpu::addWeighted(const GpuMat&, double, const GpuMat&, double, double, GpuMat&, int, Stream&) { throw_nogpu(); } #else //////////////////////////////////////////////////////////////////////// // Basic arithmetical operations (add subtract multiply divide) namespace { typedef NppStatus (*npp_arithm_8u_t)(const Npp8u* pSrc1, int nSrc1Step, const Npp8u* pSrc2, int nSrc2Step, Npp8u* pDst, int nDstStep, NppiSize oSizeROI, int nScaleFactor); typedef NppStatus (*npp_arithm_16u_t)(const Npp16u* pSrc1, int nSrc1Step, const Npp16u* pSrc2, int nSrc2Step, Npp16u* pDst, int nDstStep, NppiSize oSizeROI, int nScaleFactor); typedef NppStatus (*npp_arithm_16s_t)(const Npp16s* pSrc1, int nSrc1Step, const Npp16s* pSrc2, int nSrc2Step, Npp16s* pDst, int nDstStep, NppiSize oSizeROI, int nScaleFactor); typedef NppStatus (*npp_arithm_32s_t)(const Npp32s* pSrc1, int nSrc1Step, const Npp32s* pSrc2, int nSrc2Step, Npp32s* pDst, int nDstStep, NppiSize oSizeROI, int nScaleFactor); typedef NppStatus (*npp_arithm_32f_t)(const Npp32f* pSrc1, int nSrc1Step, const Npp32f* pSrc2, int nSrc2Step, Npp32f* pDst, int nDstStep, NppiSize oSizeROI); bool nppArithmCaller(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, npp_arithm_8u_t npp_func_8uc1, npp_arithm_8u_t npp_func_8uc4, npp_arithm_16u_t npp_func_16uc1, npp_arithm_16u_t npp_func_16uc4, npp_arithm_16s_t npp_func_16sc1, npp_arithm_16s_t npp_func_16sc4, npp_arithm_32s_t npp_func_32sc1, npp_arithm_32f_t npp_func_32fc1, npp_arithm_32f_t npp_func_32fc4, cudaStream_t stream) { bool useNpp = (src1.depth() == CV_8U || src1.depth() == CV_16U || src1.depth() == CV_16S || src1.depth() == CV_32S || src1.depth() == CV_32F); if (!useNpp) return false; bool aligned = isAligned(src1.data, 16) && isAligned(src2.data, 16) && isAligned(dst.data, 16); NppiSize sz; sz.width = src1.cols * src1.channels(); sz.height = src1.rows; NppStreamHandler h(stream); if (aligned && src1.depth() == CV_8U && (sz.width % 4) == 0) { sz.width /= 4; nppSafeCall( npp_func_8uc4(src1.ptr(), static_cast(src1.step), src2.ptr(), static_cast(src2.step), dst.ptr(), static_cast(dst.step), sz, 0) ); } else if (src1.depth() == CV_8U) { nppSafeCall( npp_func_8uc1(src1.ptr(), static_cast(src1.step), src2.ptr(), static_cast(src2.step), dst.ptr(), static_cast(dst.step), sz, 0) ); } else if (aligned && src1.depth() == CV_16U && (sz.width % 4) == 0) { sz.width /= 4; nppSafeCall( npp_func_16uc4(src1.ptr(), static_cast(src1.step), src2.ptr(), static_cast(src2.step), dst.ptr(), static_cast(dst.step), sz, 0) ); } else if (src1.depth() == CV_16U) { nppSafeCall( npp_func_16uc1(src1.ptr(), static_cast(src1.step), src2.ptr(), static_cast(src2.step), dst.ptr(), static_cast(dst.step), sz, 0) ); } else if (aligned && src1.depth() == CV_16S && (sz.width % 4) == 0) { sz.width /= 4; nppSafeCall( npp_func_16sc4(src1.ptr(), static_cast(src1.step), src2.ptr(), static_cast(src2.step), dst.ptr(), static_cast(dst.step), sz, 0) ); } else if (src1.depth() == CV_16S) { nppSafeCall( npp_func_16sc1(src1.ptr(), static_cast(src1.step), src2.ptr(), static_cast(src2.step), dst.ptr(), static_cast(dst.step), sz, 0) ); } else if (src1.depth() == CV_32S) { nppSafeCall( npp_func_32sc1(src1.ptr(), static_cast(src1.step), src2.ptr(), static_cast(src2.step), dst.ptr(), static_cast(dst.step), sz, 0) ); } else if (aligned && src1.depth() == CV_32F && (sz.width % 4) == 0) { sz.width /= 4; nppSafeCall( npp_func_32fc4(src1.ptr(), static_cast(src1.step), src2.ptr(), static_cast(src2.step), dst.ptr(), static_cast(dst.step), sz) ); } else // if (src1.depth() == CV_32F) { nppSafeCall( npp_func_32fc1(src1.ptr(), static_cast(src1.step), src2.ptr(), static_cast(src2.step), dst.ptr(), static_cast(dst.step), sz) ); } if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); return true; } } //////////////////////////////////////////////////////////////////////// // add namespace cv { namespace gpu { namespace device { template void add_gpu(const DevMem2Db& src1, const DevMem2Db& src2, const DevMem2Db& dst, const PtrStepb& mask, cudaStream_t stream); template void add_gpu(const DevMem2Db& src1, double val, const DevMem2Db& dst, const PtrStepb& mask, cudaStream_t stream); }}} void cv::gpu::add(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, const GpuMat& mask, int dtype, Stream& s) { using namespace ::cv::gpu::device; typedef void (*func_t)(const DevMem2Db& src1, const DevMem2Db& src2, const DevMem2Db& dst, const PtrStepb& mask, cudaStream_t stream); static const func_t funcs[7][7] = { {add_gpu, 0/*add_gpu*/, add_gpu, add_gpu, add_gpu, add_gpu, add_gpu}, {0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/}, {0/*add_gpu*/, 0/*add_gpu*/, add_gpu, 0/*add_gpu*/, add_gpu, add_gpu, add_gpu}, {0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, add_gpu, add_gpu, add_gpu, add_gpu}, {0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, add_gpu, add_gpu, add_gpu}, {0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, add_gpu, add_gpu}, {0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, add_gpu} }; CV_Assert(src1.type() == src2.type() && src1.size() == src2.size()); CV_Assert(mask.empty() || (src1.channels() == 1 && mask.size() == src1.size() && mask.type() == CV_8U)); if (dtype < 0) dtype = src1.depth(); dst.create(src1.size(), CV_MAKE_TYPE(CV_MAT_DEPTH(dtype), src1.channels())); cudaStream_t stream = StreamAccessor::getStream(s); if (mask.empty() && dst.type() == src1.type()) { if (nppArithmCaller(src1, src2, dst, nppiAdd_8u_C1RSfs, nppiAdd_8u_C4RSfs, nppiAdd_16u_C1RSfs, nppiAdd_16u_C4RSfs, nppiAdd_16s_C1RSfs, nppiAdd_16s_C4RSfs, nppiAdd_32s_C1RSfs, nppiAdd_32f_C1R, nppiAdd_32f_C4R, stream)) { return; } } const func_t func = funcs[src1.depth()][dst.depth()]; CV_Assert(func != 0); func(src1.reshape(1), src2.reshape(1), dst.reshape(1), mask, stream); } namespace { template struct NppTypeTraits; template<> struct NppTypeTraits { typedef Npp8u npp_t; }; template<> struct NppTypeTraits { typedef Npp8s npp_t; }; template<> struct NppTypeTraits { typedef Npp16u npp_t; }; template<> struct NppTypeTraits { typedef Npp16s npp_t; typedef Npp16sc npp_complex_type; }; template<> struct NppTypeTraits { typedef Npp32s npp_t; typedef Npp32sc npp_complex_type; }; template<> struct NppTypeTraits { typedef Npp32f npp_t; typedef Npp32fc npp_complex_type; }; template<> struct NppTypeTraits { typedef Npp64f npp_t; typedef Npp64fc npp_complex_type; }; template struct NppArithmScalarFunc { typedef typename NppTypeTraits::npp_t npp_t; typedef NppStatus (*func_ptr)(const npp_t* pSrc1, int nSrc1Step, const npp_t* pConstants, npp_t* pDst, int nDstStep, NppiSize oSizeROI, int nScaleFactor); }; template struct NppArithmScalarFunc { typedef typename NppTypeTraits::npp_t npp_t; typedef NppStatus (*func_ptr)(const npp_t* pSrc1, int nSrc1Step, const npp_t pConstants, npp_t* pDst, int nDstStep, NppiSize oSizeROI, int nScaleFactor); }; template struct NppArithmScalarFunc { typedef typename NppTypeTraits::npp_complex_type npp_complex_type; typedef NppStatus (*func_ptr)(const npp_complex_type* pSrc1, int nSrc1Step, const npp_complex_type pConstants, npp_complex_type* pDst, int nDstStep, NppiSize oSizeROI, int nScaleFactor); }; template struct NppArithmScalarFunc { typedef NppStatus (*func_ptr)(const Npp32f* pSrc1, int nSrc1Step, const Npp32f* pConstants, Npp32f* pDst, int nDstStep, NppiSize oSizeROI); }; template<> struct NppArithmScalarFunc { typedef NppStatus (*func_ptr)(const Npp32f* pSrc1, int nSrc1Step, const Npp32f pConstants, Npp32f* pDst, int nDstStep, NppiSize oSizeROI); }; template<> struct NppArithmScalarFunc { typedef NppStatus (*func_ptr)(const Npp32fc* pSrc1, int nSrc1Step, const Npp32fc pConstants, Npp32fc* pDst, int nDstStep, NppiSize oSizeROI); }; template::func_ptr func> struct NppArithmScalar { typedef typename NppTypeTraits::npp_t npp_t; static void call(const GpuMat& src, const Scalar& sc, GpuMat& dst, cudaStream_t stream) { NppStreamHandler h(stream); NppiSize sz; sz.width = src.cols; sz.height = src.rows; const npp_t pConstants[] = { saturate_cast(sc.val[0]), saturate_cast(sc.val[1]), saturate_cast(sc.val[2]), saturate_cast(sc.val[3]) }; nppSafeCall( func(src.ptr(), static_cast(src.step), pConstants, dst.ptr(), static_cast(dst.step), sz, 0) ); if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); } }; template::func_ptr func> struct NppArithmScalar { typedef typename NppTypeTraits::npp_t npp_t; static void call(const GpuMat& src, const Scalar& sc, GpuMat& dst, cudaStream_t stream) { NppStreamHandler h(stream); NppiSize sz; sz.width = src.cols; sz.height = src.rows; nppSafeCall( func(src.ptr(), static_cast(src.step), saturate_cast(sc.val[0]), dst.ptr(), static_cast(dst.step), sz, 0) ); if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); } }; template::func_ptr func> struct NppArithmScalar { typedef typename NppTypeTraits::npp_t npp_t; typedef typename NppTypeTraits::npp_complex_type npp_complex_type; static void call(const GpuMat& src, const Scalar& sc, GpuMat& dst, cudaStream_t stream) { NppStreamHandler h(stream); NppiSize sz; sz.width = src.cols; sz.height = src.rows; npp_complex_type nConstant; nConstant.re = saturate_cast(sc.val[0]); nConstant.im = saturate_cast(sc.val[1]); nppSafeCall( func(src.ptr(), static_cast(src.step), nConstant, dst.ptr(), static_cast(dst.step), sz, 0) ); if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); } }; template::func_ptr func> struct NppArithmScalar { static void call(const GpuMat& src, const Scalar& sc, GpuMat& dst, cudaStream_t stream) { NppStreamHandler h(stream); NppiSize sz; sz.width = src.cols; sz.height = src.rows; const Npp32f pConstants[] = { saturate_cast(sc.val[0]), saturate_cast(sc.val[1]), saturate_cast(sc.val[2]), saturate_cast(sc.val[3]) }; nppSafeCall( func(src.ptr(), static_cast(src.step), pConstants, dst.ptr(), static_cast(dst.step), sz) ); if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); } }; template::func_ptr func> struct NppArithmScalar { static void call(const GpuMat& src, const Scalar& sc, GpuMat& dst, cudaStream_t stream) { NppStreamHandler h(stream); NppiSize sz; sz.width = src.cols; sz.height = src.rows; nppSafeCall( func(src.ptr(), static_cast(src.step), saturate_cast(sc.val[0]), dst.ptr(), static_cast(dst.step), sz) ); if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); } }; template::func_ptr func> struct NppArithmScalar { static void call(const GpuMat& src, const Scalar& sc, GpuMat& dst, cudaStream_t stream) { NppStreamHandler h(stream); NppiSize sz; sz.width = src.cols; sz.height = src.rows; Npp32fc nConstant; nConstant.re = saturate_cast(sc.val[0]); nConstant.im = saturate_cast(sc.val[1]); nppSafeCall( func(src.ptr(), static_cast(src.step), nConstant, dst.ptr(), static_cast(dst.step), sz) ); if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); } }; } void cv::gpu::add(const GpuMat& src, const Scalar& sc, GpuMat& dst, const GpuMat& mask, int dtype, Stream& s) { using namespace ::cv::gpu::device; typedef void (*func_t)(const DevMem2Db& src1, double val, const DevMem2Db& dst, const PtrStepb& mask, cudaStream_t stream); static const func_t funcs[7][7] = { {add_gpu, 0/*add_gpu*/, add_gpu, add_gpu, add_gpu, add_gpu, add_gpu}, {0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/}, {0/*add_gpu*/, 0/*add_gpu*/, add_gpu, 0/*add_gpu*/, add_gpu, add_gpu, add_gpu}, {0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, add_gpu, add_gpu, add_gpu, add_gpu}, {0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, add_gpu, add_gpu, add_gpu}, {0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, add_gpu, add_gpu}, {0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, add_gpu} }; typedef void (*npp_func_t)(const GpuMat& src, const Scalar& sc, GpuMat& dst, cudaStream_t stream); static const npp_func_t npp_funcs[7][4] = { {NppArithmScalar::call, 0, NppArithmScalar::call, NppArithmScalar::call}, {0,0,0,0}, {NppArithmScalar::call, 0, NppArithmScalar::call, NppArithmScalar::call}, {NppArithmScalar::call, NppArithmScalar::call, NppArithmScalar::call, NppArithmScalar::call}, {NppArithmScalar::call, NppArithmScalar::call, NppArithmScalar::call, 0}, {NppArithmScalar::call, NppArithmScalar::call, NppArithmScalar::call, NppArithmScalar::call}, {0,0,0,0} }; CV_Assert(mask.empty() || (src.channels() == 1 && mask.size() == src.size() && mask.type() == CV_8U)); if (dtype < 0) dtype = src.depth(); dst.create(src.size(), CV_MAKE_TYPE(CV_MAT_DEPTH(dtype), src.channels())); cudaStream_t stream = StreamAccessor::getStream(s); if (mask.empty() && dst.type() == src.type()) { const npp_func_t npp_func = npp_funcs[src.depth()][src.channels() - 1]; if (npp_func) { npp_func(src, sc, dst, stream); return; } } CV_Assert(src.channels() == 1); const func_t func = funcs[src.depth()][dst.depth()]; CV_Assert(func != 0); func(src, sc.val[0], dst, mask, stream); } //////////////////////////////////////////////////////////////////////// // subtract namespace cv { namespace gpu { namespace device { template void subtract_gpu(const DevMem2Db& src1, const DevMem2Db& src2, const DevMem2Db& dst, const PtrStepb& mask, cudaStream_t stream); template void subtract_gpu(const DevMem2Db& src1, double val, const DevMem2Db& dst, const PtrStepb& mask, cudaStream_t stream); }}} void cv::gpu::subtract(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, const GpuMat& mask, int dtype, Stream& s) { using namespace ::cv::gpu::device; typedef void (*func_t)(const DevMem2Db& src1, const DevMem2Db& src2, const DevMem2Db& dst, const PtrStepb& mask, cudaStream_t stream); static const func_t funcs[7][7] = { {subtract_gpu, 0/*subtract_gpu*/, subtract_gpu, subtract_gpu, subtract_gpu, subtract_gpu, subtract_gpu}, {0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/}, {0/*subtract_gpu*/, 0/*subtract_gpu*/, subtract_gpu, 0/*subtract_gpu*/, subtract_gpu, subtract_gpu, subtract_gpu}, {0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, subtract_gpu, subtract_gpu, subtract_gpu, subtract_gpu}, {0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, subtract_gpu, subtract_gpu, subtract_gpu}, {0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, subtract_gpu, subtract_gpu}, {0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, subtract_gpu} }; CV_Assert(src1.type() == src2.type() && src1.size() == src2.size()); CV_Assert(mask.empty() || (src1.channels() == 1 && mask.size() == src1.size() && mask.type() == CV_8U)); if (dtype < 0) dtype = src1.depth(); dst.create(src1.size(), CV_MAKE_TYPE(CV_MAT_DEPTH(dtype), src1.channels())); cudaStream_t stream = StreamAccessor::getStream(s); if (mask.empty() && dst.type() == src1.type()) { if (nppArithmCaller(src2, src1, dst, nppiSub_8u_C1RSfs, nppiSub_8u_C4RSfs, nppiSub_16u_C1RSfs, nppiSub_16u_C4RSfs, nppiSub_16s_C1RSfs, nppiSub_16s_C4RSfs, nppiSub_32s_C1RSfs, nppiSub_32f_C1R, nppiSub_32f_C4R, stream)) { return; } } const func_t func = funcs[src1.depth()][dst.depth()]; CV_Assert(func != 0); func(src1.reshape(1), src2.reshape(1), dst.reshape(1), mask, stream); } void cv::gpu::subtract(const GpuMat& src, const Scalar& sc, GpuMat& dst, const GpuMat& mask, int dtype, Stream& s) { using namespace ::cv::gpu::device; typedef void (*func_t)(const DevMem2Db& src1, double val, const DevMem2Db& dst, const PtrStepb& mask, cudaStream_t stream); static const func_t funcs[7][7] = { {subtract_gpu, 0/*subtract_gpu*/, subtract_gpu, subtract_gpu, subtract_gpu, subtract_gpu, subtract_gpu}, {0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/}, {0/*subtract_gpu*/, 0/*subtract_gpu*/, subtract_gpu, 0/*subtract_gpu*/, subtract_gpu, subtract_gpu, subtract_gpu}, {0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, subtract_gpu, subtract_gpu, subtract_gpu, subtract_gpu}, {0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, subtract_gpu, subtract_gpu, subtract_gpu}, {0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, subtract_gpu, subtract_gpu}, {0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, subtract_gpu} }; typedef void (*npp_func_t)(const GpuMat& src, const Scalar& sc, GpuMat& dst, cudaStream_t stream); static const npp_func_t npp_funcs[7][4] = { {NppArithmScalar::call, 0, NppArithmScalar::call, NppArithmScalar::call}, {0,0,0,0}, {NppArithmScalar::call, 0, NppArithmScalar::call, NppArithmScalar::call}, {NppArithmScalar::call, NppArithmScalar::call, NppArithmScalar::call, NppArithmScalar::call}, {NppArithmScalar::call, NppArithmScalar::call, NppArithmScalar::call, 0}, {NppArithmScalar::call, NppArithmScalar::call, NppArithmScalar::call, NppArithmScalar::call}, {0,0,0,0} }; CV_Assert(mask.empty() || (src.channels() == 1 && mask.size() == src.size() && mask.type() == CV_8U)); if (dtype < 0) dtype = src.depth(); dst.create(src.size(), CV_MAKE_TYPE(CV_MAT_DEPTH(dtype), src.channels())); cudaStream_t stream = StreamAccessor::getStream(s); if (mask.empty() && dst.type() == src.type()) { const npp_func_t npp_func = npp_funcs[src.depth()][src.channels() - 1]; if (npp_func) { npp_func(src, sc, dst, stream); return; } } CV_Assert(src.channels() == 1); const func_t func = funcs[src.depth()][dst.depth()]; CV_Assert(func != 0); func(src, sc.val[0], dst, mask, stream); } //////////////////////////////////////////////////////////////////////// // multiply namespace cv { namespace gpu { namespace device { void multiply_gpu(const DevMem2D_& src1, const DevMem2Df& src2, const DevMem2D_& dst, cudaStream_t stream); void multiply_gpu(const DevMem2D_& src1, const DevMem2Df& src2, const DevMem2D_& dst, cudaStream_t stream); template void multiply_gpu(const DevMem2Db& src1, const DevMem2Db& src2, const DevMem2Db& dst, double scale, cudaStream_t stream); template void multiply_gpu(const DevMem2Db& src1, double val, const DevMem2Db& dst, double scale, cudaStream_t stream); }}} void cv::gpu::multiply(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, double scale, int dtype, Stream& s) { using namespace ::cv::gpu::device; typedef void (*func_t)(const DevMem2Db& src1, const DevMem2Db& src2, const DevMem2Db& dst, double scale, cudaStream_t stream); static const func_t funcs[7][7] = { {multiply_gpu, 0/*multiply_gpu*/, multiply_gpu, multiply_gpu, multiply_gpu, multiply_gpu, multiply_gpu}, {0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/}, {0/*multiply_gpu*/, 0/*multiply_gpu*/, multiply_gpu, 0/*multiply_gpu*/, multiply_gpu, multiply_gpu, multiply_gpu}, {0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, multiply_gpu, multiply_gpu, multiply_gpu, multiply_gpu}, {0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, multiply_gpu, multiply_gpu, multiply_gpu}, {0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, multiply_gpu, multiply_gpu}, {0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, multiply_gpu} }; cudaStream_t stream = StreamAccessor::getStream(s); if (src1.type() == CV_8UC4 && src2.type() == CV_32FC1) { CV_Assert(src1.size() == src2.size()); dst.create(src1.size(), src1.type()); multiply_gpu(static_cast >(src1), static_cast(src2), static_cast >(dst), stream); } else if (src1.type() == CV_16SC4 && src2.type() == CV_32FC1) { CV_Assert(src1.size() == src2.size()); dst.create(src1.size(), src1.type()); multiply_gpu(static_cast >(src1), static_cast(src2), static_cast >(dst), stream); } else { CV_Assert(src1.type() == src2.type() && src1.size() == src2.size()); if (dtype < 0) dtype = src1.depth(); dst.create(src1.size(), CV_MAKE_TYPE(CV_MAT_DEPTH(dtype), src1.channels())); if (scale == 1 && dst.type() == src1.type()) { if (nppArithmCaller(src1, src2, dst, nppiMul_8u_C1RSfs, nppiMul_8u_C4RSfs, nppiMul_16u_C1RSfs, nppiMul_16u_C4RSfs, nppiMul_16s_C1RSfs, nppiMul_16s_C4RSfs, nppiMul_32s_C1RSfs, nppiMul_32f_C1R, nppiMul_32f_C4R, stream)) { return; } } const func_t func = funcs[src1.depth()][dst.depth()]; CV_Assert(func != 0); func(src1.reshape(1), src2.reshape(1), dst.reshape(1), scale, stream); } } namespace { bool isIntScalar(Scalar sc) { Scalar_ isc(sc); return sc.val[0] == isc.val[0] && sc.val[1] == isc.val[1] && sc.val[2] == isc.val[2] && sc.val[3] == isc.val[3]; } } void cv::gpu::multiply(const GpuMat& src, const Scalar& sc, GpuMat& dst, double scale, int dtype, Stream& s) { using namespace ::cv::gpu::device; typedef void (*func_t)(const DevMem2Db& src1, double val, const DevMem2Db& dst, double scale, cudaStream_t stream); static const func_t funcs[7][7] = { {multiply_gpu, 0/*multiply_gpu*/, multiply_gpu, multiply_gpu, multiply_gpu, multiply_gpu, multiply_gpu}, {0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/}, {0/*multiply_gpu*/, 0/*multiply_gpu*/, multiply_gpu, 0/*multiply_gpu*/, multiply_gpu, multiply_gpu, multiply_gpu}, {0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, multiply_gpu, multiply_gpu, multiply_gpu, multiply_gpu}, {0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, multiply_gpu, multiply_gpu, multiply_gpu}, {0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, multiply_gpu, multiply_gpu}, {0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, multiply_gpu} }; typedef void (*npp_func_t)(const GpuMat& src, const Scalar& sc, GpuMat& dst, cudaStream_t stream); static const npp_func_t npp_funcs[7][4] = { {NppArithmScalar::call, 0, NppArithmScalar::call, NppArithmScalar::call}, {0,0,0,0}, {NppArithmScalar::call, 0, NppArithmScalar::call, NppArithmScalar::call}, {NppArithmScalar::call, 0, NppArithmScalar::call, NppArithmScalar::call}, {NppArithmScalar::call, 0, NppArithmScalar::call, 0}, {NppArithmScalar::call, 0, NppArithmScalar::call, NppArithmScalar::call}, {0,0,0,0} }; if (dtype < 0) dtype = src.depth(); dst.create(src.size(), CV_MAKE_TYPE(CV_MAT_DEPTH(dtype), src.channels())); cudaStream_t stream = StreamAccessor::getStream(s); if (dst.type() == src.type() && scale == 1) { const npp_func_t npp_func = npp_funcs[src.depth()][src.channels() - 1]; if (npp_func && (src.depth() == CV_32F || isIntScalar(sc))) { npp_func(src, sc, dst, stream); return; } } const func_t func = funcs[src.depth()][dst.depth()]; CV_Assert(func != 0); func(src.reshape(1), sc.val[0], dst.reshape(1), scale, stream); } //////////////////////////////////////////////////////////////////////// // divide namespace cv { namespace gpu { namespace device { void divide_gpu(const DevMem2D_& src1, const DevMem2Df& src2, const DevMem2D_& dst, cudaStream_t stream); void divide_gpu(const DevMem2D_& src1, const DevMem2Df& src2, const DevMem2D_& dst, cudaStream_t stream); template void divide_gpu(const DevMem2Db& src1, const DevMem2Db& src2, const DevMem2Db& dst, double scale, cudaStream_t stream); template void divide_gpu(const DevMem2Db& src1, double val, const DevMem2Db& dst, double scale, cudaStream_t stream); template void divide_gpu(double scalar, const DevMem2Db& src2, const DevMem2Db& dst, cudaStream_t stream); }}} void cv::gpu::divide(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, double scale, int dtype, Stream& s) { using namespace ::cv::gpu::device; typedef void (*func_t)(const DevMem2Db& src1, const DevMem2Db& src2, const DevMem2Db& dst, double scale, cudaStream_t stream); static const func_t funcs[7][7] = { {divide_gpu, 0/*divide_gpu*/, divide_gpu, divide_gpu, divide_gpu, divide_gpu, divide_gpu}, {0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/}, {0/*divide_gpu*/, 0/*divide_gpu*/, divide_gpu, 0/*divide_gpu*/, divide_gpu, divide_gpu, divide_gpu}, {0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, divide_gpu, divide_gpu, divide_gpu, divide_gpu}, {0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, divide_gpu, divide_gpu, divide_gpu}, {0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, divide_gpu, divide_gpu}, {0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, divide_gpu} }; cudaStream_t stream = StreamAccessor::getStream(s); if (src1.type() == CV_8UC4 && src2.type() == CV_32FC1) { CV_Assert(src1.size() == src2.size()); dst.create(src1.size(), src1.type()); multiply_gpu(static_cast >(src1), static_cast(src2), static_cast >(dst), stream); } else if (src1.type() == CV_16SC4 && src2.type() == CV_32FC1) { CV_Assert(src1.size() == src2.size()); dst.create(src1.size(), src1.type()); multiply_gpu(static_cast >(src1), static_cast(src2), static_cast >(dst), stream); } else { CV_Assert(src1.type() == src2.type() && src1.size() == src2.size()); if (dtype < 0) dtype = src1.depth(); dst.create(src1.size(), CV_MAKE_TYPE(CV_MAT_DEPTH(dtype), src1.channels())); if (scale == 1 && dst.type() == src1.type()) { if (nppArithmCaller(src2, src1, dst, nppiDiv_8u_C1RSfs, nppiDiv_8u_C4RSfs, nppiDiv_16u_C1RSfs, nppiDiv_16u_C4RSfs, nppiDiv_16s_C1RSfs, nppiDiv_16s_C4RSfs, nppiDiv_32s_C1RSfs, nppiDiv_32f_C1R, nppiDiv_32f_C4R, stream)) { return; } } const func_t func = funcs[src1.depth()][dst.depth()]; CV_Assert(func != 0); func(src1.reshape(1), src2.reshape(1), dst.reshape(1), scale, stream); } } void cv::gpu::divide(const GpuMat& src, const Scalar& sc, GpuMat& dst, double scale, int dtype, Stream& s) { using namespace ::cv::gpu::device; typedef void (*func_t)(const DevMem2Db& src1, double val, const DevMem2Db& dst, double scale, cudaStream_t stream); static const func_t funcs[7][7] = { {divide_gpu, 0/*divide_gpu*/, divide_gpu, divide_gpu, divide_gpu, divide_gpu, divide_gpu}, {0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/}, {0/*divide_gpu*/, 0/*divide_gpu*/, divide_gpu, 0/*divide_gpu*/, divide_gpu, divide_gpu, divide_gpu}, {0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, divide_gpu, divide_gpu, divide_gpu, divide_gpu}, {0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, divide_gpu, divide_gpu, divide_gpu}, {0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, divide_gpu, divide_gpu}, {0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, divide_gpu} }; typedef void (*npp_func_t)(const GpuMat& src, const Scalar& sc, GpuMat& dst, cudaStream_t stream); static const npp_func_t npp_funcs[7][4] = { {NppArithmScalar::call, 0, NppArithmScalar::call, NppArithmScalar::call}, {0,0,0,0}, {NppArithmScalar::call, 0, NppArithmScalar::call, NppArithmScalar::call}, {NppArithmScalar::call, 0, NppArithmScalar::call, NppArithmScalar::call}, {NppArithmScalar::call, 0, NppArithmScalar::call, 0}, {NppArithmScalar::call, 0, NppArithmScalar::call, NppArithmScalar::call}, {0,0,0,0} }; if (dtype < 0) dtype = src.depth(); dst.create(src.size(), CV_MAKE_TYPE(CV_MAT_DEPTH(dtype), src.channels())); cudaStream_t stream = StreamAccessor::getStream(s); if (dst.type() == src.type() && scale == 1) { const npp_func_t npp_func = npp_funcs[src.depth()][src.channels() - 1]; if (npp_func && (src.depth() == CV_32F || isIntScalar(sc))) { npp_func(src, sc, dst, stream); return; } } const func_t func = funcs[src.depth()][dst.depth()]; CV_Assert(func != 0); func(src.reshape(1), sc.val[0], dst.reshape(1), scale, stream); } void cv::gpu::divide(double scale, const GpuMat& src, GpuMat& dst, int dtype, Stream& s) { using namespace ::cv::gpu::device; typedef void (*func_t)(double scalar, const DevMem2Db& src2, const DevMem2Db& dst, cudaStream_t stream); static const func_t funcs[7][7] = { {divide_gpu, 0/*divide_gpu*/, divide_gpu, divide_gpu, divide_gpu, divide_gpu, divide_gpu}, {0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/}, {0/*divide_gpu*/, 0/*divide_gpu*/, divide_gpu, 0/*divide_gpu*/, divide_gpu, divide_gpu, divide_gpu}, {0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, divide_gpu, divide_gpu, divide_gpu, divide_gpu}, {0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, divide_gpu, divide_gpu, divide_gpu}, {0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, divide_gpu, divide_gpu}, {0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, divide_gpu} }; CV_Assert(src.channels() == 1); if (dtype < 0) dtype = src.depth(); dst.create(src.size(), CV_MAKE_TYPE(CV_MAT_DEPTH(dtype), src.channels())); cudaStream_t stream = StreamAccessor::getStream(s); const func_t func = funcs[src.depth()][dst.depth()]; CV_Assert(func != 0); func(scale, src, dst, stream); } ////////////////////////////////////////////////////////////////////////////// // absdiff namespace cv { namespace gpu { namespace device { template void absdiff_gpu(const DevMem2Db& src1, const DevMem2Db& src2, const DevMem2Db& dst, cudaStream_t stream); template void absdiff_gpu(const DevMem2Db& src1, double val, const DevMem2Db& dst, cudaStream_t stream); }}} void cv::gpu::absdiff(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, Stream& s) { using namespace ::cv::gpu::device; typedef void (*func_t)(const DevMem2Db& src1, const DevMem2Db& src2, const DevMem2Db& dst, cudaStream_t stream); static const func_t funcs[] = { absdiff_gpu, absdiff_gpu, absdiff_gpu, absdiff_gpu, absdiff_gpu, absdiff_gpu, absdiff_gpu }; CV_Assert(src1.size() == src2.size() && src1.type() == src2.type()); dst.create( src1.size(), src1.type() ); cudaStream_t stream = StreamAccessor::getStream(s); NppiSize sz; sz.width = src1.cols * src1.channels(); sz.height = src1.rows; if (src1.depth() == CV_8U) { NppStreamHandler h(stream); nppSafeCall( nppiAbsDiff_8u_C1R(src1.ptr(), static_cast(src1.step), src2.ptr(), static_cast(src2.step), dst.ptr(), static_cast(dst.step), sz) ); if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); } else if (src1.depth() == CV_16U) { NppStreamHandler h(stream); nppSafeCall( nppiAbsDiff_16u_C1R(src1.ptr(), static_cast(src1.step), src2.ptr(), static_cast(src2.step), dst.ptr(), static_cast(dst.step), sz) ); if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); } else if (src1.depth() == CV_32F) { NppStreamHandler h(stream); nppSafeCall( nppiAbsDiff_32f_C1R(src1.ptr(), static_cast(src1.step), src2.ptr(), static_cast(src2.step), dst.ptr(), static_cast(dst.step), sz) ); if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); } else { const func_t func = funcs[src1.depth()]; CV_Assert(func != 0); func(src1.reshape(1), src2.reshape(1), dst.reshape(1), stream); } } namespace { template struct NppAbsDiffCFunc { typedef typename NppTypeTraits::npp_t npp_t; typedef NppStatus (*func_t)(const npp_t* pSrc1, int nSrc1Step, npp_t* pDst, int nDstStep, NppiSize oSizeROI, npp_t nConstant); }; template <> struct NppAbsDiffCFunc { typedef NppStatus (*func_t)(const Npp16u* pSrc1, int nSrc1Step, Npp16u* pDst, int nDstStep, NppiSize oSizeROI, Npp32u nConstant); }; template ::func_t func> struct NppAbsDiffC { typedef typename NppTypeTraits::npp_t npp_t; static void call(const DevMem2Db& src1, double val, const DevMem2Db& dst, cudaStream_t stream) { NppStreamHandler h(stream); NppiSize sz; sz.width = src1.cols; sz.height = src1.rows; nppSafeCall( func((const npp_t*)src1.data, static_cast(src1.step), (npp_t*)dst.data, static_cast(dst.step), sz, static_cast(val)) ); if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); } }; } void cv::gpu::absdiff(const GpuMat& src1, const Scalar& src2, GpuMat& dst, Stream& s) { using namespace cv::gpu::device; typedef void (*func_t)(const DevMem2Db& src1, double val, const DevMem2Db& dst, cudaStream_t stream); static const func_t funcs[] = { NppAbsDiffC::call, absdiff_gpu, NppAbsDiffC::call, absdiff_gpu, absdiff_gpu, NppAbsDiffC::call, absdiff_gpu }; CV_Assert(src1.channels() == 1); dst.create(src1.size(), src1.type()); cudaStream_t stream = StreamAccessor::getStream(s); funcs[src1.depth()](src1, src2.val[0], dst, stream); } ////////////////////////////////////////////////////////////////////////////// // abs void cv::gpu::abs(const GpuMat& src, GpuMat& dst, Stream& s) { CV_Assert(src.depth() == CV_16S || src.depth() == CV_32F); dst.create(src.size(), src.type()); cudaStream_t stream = StreamAccessor::getStream(s); NppStreamHandler h(stream); NppiSize oSizeROI; oSizeROI.width = src.cols * src.channels(); oSizeROI.height = src.rows; bool aligned = isAligned(src.data, 16) && isAligned(dst.data, 16); if (src.depth() == CV_16S) { if (aligned && oSizeROI.width % 4 == 0) { oSizeROI.width /= 4; nppSafeCall( nppiAbs_16s_C4R(src.ptr(), static_cast(src.step), dst.ptr(), static_cast(dst.step), oSizeROI) ); } else { nppSafeCall( nppiAbs_16s_C1R(src.ptr(), static_cast(src.step), dst.ptr(), static_cast(dst.step), oSizeROI) ); } } else { if (aligned && oSizeROI.width % 4 == 0) { oSizeROI.width /= 4; nppSafeCall( nppiAbs_32f_C4R(src.ptr(), static_cast(src.step), dst.ptr(), static_cast(dst.step), oSizeROI) ); } else { nppSafeCall( nppiAbs_32f_C1R(src.ptr(), static_cast(src.step), dst.ptr(), static_cast(dst.step), oSizeROI) ); } } if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); } ////////////////////////////////////////////////////////////////////////////// // sqr namespace { template struct NppSqrFunc { typedef typename NppTypeTraits::npp_t npp_t; typedef NppStatus (*func_t)(const npp_t* pSrc, int nSrcStep, npp_t* pDst, int nDstStep, NppiSize oSizeROI, int nScaleFactor); }; template <> struct NppSqrFunc { typedef NppTypeTraits::npp_t npp_t; typedef NppStatus (*func_t)(const npp_t* pSrc, int nSrcStep, npp_t* pDst, int nDstStep, NppiSize oSizeROI); }; template ::func_t func, typename NppSqrFunc::func_t func_c4> struct NppSqr { typedef typename NppSqrFunc::npp_t npp_t; static void call(const GpuMat& src, GpuMat& dst, cudaStream_t stream) { NppStreamHandler h(stream); NppiSize oSizeROI; oSizeROI.width = src.cols * src.channels(); oSizeROI.height = src.rows; bool aligned = isAligned(src.data, 16) && isAligned(dst.data, 16); if (aligned && oSizeROI.width % 4 == 0) { oSizeROI.width /= 4; nppSafeCall( func_c4(src.ptr(), static_cast(src.step), dst.ptr(), static_cast(dst.step), oSizeROI, 0) ); } else { nppSafeCall( func(src.ptr(), static_cast(src.step), dst.ptr(), static_cast(dst.step), oSizeROI, 0) ); } if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); } }; template ::func_t func, typename NppSqrFunc::func_t func_c4> struct NppSqr { typedef NppSqrFunc::npp_t npp_t; static void call(const GpuMat& src, GpuMat& dst, cudaStream_t stream) { NppStreamHandler h(stream); NppiSize oSizeROI; oSizeROI.width = src.cols * src.channels(); oSizeROI.height = src.rows; bool aligned = isAligned(src.data, 16) && isAligned(dst.data, 16); if (aligned && oSizeROI.width % 4 == 0) { oSizeROI.width /= 4; nppSafeCall( func_c4(src.ptr(), static_cast(src.step), dst.ptr(), static_cast(dst.step), oSizeROI) ); } else { nppSafeCall( func(src.ptr(), static_cast(src.step), dst.ptr(), static_cast(dst.step), oSizeROI) ); } if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); } }; } void cv::gpu::sqr(const GpuMat& src, GpuMat& dst, Stream& stream) { typedef void (*func_t)(const GpuMat& src, GpuMat& dst, cudaStream_t stream); static const func_t funcs[] = { NppSqr::call, 0, NppSqr::call, NppSqr::call, 0, NppSqr::call }; CV_Assert(src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_16S || src.depth() == CV_32F); dst.create(src.size(), src.type()); funcs[src.depth()](src, dst, StreamAccessor::getStream(stream)); } ////////////////////////////////////////////////////////////////////////////// // sqrt namespace { template struct NppOneSourceFunc { typedef typename NppTypeTraits::npp_t npp_t; typedef NppStatus (*func_t)(const npp_t* pSrc, int nSrcStep, npp_t* pDst, int nDstStep, NppiSize oSizeROI, int nScaleFactor); }; template <> struct NppOneSourceFunc { typedef NppTypeTraits::npp_t npp_t; typedef NppStatus (*func_t)(const npp_t* pSrc, int nSrcStep, npp_t* pDst, int nDstStep, NppiSize oSizeROI); }; template ::func_t func> struct NppOneSource { typedef typename NppOneSourceFunc::npp_t npp_t; static void call(const GpuMat& src, GpuMat& dst, cudaStream_t stream) { NppStreamHandler h(stream); NppiSize oSizeROI; oSizeROI.width = src.cols * src.channels(); oSizeROI.height = src.rows; nppSafeCall( func(src.ptr(), static_cast(src.step), dst.ptr(), static_cast(dst.step), oSizeROI, 0) ); if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); } }; template ::func_t func> struct NppOneSource { typedef NppOneSourceFunc::npp_t npp_t; static void call(const GpuMat& src, GpuMat& dst, cudaStream_t stream) { NppStreamHandler h(stream); NppiSize oSizeROI; oSizeROI.width = src.cols * src.channels(); oSizeROI.height = src.rows; nppSafeCall( func(src.ptr(), static_cast(src.step), dst.ptr(), static_cast(dst.step), oSizeROI) ); if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); } }; } void cv::gpu::sqrt(const GpuMat& src, GpuMat& dst, Stream& stream) { typedef void (*func_t)(const GpuMat& src, GpuMat& dst, cudaStream_t stream); static const func_t funcs[] = { NppOneSource::call, 0, NppOneSource::call, NppOneSource::call, 0, NppOneSource::call }; CV_Assert(src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_16S || src.depth() == CV_32F); dst.create(src.size(), src.type()); funcs[src.depth()](src, dst, StreamAccessor::getStream(stream)); } //////////////////////////////////////////////////////////////////////// // log void cv::gpu::log(const GpuMat& src, GpuMat& dst, Stream& stream) { typedef void (*func_t)(const GpuMat& src, GpuMat& dst, cudaStream_t stream); static const func_t funcs[] = { NppOneSource::call, 0, NppOneSource::call, NppOneSource::call, 0, NppOneSource::call }; CV_Assert(src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_16S || src.depth() == CV_32F); dst.create(src.size(), src.type()); funcs[src.depth()](src, dst, StreamAccessor::getStream(stream)); } //////////////////////////////////////////////////////////////////////// // exp void cv::gpu::exp(const GpuMat& src, GpuMat& dst, Stream& stream) { typedef void (*func_t)(const GpuMat& src, GpuMat& dst, cudaStream_t stream); static const func_t funcs[] = { NppOneSource::call, 0, NppOneSource::call, NppOneSource::call, 0, NppOneSource::call }; CV_Assert(src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_16S || src.depth() == CV_32F); dst.create(src.size(), src.type()); funcs[src.depth()](src, dst, StreamAccessor::getStream(stream)); } ////////////////////////////////////////////////////////////////////////////// // Comparison of two matrixes namespace cv { namespace gpu { namespace device { template void compare_eq(const DevMem2Db& src1, const DevMem2Db& src2, const DevMem2Db& dst, cudaStream_t stream); template void compare_ne(const DevMem2Db& src1, const DevMem2Db& src2, const DevMem2Db& dst, cudaStream_t stream); template void compare_lt(const DevMem2Db& src1, const DevMem2Db& src2, const DevMem2Db& dst, cudaStream_t stream); template void compare_le(const DevMem2Db& src1, const DevMem2Db& src2, const DevMem2Db& dst, cudaStream_t stream); }}} void cv::gpu::compare(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, int cmpop, Stream& stream) { using namespace ::cv::gpu::device; typedef void (*func_t)(const DevMem2Db& src1, const DevMem2Db& src2, const DevMem2Db& dst, cudaStream_t stream); static const func_t funcs[7][4] = { {compare_eq, compare_ne, compare_lt, compare_le}, {compare_eq, compare_ne, compare_lt, compare_le}, {compare_eq, compare_ne, compare_lt, compare_le}, {compare_eq, compare_ne, compare_lt, compare_le}, {compare_eq, compare_ne, compare_lt, compare_le}, {compare_eq, compare_ne, compare_lt, compare_le}, {compare_eq, compare_ne, compare_lt, compare_le} }; CV_Assert(src1.size() == src2.size() && src1.type() == src2.type()); int code; const GpuMat* psrc1; const GpuMat* psrc2; switch (cmpop) { case CMP_EQ: code = 0; psrc1 = &src1; psrc2 = &src2; break; case CMP_GE: code = 3; psrc1 = &src2; psrc2 = &src1; break; case CMP_GT: code = 2; psrc1 = &src2; psrc2 = &src1; break; case CMP_LE: code = 3; psrc1 = &src1; psrc2 = &src2; break; case CMP_LT: code = 2; psrc1 = &src1; psrc2 = &src2; break; case CMP_NE: code = 1; psrc1 = &src1; psrc2 = &src2; break; default: CV_Error(CV_StsBadFlag, "Incorrect compare operation"); }; dst.create(src1.size(), CV_MAKE_TYPE(CV_8U, src1.channels())); funcs[src1.depth()][code](psrc1->reshape(1), psrc2->reshape(1), dst.reshape(1), StreamAccessor::getStream(stream)); } ////////////////////////////////////////////////////////////////////////////// // Unary bitwise logical operations namespace cv { namespace gpu { namespace device { void bitwiseNotCaller(int rows, int cols, size_t elem_size1, int cn, const PtrStepb src, PtrStepb dst, cudaStream_t stream); template void bitwiseMaskNotCaller(int rows, int cols, int cn, const PtrStepb src, const PtrStepb mask, PtrStepb dst, cudaStream_t stream); }}} namespace { void bitwiseNotCaller(const GpuMat& src, GpuMat& dst, cudaStream_t stream) { dst.create(src.size(), src.type()); ::cv::gpu::device::bitwiseNotCaller(src.rows, src.cols, src.elemSize1(), dst.channels(), src, dst, stream); } void bitwiseNotCaller(const GpuMat& src, GpuMat& dst, const GpuMat& mask, cudaStream_t stream) { using namespace ::cv::gpu::device; typedef void (*Caller)(int, int, int, const PtrStepb, const PtrStepb, PtrStepb, cudaStream_t); static Caller callers[] = { bitwiseMaskNotCaller, bitwiseMaskNotCaller, bitwiseMaskNotCaller, bitwiseMaskNotCaller, bitwiseMaskNotCaller, bitwiseMaskNotCaller, bitwiseMaskNotCaller }; CV_Assert(mask.type() == CV_8U && mask.size() == src.size()); dst.create(src.size(), src.type()); Caller caller = callers[src.depth()]; CV_Assert(caller); int cn = src.depth() != CV_64F ? src.channels() : src.channels() * (sizeof(double) / sizeof(unsigned int)); caller(src.rows, src.cols, cn, src, mask, dst, stream); } } void cv::gpu::bitwise_not(const GpuMat& src, GpuMat& dst, const GpuMat& mask, Stream& stream) { if (mask.empty()) bitwiseNotCaller(src, dst, StreamAccessor::getStream(stream)); else bitwiseNotCaller(src, dst, mask, StreamAccessor::getStream(stream)); } ////////////////////////////////////////////////////////////////////////////// // Binary bitwise logical operations namespace cv { namespace gpu { namespace device { void bitwiseOrCaller(int rows, int cols, size_t elem_size1, int cn, const PtrStepb src1, const PtrStepb src2, PtrStepb dst, cudaStream_t stream); template void bitwiseMaskOrCaller(int rows, int cols, int cn, const PtrStepb src1, const PtrStepb src2, const PtrStepb mask, PtrStepb dst, cudaStream_t stream); void bitwiseAndCaller(int rows, int cols, size_t elem_size1, int cn, const PtrStepb src1, const PtrStepb src2, PtrStepb dst, cudaStream_t stream); template void bitwiseMaskAndCaller(int rows, int cols, int cn, const PtrStepb src1, const PtrStepb src2, const PtrStepb mask, PtrStepb dst, cudaStream_t stream); void bitwiseXorCaller(int rows, int cols, size_t elem_size1, int cn, const PtrStepb src1, const PtrStepb src2, PtrStepb dst, cudaStream_t stream); template void bitwiseMaskXorCaller(int rows, int cols, int cn, const PtrStepb src1, const PtrStepb src2, const PtrStepb mask, PtrStepb dst, cudaStream_t stream); }}} namespace { void bitwiseOrCaller(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, cudaStream_t stream) { CV_Assert(src1.size() == src2.size() && src1.type() == src2.type()); dst.create(src1.size(), src1.type()); ::cv::gpu::device::bitwiseOrCaller(dst.rows, dst.cols, dst.elemSize1(), dst.channels(), src1, src2, dst, stream); } void bitwiseOrCaller(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, const GpuMat& mask, cudaStream_t stream) { using namespace ::cv::gpu::device; typedef void (*Caller)(int, int, int, const PtrStepb, const PtrStepb, const PtrStepb, PtrStepb, cudaStream_t); static Caller callers[] = { bitwiseMaskOrCaller, bitwiseMaskOrCaller, bitwiseMaskOrCaller, bitwiseMaskOrCaller, bitwiseMaskOrCaller, bitwiseMaskOrCaller, bitwiseMaskOrCaller }; CV_Assert(src1.size() == src2.size() && src1.type() == src2.type()); dst.create(src1.size(), src1.type()); Caller caller = callers[src1.depth()]; CV_Assert(caller); int cn = dst.depth() != CV_64F ? dst.channels() : dst.channels() * (sizeof(double) / sizeof(unsigned int)); caller(dst.rows, dst.cols, cn, src1, src2, mask, dst, stream); } void bitwiseAndCaller(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, cudaStream_t stream) { CV_Assert(src1.size() == src2.size() && src1.type() == src2.type()); dst.create(src1.size(), src1.type()); ::cv::gpu::device::bitwiseAndCaller(dst.rows, dst.cols, dst.elemSize1(), dst.channels(), src1, src2, dst, stream); } void bitwiseAndCaller(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, const GpuMat& mask, cudaStream_t stream) { using namespace ::cv::gpu::device; typedef void (*Caller)(int, int, int, const PtrStepb, const PtrStepb, const PtrStepb, PtrStepb, cudaStream_t); static Caller callers[] = { bitwiseMaskAndCaller, bitwiseMaskAndCaller, bitwiseMaskAndCaller, bitwiseMaskAndCaller, bitwiseMaskAndCaller, bitwiseMaskAndCaller, bitwiseMaskAndCaller }; CV_Assert(src1.size() == src2.size() && src1.type() == src2.type()); dst.create(src1.size(), src1.type()); Caller caller = callers[src1.depth()]; CV_Assert(caller); int cn = dst.depth() != CV_64F ? dst.channels() : dst.channels() * (sizeof(double) / sizeof(unsigned int)); caller(dst.rows, dst.cols, cn, src1, src2, mask, dst, stream); } void bitwiseXorCaller(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, cudaStream_t stream) { CV_Assert(src1.size() == src2.size() && src1.type() == src2.type()); dst.create(src1.size(), src1.type()); ::cv::gpu::device::bitwiseXorCaller(dst.rows, dst.cols, dst.elemSize1(), dst.channels(), src1, src2, dst, stream); } void bitwiseXorCaller(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, const GpuMat& mask, cudaStream_t stream) { using namespace ::cv::gpu::device; typedef void (*Caller)(int, int, int, const PtrStepb, const PtrStepb, const PtrStepb, PtrStepb, cudaStream_t); static Caller callers[] = { bitwiseMaskXorCaller, bitwiseMaskXorCaller, bitwiseMaskXorCaller, bitwiseMaskXorCaller, bitwiseMaskXorCaller, bitwiseMaskXorCaller, bitwiseMaskXorCaller }; CV_Assert(src1.size() == src2.size() && src1.type() == src2.type()); dst.create(src1.size(), src1.type()); Caller caller = callers[src1.depth()]; CV_Assert(caller); int cn = dst.depth() != CV_64F ? dst.channels() : dst.channels() * (sizeof(double) / sizeof(unsigned int)); caller(dst.rows, dst.cols, cn, src1, src2, mask, dst, stream); } } void cv::gpu::bitwise_or(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, const GpuMat& mask, Stream& stream) { if (mask.empty()) bitwiseOrCaller(src1, src2, dst, StreamAccessor::getStream(stream)); else bitwiseOrCaller(src1, src2, dst, mask, StreamAccessor::getStream(stream)); } void cv::gpu::bitwise_and(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, const GpuMat& mask, Stream& stream) { if (mask.empty()) bitwiseAndCaller(src1, src2, dst, StreamAccessor::getStream(stream)); else bitwiseAndCaller(src1, src2, dst, mask, StreamAccessor::getStream(stream)); } void cv::gpu::bitwise_xor(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, const GpuMat& mask, Stream& stream) { if (mask.empty()) bitwiseXorCaller(src1, src2, dst, StreamAccessor::getStream(stream)); else bitwiseXorCaller(src1, src2, dst, mask, StreamAccessor::getStream(stream)); } namespace { template struct NppBitwiseCFunc { typedef typename NppTypeTraits::npp_t npp_t; typedef NppStatus (*func_t)(const npp_t* pSrc1, int nSrc1Step, const npp_t* pConstants, npp_t* pDst, int nDstStep, NppiSize oSizeROI); }; template struct NppBitwiseCFunc { typedef typename NppTypeTraits::npp_t npp_t; typedef NppStatus (*func_t)(const npp_t* pSrc1, int nSrc1Step, const npp_t pConstant, npp_t* pDst, int nDstStep, NppiSize oSizeROI); }; template ::func_t func> struct NppBitwiseC { typedef typename NppBitwiseCFunc::npp_t npp_t; static void call(const GpuMat& src, Scalar sc, GpuMat& dst, cudaStream_t stream) { NppStreamHandler h(stream); NppiSize oSizeROI; oSizeROI.width = src.cols; oSizeROI.height = src.rows; const npp_t pConstants[] = {static_cast(sc.val[0]), static_cast(sc.val[1]), static_cast(sc.val[2]), static_cast(sc.val[3])}; nppSafeCall( func(src.ptr(), static_cast(src.step), pConstants, dst.ptr(), static_cast(dst.step), oSizeROI) ); if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); } }; template ::func_t func> struct NppBitwiseC { typedef typename NppBitwiseCFunc::npp_t npp_t; static void call(const GpuMat& src, Scalar sc, GpuMat& dst, cudaStream_t stream) { NppStreamHandler h(stream); NppiSize oSizeROI; oSizeROI.width = src.cols; oSizeROI.height = src.rows; nppSafeCall( func(src.ptr(), static_cast(src.step), static_cast(sc.val[0]), dst.ptr(), static_cast(dst.step), oSizeROI) ); if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); } }; } void cv::gpu::bitwise_or(const GpuMat& src, const Scalar& sc, GpuMat& dst, Stream& stream) { typedef void (*func_t)(const GpuMat& src, Scalar sc, GpuMat& dst, cudaStream_t stream); static const func_t funcs[5][4] = { {NppBitwiseC::call, 0, NppBitwiseC::call, NppBitwiseC::call}, {0,0,0,0}, {NppBitwiseC::call, 0, NppBitwiseC::call, NppBitwiseC::call}, {0,0,0,0}, {NppBitwiseC::call, 0, NppBitwiseC::call, NppBitwiseC::call} }; CV_Assert(src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32S); CV_Assert(src.channels() == 1 || src.channels() == 3 || src.channels() == 4); dst.create(src.size(), src.type()); funcs[src.depth()][src.channels() - 1](src, sc, dst, StreamAccessor::getStream(stream)); } void cv::gpu::bitwise_and(const GpuMat& src, const Scalar& sc, GpuMat& dst, Stream& stream) { typedef void (*func_t)(const GpuMat& src, Scalar sc, GpuMat& dst, cudaStream_t stream); static const func_t funcs[5][4] = { {NppBitwiseC::call, 0, NppBitwiseC::call, NppBitwiseC::call}, {0,0,0,0}, {NppBitwiseC::call, 0, NppBitwiseC::call, NppBitwiseC::call}, {0,0,0,0}, {NppBitwiseC::call, 0, NppBitwiseC::call, NppBitwiseC::call} }; CV_Assert(src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32S); CV_Assert(src.channels() == 1 || src.channels() == 3 || src.channels() == 4); dst.create(src.size(), src.type()); funcs[src.depth()][src.channels() - 1](src, sc, dst, StreamAccessor::getStream(stream)); } void cv::gpu::bitwise_xor(const GpuMat& src, const Scalar& sc, GpuMat& dst, Stream& stream) { typedef void (*func_t)(const GpuMat& src, Scalar sc, GpuMat& dst, cudaStream_t stream); static const func_t funcs[5][4] = { {NppBitwiseC::call, 0, NppBitwiseC::call, NppBitwiseC::call}, {0,0,0,0}, {NppBitwiseC::call, 0, NppBitwiseC::call, NppBitwiseC::call}, {0,0,0,0}, {NppBitwiseC::call, 0, NppBitwiseC::call, NppBitwiseC::call} }; CV_Assert(src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32S); CV_Assert(src.channels() == 1 || src.channels() == 3 || src.channels() == 4); dst.create(src.size(), src.type()); funcs[src.depth()][src.channels() - 1](src, sc, dst, StreamAccessor::getStream(stream)); } ////////////////////////////////////////////////////////////////////////////// // shift namespace { template struct NppShiftFunc { typedef typename NppTypeTraits::npp_t npp_t; typedef NppStatus (*func_t)(const npp_t* pSrc1, int nSrc1Step, const Npp32u* pConstants, npp_t* pDst, int nDstStep, NppiSize oSizeROI); }; template struct NppShiftFunc { typedef typename NppTypeTraits::npp_t npp_t; typedef NppStatus (*func_t)(const npp_t* pSrc1, int nSrc1Step, const Npp32u pConstants, npp_t* pDst, int nDstStep, NppiSize oSizeROI); }; template ::func_t func> struct NppShift { typedef typename NppTypeTraits::npp_t npp_t; static void call(const GpuMat& src, Scalar_ sc, GpuMat& dst, cudaStream_t stream) { NppStreamHandler h(stream); NppiSize oSizeROI; oSizeROI.width = src.cols; oSizeROI.height = src.rows; nppSafeCall( func(src.ptr(), static_cast(src.step), sc.val, dst.ptr(), static_cast(dst.step), oSizeROI) ); if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); } }; template ::func_t func> struct NppShift { typedef typename NppTypeTraits::npp_t npp_t; static void call(const GpuMat& src, Scalar_ sc, GpuMat& dst, cudaStream_t stream) { NppStreamHandler h(stream); NppiSize oSizeROI; oSizeROI.width = src.cols; oSizeROI.height = src.rows; nppSafeCall( func(src.ptr(), static_cast(src.step), sc.val[0], dst.ptr(), static_cast(dst.step), oSizeROI) ); if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); } }; } void cv::gpu::rshift(const GpuMat& src, const Scalar& sc, GpuMat& dst, Stream& stream) { typedef void (*func_t)(const GpuMat& src, Scalar_ sc, GpuMat& dst, cudaStream_t stream); static const func_t funcs[5][4] = { {NppShift::call, 0, NppShift::call, NppShift::call }, {NppShift::call, 0, NppShift::call, NppShift::call }, {NppShift::call, 0, NppShift::call, NppShift::call}, {NppShift::call, 0, NppShift::call, NppShift::call}, {NppShift::call, 0, NppShift::call, NppShift::call}, }; CV_Assert(src.depth() < CV_32F); CV_Assert(src.channels() == 1 || src.channels() == 3 || src.channels() == 4); dst.create(src.size(), src.type()); funcs[src.depth()][src.channels() - 1](src, sc, dst, StreamAccessor::getStream(stream)); } void cv::gpu::lshift(const GpuMat& src, const Scalar& sc, GpuMat& dst, Stream& stream) { typedef void (*func_t)(const GpuMat& src, Scalar_ sc, GpuMat& dst, cudaStream_t stream); static const func_t funcs[5][4] = { {NppShift::call , 0, NppShift::call , NppShift::call }, {0 , 0, 0 , 0 }, {NppShift::call, 0, NppShift::call, NppShift::call}, {0 , 0, 0 , 0 }, {NppShift::call, 0, NppShift::call, NppShift::call}, }; CV_Assert(src.depth() == CV_8U || src.depth() == CV_16U || src.depth() == CV_32S); CV_Assert(src.channels() == 1 || src.channels() == 3 || src.channels() == 4); dst.create(src.size(), src.type()); funcs[src.depth()][src.channels() - 1](src, sc, dst, StreamAccessor::getStream(stream)); } ////////////////////////////////////////////////////////////////////////////// // Minimum and maximum operations namespace cv { namespace gpu { namespace device { template void min_gpu(const DevMem2D_& src1, const DevMem2D_& src2, const DevMem2D_& dst, cudaStream_t stream); template void max_gpu(const DevMem2D_& src1, const DevMem2D_& src2, const DevMem2D_& dst, cudaStream_t stream); template void min_gpu(const DevMem2D_& src1, T src2, const DevMem2D_& dst, cudaStream_t stream); template void max_gpu(const DevMem2D_& src1, T src2, const DevMem2D_& dst, cudaStream_t stream); }}} namespace { template void min_caller(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, cudaStream_t stream) { CV_Assert(src1.size() == src2.size() && src1.type() == src2.type()); dst.create(src1.size(), src1.type()); ::cv::gpu::device::min_gpu(src1.reshape(1), src2.reshape(1), dst.reshape(1), stream); } template void min_caller(const GpuMat& src1, double src2, GpuMat& dst, cudaStream_t stream) { dst.create(src1.size(), src1.type()); ::cv::gpu::device::min_gpu(src1.reshape(1), saturate_cast(src2), dst.reshape(1), stream); } template void max_caller(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, cudaStream_t stream) { CV_Assert(src1.size() == src2.size() && src1.type() == src2.type()); dst.create(src1.size(), src1.type()); ::cv::gpu::device::max_gpu(src1.reshape(1), src2.reshape(1), dst.reshape(1), stream); } template void max_caller(const GpuMat& src1, double src2, GpuMat& dst, cudaStream_t stream) { dst.create(src1.size(), src1.type()); ::cv::gpu::device::max_gpu(src1.reshape(1), saturate_cast(src2), dst.reshape(1), stream); } } void cv::gpu::min(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, Stream& stream) { CV_Assert(src1.size() == src2.size() && src1.type() == src2.type()); CV_Assert((src1.depth() != CV_64F) || (TargetArchs::builtWith(NATIVE_DOUBLE) && DeviceInfo().supports(NATIVE_DOUBLE))); typedef void (*func_t)(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, cudaStream_t stream); static const func_t funcs[] = { min_caller, min_caller, min_caller, min_caller, min_caller, min_caller, min_caller }; funcs[src1.depth()](src1, src2, dst, StreamAccessor::getStream(stream)); } void cv::gpu::min(const GpuMat& src1, double src2, GpuMat& dst, Stream& stream) { CV_Assert((src1.depth() != CV_64F) || (TargetArchs::builtWith(NATIVE_DOUBLE) && DeviceInfo().supports(NATIVE_DOUBLE))); typedef void (*func_t)(const GpuMat& src1, double src2, GpuMat& dst, cudaStream_t stream); static const func_t funcs[] = { min_caller, min_caller, min_caller, min_caller, min_caller, min_caller, min_caller }; funcs[src1.depth()](src1, src2, dst, StreamAccessor::getStream(stream)); } void cv::gpu::max(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, Stream& stream) { CV_Assert(src1.size() == src2.size() && src1.type() == src2.type()); CV_Assert((src1.depth() != CV_64F) || (TargetArchs::builtWith(NATIVE_DOUBLE) && DeviceInfo().supports(NATIVE_DOUBLE))); typedef void (*func_t)(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, cudaStream_t stream); static const func_t funcs[] = { max_caller, max_caller, max_caller, max_caller, max_caller, max_caller, max_caller }; funcs[src1.depth()](src1, src2, dst, StreamAccessor::getStream(stream)); } void cv::gpu::max(const GpuMat& src1, double src2, GpuMat& dst, Stream& stream) { CV_Assert((src1.depth() != CV_64F) || (TargetArchs::builtWith(NATIVE_DOUBLE) && DeviceInfo().supports(NATIVE_DOUBLE))); typedef void (*func_t)(const GpuMat& src1, double src2, GpuMat& dst, cudaStream_t stream); static const func_t funcs[] = { max_caller, max_caller, max_caller, max_caller, max_caller, max_caller, max_caller }; funcs[src1.depth()](src1, src2, dst, StreamAccessor::getStream(stream)); } //////////////////////////////////////////////////////////////////////// // threshold namespace cv { namespace gpu { namespace device { template void threshold_gpu(const DevMem2Db& src, const DevMem2Db& dst, T thresh, T maxVal, int type, cudaStream_t stream); }}} namespace { template void threshold_caller(const GpuMat& src, GpuMat& dst, double thresh, double maxVal, int type, cudaStream_t stream) { cv::gpu::device::threshold_gpu(src, dst, saturate_cast(thresh), saturate_cast(maxVal), type, stream); } } double cv::gpu::threshold(const GpuMat& src, GpuMat& dst, double thresh, double maxVal, int type, Stream& s) { CV_Assert(src.channels() == 1 && src.depth() <= CV_64F); CV_Assert(type <= THRESH_TOZERO_INV); dst.create(src.size(), src.type()); cudaStream_t stream = StreamAccessor::getStream(s); if (src.type() == CV_32FC1 && type == THRESH_TRUNC) { NppStreamHandler h(stream); NppiSize sz; sz.width = src.cols; sz.height = src.rows; nppSafeCall( nppiThreshold_32f_C1R(src.ptr(), static_cast(src.step), dst.ptr(), static_cast(dst.step), sz, static_cast(thresh), NPP_CMP_GREATER) ); if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); } else { typedef void (*caller_t)(const GpuMat& src, GpuMat& dst, double thresh, double maxVal, int type, cudaStream_t stream); static const caller_t callers[] = { threshold_caller, threshold_caller, threshold_caller, threshold_caller, threshold_caller, threshold_caller, threshold_caller }; if (src.depth() != CV_32F && src.depth() != CV_64F) { thresh = cvFloor(thresh); maxVal = cvRound(maxVal); } callers[src.depth()](src, dst, thresh, maxVal, type, stream); } return thresh; } //////////////////////////////////////////////////////////////////////// // pow namespace cv { namespace gpu { namespace device { template void pow_caller(const DevMem2Db& src, float power, DevMem2Db dst, cudaStream_t stream); }}} void cv::gpu::pow(const GpuMat& src, double power, GpuMat& dst, Stream& stream) { using namespace ::cv::gpu::device; CV_Assert(src.depth() != CV_64F); dst.create(src.size(), src.type()); typedef void (*caller_t)(const DevMem2Db& src, float power, DevMem2Db dst, cudaStream_t stream); static const caller_t callers[] = { pow_caller, pow_caller, pow_caller, pow_caller, pow_caller, pow_caller }; callers[src.depth()](src.reshape(1), (float)power, dst.reshape(1), StreamAccessor::getStream(stream)); } //////////////////////////////////////////////////////////////////////// // alphaComp namespace { template struct NppAlphaCompFunc { typedef typename NppTypeTraits::npp_t npp_t; typedef NppStatus (*func_t)(const npp_t* pSrc1, int nSrc1Step, const npp_t* pSrc2, int nSrc2Step, npp_t* pDst, int nDstStep, NppiSize oSizeROI, NppiAlphaOp eAlphaOp); }; template ::func_t func> struct NppAlphaComp { typedef typename NppTypeTraits::npp_t npp_t; static void call(const GpuMat& img1, const GpuMat& img2, GpuMat& dst, NppiAlphaOp eAlphaOp, cudaStream_t stream) { NppStreamHandler h(stream); NppiSize oSizeROI; oSizeROI.width = img1.cols; oSizeROI.height = img2.rows; nppSafeCall( func(img1.ptr(), static_cast(img1.step), img2.ptr(), static_cast(img2.step), dst.ptr(), static_cast(dst.step), oSizeROI, eAlphaOp) ); if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); } }; } void cv::gpu::alphaComp(const GpuMat& img1, const GpuMat& img2, GpuMat& dst, int alpha_op, Stream& stream) { static const NppiAlphaOp npp_alpha_ops[] = { NPPI_OP_ALPHA_OVER, NPPI_OP_ALPHA_IN, NPPI_OP_ALPHA_OUT, NPPI_OP_ALPHA_ATOP, NPPI_OP_ALPHA_XOR, NPPI_OP_ALPHA_PLUS, NPPI_OP_ALPHA_OVER_PREMUL, NPPI_OP_ALPHA_IN_PREMUL, NPPI_OP_ALPHA_OUT_PREMUL, NPPI_OP_ALPHA_ATOP_PREMUL, NPPI_OP_ALPHA_XOR_PREMUL, NPPI_OP_ALPHA_PLUS_PREMUL, NPPI_OP_ALPHA_PREMUL }; typedef void (*func_t)(const GpuMat& img1, const GpuMat& img2, GpuMat& dst, NppiAlphaOp eAlphaOp, cudaStream_t stream); static const func_t funcs[] = { NppAlphaComp::call, 0, NppAlphaComp::call, 0, NppAlphaComp::call, NppAlphaComp::call, 0 }; CV_Assert(img1.type() == CV_8UC4 || img1.type() == CV_16UC4 || img1.type() == CV_32SC4 || img1.type() == CV_32FC4); CV_Assert(img1.size() == img2.size() && img1.type() == img2.type()); dst.create(img1.size(), img1.type()); const func_t func = funcs[img1.depth()]; CV_Assert(func != 0); func(img1, img2, dst, npp_alpha_ops[alpha_op], StreamAccessor::getStream(stream)); } //////////////////////////////////////////////////////////////////////// // addWeighted namespace cv { namespace gpu { namespace device { template void addWeighted_gpu(const DevMem2Db& src1, double alpha, const DevMem2Db& src2, double beta, double gamma, const DevMem2Db& dst, cudaStream_t stream); }}} void cv::gpu::addWeighted(const GpuMat& src1, double alpha, const GpuMat& src2, double beta, double gamma, GpuMat& dst, int dtype, Stream& stream) { using namespace ::cv::gpu::device; CV_Assert(src1.size() == src2.size()); CV_Assert(src1.type() == src2.type() || (dtype >= 0 && src1.channels() == src2.channels())); dtype = dtype >= 0 ? CV_MAKETYPE(dtype, src1.channels()) : src1.type(); dst.create(src1.size(), dtype); const GpuMat* psrc1 = &src1; const GpuMat* psrc2 = &src2; if (src1.depth() > src2.depth()) { std::swap(psrc1, psrc2); std::swap(alpha, beta); } typedef void (*caller_t)(const DevMem2Db& src1, double alpha, const DevMem2Db& src2, double beta, double gamma, const DevMem2Db& dst, cudaStream_t stream); static const caller_t callers[7][7][7] = { { { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu } }, { { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu } }, { { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu } }, { { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu } }, { { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu } }, { { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu } }, { { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu } } }; callers[psrc1->depth()][psrc2->depth()][dst.depth()](psrc1->reshape(1), alpha, psrc2->reshape(1), beta, gamma, dst.reshape(1), StreamAccessor::getStream(stream)); } #endif