/*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) || defined (CUDA_DISABLER) 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&, Scalar_, GpuMat&, Stream&) { throw_nogpu(); } void cv::gpu::lshift(const GpuMat&, 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 { 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 NppArithmFunc { 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, int nScaleFactor); }; template <> struct NppArithmFunc { typedef NppTypeTraits::npp_t npp_t; typedef NppStatus (*func_t)(const Npp32f* pSrc1, int nSrc1Step, const Npp32f* pSrc2, int nSrc2Step, Npp32f* pDst, int nDstStep, NppiSize oSizeROI); }; template ::func_t func> struct NppArithm { typedef typename NppArithmFunc::npp_t npp_t; static void call(const PtrStepSzb src1, const PtrStepb src2, PtrStepb 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), (const npp_t*)src2.data, static_cast(src2.step), (npp_t*)dst.data, static_cast(dst.step), sz, 0) ); if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); } }; template ::func_t func> struct NppArithm { typedef typename NppArithmFunc::npp_t npp_t; static void call(const PtrStepSzb src1, const PtrStepb src2, PtrStepb 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), (const npp_t*)src2.data, static_cast(src2.step), (npp_t*)dst.data, static_cast(dst.step), sz) ); if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); } }; 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 PtrStepSzb src, Scalar sc, PtrStepb 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((const npp_t*)src.data, static_cast(src.step), pConstants, (npp_t*)dst.data, 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 PtrStepSzb src, Scalar sc, PtrStepb dst, cudaStream_t stream) { NppStreamHandler h(stream); NppiSize sz; sz.width = src.cols; sz.height = src.rows; nppSafeCall( func((const npp_t*)src.data, static_cast(src.step), saturate_cast(sc.val[0]), (npp_t*)dst.data, 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 PtrStepSzb src, Scalar sc, PtrStepb 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((const npp_complex_type*)src.data, static_cast(src.step), nConstant, (npp_complex_type*)dst.data, 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 PtrStepSzb src, Scalar sc, PtrStepb 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((const npp_t*)src.data, static_cast(src.step), pConstants, (npp_t*)dst.data, static_cast(dst.step), sz) ); if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); } }; template::func_ptr func> struct NppArithmScalar { typedef typename NppTypeTraits::npp_t npp_t; static void call(const PtrStepSzb src, Scalar sc, PtrStepb dst, cudaStream_t stream) { NppStreamHandler h(stream); NppiSize sz; sz.width = src.cols; sz.height = src.rows; nppSafeCall( func((const npp_t*)src.data, static_cast(src.step), saturate_cast(sc.val[0]), (npp_t*)dst.data, static_cast(dst.step), sz) ); 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 PtrStepSzb src, Scalar sc, PtrStepb 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((const npp_complex_type*)src.data, static_cast(src.step), nConstant, (npp_complex_type*)dst.data, static_cast(dst.step), sz) ); if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); } }; } //////////////////////////////////////////////////////////////////////// // add namespace cv { namespace gpu { namespace device { template void add_gpu(const PtrStepSzb& src1, const PtrStepSzb& src2, const PtrStepSzb& dst, const PtrStepb& mask, cudaStream_t stream); template void add_gpu(const PtrStepSzb& src1, double val, const PtrStepSzb& 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 PtrStepSzb& src1, const PtrStepSzb& src2, const PtrStepSzb& 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 PtrStepSzb src1, const PtrStepb src2, PtrStepb dst, cudaStream_t stream); static const npp_func_t npp_funcs[] = { NppArithm::call, 0, NppArithm::call, NppArithm::call, NppArithm::call, NppArithm::call }; if (dtype < 0) dtype = src1.depth(); CV_Assert(src1.depth() <= CV_64F && CV_MAT_DEPTH(dtype) <= CV_64F); 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 (src1.depth() == CV_64F || CV_MAT_DEPTH(dtype) == CV_64F) { if (!TargetArchs::builtWith(NATIVE_DOUBLE) || !DeviceInfo().supports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } 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() && src1.depth() <= CV_32F) { npp_funcs[src1.depth()](src1.reshape(1), src2.reshape(1), dst.reshape(1), stream); return; } const func_t func = funcs[src1.depth()][dst.depth()]; if (!func) CV_Error(CV_StsUnsupportedFormat, "Unsupported combination of source and destination types"); func(src1.reshape(1), src2.reshape(1), dst.reshape(1), mask, stream); } 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 PtrStepSzb& src1, double val, const PtrStepSzb& 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 PtrStepSzb src, Scalar sc, PtrStepb 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 } }; if (dtype < 0) dtype = src.depth(); CV_Assert(src.depth() <= CV_64F && CV_MAT_DEPTH(dtype) <= CV_64F); CV_Assert(src.channels() <= 4); CV_Assert(mask.empty() || (src.channels() == 1 && mask.size() == src.size() && mask.type() == CV_8U)); if (src.depth() == CV_64F || CV_MAT_DEPTH(dtype) == CV_64F) { if (!TargetArchs::builtWith(NATIVE_DOUBLE) || !DeviceInfo().supports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } 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()]; if (!func) CV_Error(CV_StsUnsupportedFormat, "Unsupported combination of source and destination types"); func(src, sc.val[0], dst, mask, stream); } //////////////////////////////////////////////////////////////////////// // subtract namespace cv { namespace gpu { namespace device { template void subtract_gpu(const PtrStepSzb& src1, const PtrStepSzb& src2, const PtrStepSzb& dst, const PtrStepb& mask, cudaStream_t stream); template void subtract_gpu(const PtrStepSzb& src1, double val, const PtrStepSzb& 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 PtrStepSzb& src1, const PtrStepSzb& src2, const PtrStepSzb& 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 PtrStepSzb src1, const PtrStepb src2, PtrStepb dst, cudaStream_t stream); static const npp_func_t npp_funcs[6] = { NppArithm::call, 0, NppArithm::call, NppArithm::call, NppArithm::call, NppArithm::call }; if (dtype < 0) dtype = src1.depth(); CV_Assert(src1.depth() <= CV_64F && CV_MAT_DEPTH(dtype) <= CV_64F); 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 (src1.depth() == CV_64F || CV_MAT_DEPTH(dtype) == CV_64F) { if (!TargetArchs::builtWith(NATIVE_DOUBLE) || !DeviceInfo().supports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } 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() && src1.depth() <= CV_32F) { npp_funcs[src1.depth()](src2.reshape(1), src1.reshape(1), dst.reshape(1), stream); return; } const func_t func = funcs[src1.depth()][dst.depth()]; if (!func) CV_Error(CV_StsUnsupportedFormat, "Unsupported combination of source and destination types"); 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 PtrStepSzb& src1, double val, const PtrStepSzb& 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 PtrStepSzb src, Scalar sc, PtrStepb 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 } }; if (dtype < 0) dtype = src.depth(); CV_Assert(src.depth() <= CV_64F && CV_MAT_DEPTH(dtype) <= CV_64F); CV_Assert(src.channels() <= 4); CV_Assert(mask.empty() || (src.channels() == 1 && mask.size() == src.size() && mask.type() == CV_8U)); if (src.depth() == CV_64F || CV_MAT_DEPTH(dtype) == CV_64F) { if (!TargetArchs::builtWith(NATIVE_DOUBLE) || !DeviceInfo().supports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } 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()]; if (!func) CV_Error(CV_StsUnsupportedFormat, "Unsupported combination of source and destination types"); func(src, sc.val[0], dst, mask, stream); } //////////////////////////////////////////////////////////////////////// // multiply namespace cv { namespace gpu { namespace device { void multiply_gpu(const PtrStepSz& src1, const PtrStepSzf& src2, const PtrStepSz& dst, cudaStream_t stream); void multiply_gpu(const PtrStepSz& src1, const PtrStepSzf& src2, const PtrStepSz& dst, cudaStream_t stream); template void multiply_gpu(const PtrStepSzb& src1, const PtrStepSzb& src2, const PtrStepSzb& dst, double scale, cudaStream_t stream); template void multiply_gpu(const PtrStepSzb& src1, double val, const PtrStepSzb& 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; 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 { typedef void (*func_t)(const PtrStepSzb& src1, const PtrStepSzb& src2, const PtrStepSzb& 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 PtrStepSzb src1, const PtrStepb src2, PtrStepb dst, cudaStream_t stream); static const npp_func_t npp_funcs[] = { NppArithm::call, 0, NppArithm::call, NppArithm::call, NppArithm::call, NppArithm::call }; if (dtype < 0) dtype = src1.depth(); CV_Assert(src1.depth() <= CV_64F && CV_MAT_DEPTH(dtype) <= CV_64F); CV_Assert(src1.type() == src2.type() && src1.size() == src2.size()); if (src1.depth() == CV_64F || CV_MAT_DEPTH(dtype) == CV_64F) { if (!TargetArchs::builtWith(NATIVE_DOUBLE) || !DeviceInfo().supports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } dst.create(src1.size(), CV_MAKE_TYPE(CV_MAT_DEPTH(dtype), src1.channels())); #if (CUDA_VERSION <= 4020) if (scale == 1 && dst.type() == src1.type() && src1.depth() <= CV_32F) #else if (scale == 1 && dst.type() == src1.type() && src1.depth() <= CV_32F && src1.depth() > CV_8U) #endif { npp_funcs[src1.depth()](src1.reshape(1), src2.reshape(1), dst.reshape(1), stream); return; } const func_t func = funcs[src1.depth()][dst.depth()]; if (!func) CV_Error(CV_StsUnsupportedFormat, "Unsupported combination of source and destination types"); func(src1.reshape(1), src2.reshape(1), dst.reshape(1), scale, stream); } } namespace { inline bool isIntScalar(Scalar sc) { return sc.val[0] == static_cast(sc.val[0]) && sc.val[1] == static_cast(sc.val[1]) && sc.val[2] == static_cast(sc.val[2]) && sc.val[3] == static_cast(sc.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 PtrStepSzb& src1, double val, const PtrStepSzb& 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 PtrStepSzb src, Scalar sc, PtrStepb 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(); CV_Assert(src.depth() <= CV_64F && CV_MAT_DEPTH(dtype) <= CV_64F); CV_Assert(src.channels() <= 4); if (src.depth() == CV_64F || CV_MAT_DEPTH(dtype) == CV_64F) { if (!TargetArchs::builtWith(NATIVE_DOUBLE) || !DeviceInfo().supports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } 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 && (src.depth() == CV_32F || isIntScalar(sc))) { 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()]; if (!func) CV_Error(CV_StsUnsupportedFormat, "Unsupported combination of source and destination types"); func(src, sc.val[0], dst, scale, stream); } //////////////////////////////////////////////////////////////////////// // divide namespace cv { namespace gpu { namespace device { void divide_gpu(const PtrStepSz& src1, const PtrStepSzf& src2, const PtrStepSz& dst, cudaStream_t stream); void divide_gpu(const PtrStepSz& src1, const PtrStepSzf& src2, const PtrStepSz& dst, cudaStream_t stream); template void divide_gpu(const PtrStepSzb& src1, const PtrStepSzb& src2, const PtrStepSzb& dst, double scale, cudaStream_t stream); template void divide_gpu(const PtrStepSzb& src1, double val, const PtrStepSzb& dst, double scale, cudaStream_t stream); template void divide_gpu(double scalar, const PtrStepSzb& src2, const PtrStepSzb& 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; 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()); divide_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()); divide_gpu(static_cast >(src1), static_cast(src2), static_cast >(dst), stream); } else { typedef void (*func_t)(const PtrStepSzb& src1, const PtrStepSzb& src2, const PtrStepSzb& 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 PtrStepSzb src1, const PtrStepb src2, PtrStepb dst, cudaStream_t stream); static const npp_func_t npp_funcs[6] = { NppArithm::call, 0, NppArithm::call, NppArithm::call, NppArithm::call, NppArithm::call }; if (dtype < 0) dtype = src1.depth(); CV_Assert(src1.depth() <= CV_64F && CV_MAT_DEPTH(dtype) <= CV_64F); CV_Assert(src1.type() == src2.type() && src1.size() == src2.size()); if (src1.depth() == CV_64F || CV_MAT_DEPTH(dtype) == CV_64F) { if (!TargetArchs::builtWith(NATIVE_DOUBLE) || !DeviceInfo().supports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } dst.create(src1.size(), CV_MAKE_TYPE(CV_MAT_DEPTH(dtype), src1.channels())); if (scale == 1 && dst.type() == src1.type() && src1.depth() <= CV_32F) { npp_funcs[src1.depth()](src2.reshape(1), src1.reshape(1), dst.reshape(1), stream); return; } const func_t func = funcs[src1.depth()][dst.depth()]; if (!func) CV_Error(CV_StsUnsupportedFormat, "Unsupported combination of source and destination types"); 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 PtrStepSzb& src1, double val, const PtrStepSzb& 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 PtrStepSzb src, Scalar sc, PtrStepb 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(); CV_Assert(src.depth() <= CV_64F && CV_MAT_DEPTH(dtype) <= CV_64F); CV_Assert(src.channels() <= 4); if (src.depth() == CV_64F || CV_MAT_DEPTH(dtype) == CV_64F) { if (!TargetArchs::builtWith(NATIVE_DOUBLE) || !DeviceInfo().supports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } 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 && (src.depth() == CV_32F || isIntScalar(sc))) { 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()]; if (!func) CV_Error(CV_StsUnsupportedFormat, "Unsupported combination of source and destination types"); func(src, sc.val[0], dst, 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 PtrStepSzb& src2, const PtrStepSzb& 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 } }; if (dtype < 0) dtype = src.depth(); CV_Assert(src.depth() <= CV_64F && CV_MAT_DEPTH(dtype) <= CV_64F); CV_Assert(src.channels() == 1); if (src.depth() == CV_64F || CV_MAT_DEPTH(dtype) == CV_64F) { if (!TargetArchs::builtWith(NATIVE_DOUBLE) || !DeviceInfo().supports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } 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()]; if (!func) CV_Error(CV_StsUnsupportedFormat, "Unsupported combination of source and destination types"); func(scale, src, dst, stream); } ////////////////////////////////////////////////////////////////////////////// // absdiff namespace cv { namespace gpu { namespace device { template void absdiff_gpu(const PtrStepSzb src1, const PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); template void absdiff_gpu(const PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); }}} namespace { template struct NppAbsDiffFunc { typedef typename NppTypeTraits::npp_t npp_t; typedef NppStatus (*func_t)(const npp_t* src1, int src1_step, const npp_t* src2, int src2_step, npp_t* dst, int dst_step, NppiSize sz); }; template ::func_t func> struct NppAbsDiff { typedef typename NppAbsDiffFunc::npp_t npp_t; static void call(const PtrStepSzb src1, const PtrStepSzb src2, PtrStepSzb 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), (const npp_t*)src2.data, static_cast(src2.step), (npp_t*)dst.data, static_cast(dst.step), sz) ); if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); } }; template struct NppAbsDiffCFunc { typedef typename NppTypeTraits::npp_t npp_t; typedef npp_t scalar_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 NppTypeTraits::npp_t npp_t; typedef Npp32u scalar_t; #if (CUDA_VERSION <= 4020) typedef NppStatus (*func_t)(const Npp16u* pSrc1, int nSrc1Step, Npp16u* pDst, int nDstStep, NppiSize oSizeROI, Npp32u nConstant); #else typedef NppStatus (*func_t)(const Npp16u * pSrc1, int nSrc1Step, Npp16u * pDst, int nDstStep, NppiSize oSizeROI, Npp16u nConstant); #endif }; template ::func_t func> struct NppAbsDiffC { typedef typename NppAbsDiffCFunc::npp_t npp_t; typedef typename NppAbsDiffCFunc::scalar_t scalar_t; static void call(const PtrStepSzb src1, double val, PtrStepSzb 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 GpuMat& src2, GpuMat& dst, Stream& stream) { using namespace cv::gpu::device; typedef void (*func_t)(const PtrStepSzb src1, const PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); static const func_t funcs[] = { NppAbsDiff::call, absdiff_gpu, NppAbsDiff::call, absdiff_gpu, absdiff_gpu, NppAbsDiff::call, absdiff_gpu }; CV_Assert(src1.depth() <= CV_64F); CV_Assert(src1.size() == src2.size() && src1.type() == src2.type()); if (src1.depth() == CV_64F) { if (!TargetArchs::builtWith(NATIVE_DOUBLE) || !DeviceInfo().supports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } dst.create(src1.size(), src1.type()); funcs[src1.depth()](src1.reshape(1), src2.reshape(1), dst.reshape(1), StreamAccessor::getStream(stream)); } void cv::gpu::absdiff(const GpuMat& src1, const Scalar& src2, GpuMat& dst, Stream& stream) { using namespace cv::gpu::device; typedef void (*func_t)(const PtrStepSzb src1, double val, PtrStepSzb 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.depth() <= CV_64F); CV_Assert(src1.channels() == 1); if (src1.depth() == CV_64F) { if (!TargetArchs::builtWith(NATIVE_DOUBLE) || !DeviceInfo().supports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } dst.create(src1.size(), src1.type()); funcs[src1.depth()](src1, src2.val[0], dst, StreamAccessor::getStream(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(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); template void compare_ne(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); template void compare_lt(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); template void compare_le(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); template void compare_eq(PtrStepSzb src, int cn, double val[4], PtrStepSzb dst, cudaStream_t stream); template void compare_ne(PtrStepSzb src, int cn, double val[4], PtrStepSzb dst, cudaStream_t stream); template void compare_lt(PtrStepSzb src, int cn, double val[4], PtrStepSzb dst, cudaStream_t stream); template void compare_le(PtrStepSzb src, int cn, double val[4], PtrStepSzb dst, cudaStream_t stream); template void compare_gt(PtrStepSzb src, int cn, double val[4], PtrStepSzb dst, cudaStream_t stream); template void compare_ge(PtrStepSzb src, int cn, double val[4], PtrStepSzb 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)(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb 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.depth() <= CV_64F); CV_Assert(src1.size() == src2.size() && src1.type() == src2.type()); CV_Assert(cmpop >= CMP_EQ && cmpop <= CMP_NE); if (src1.depth() == CV_64F) { if (!TargetArchs::builtWith(NATIVE_DOUBLE) || !DeviceInfo().supports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } static const int codes[] = { 0, 2, 3, 2, 3, 1 }; const GpuMat* psrc1[] = { &src1, &src2, &src2, &src1, &src1, &src1 }; const GpuMat* psrc2[] = { &src2, &src1, &src1, &src2, &src2, &src2 }; dst.create(src1.size(), CV_MAKE_TYPE(CV_8U, src1.channels())); funcs[src1.depth()][codes[cmpop]](psrc1[cmpop]->reshape(1), psrc2[cmpop]->reshape(1), dst.reshape(1), StreamAccessor::getStream(stream)); } namespace { template void castScalar(Scalar& sc) { sc.val[0] = saturate_cast(sc.val[0]); sc.val[1] = saturate_cast(sc.val[1]); sc.val[2] = saturate_cast(sc.val[2]); sc.val[3] = saturate_cast(sc.val[3]); } } ////////////////////////////////////////////////////////////////////////////// // 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 (*func_t)(int, int, int, const PtrStepb, const PtrStepb, PtrStepb, cudaStream_t); static func_t funcs[] = { bitwiseMaskNotCaller, bitwiseMaskNotCaller, bitwiseMaskNotCaller, bitwiseMaskNotCaller, bitwiseMaskNotCaller, bitwiseMaskNotCaller, bitwiseMaskNotCaller }; CV_Assert(src.depth() <= CV_64F); CV_Assert(mask.type() == CV_8U && mask.size() == src.size()); dst.create(src.size(), src.type()); const func_t func = funcs[src.depth()]; int cn = src.depth() != CV_64F ? src.channels() : src.channels() * (sizeof(double) / sizeof(unsigned int)); func(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 (*func_t)(int, int, int, const PtrStepb, const PtrStepb, const PtrStepb, PtrStepb, cudaStream_t); static func_t funcs[] = { bitwiseMaskOrCaller, bitwiseMaskOrCaller, bitwiseMaskOrCaller, bitwiseMaskOrCaller, bitwiseMaskOrCaller, bitwiseMaskOrCaller, bitwiseMaskOrCaller }; CV_Assert(src1.depth() <= CV_64F); CV_Assert(src1.size() == src2.size() && src1.type() == src2.type()); CV_Assert(mask.type() == CV_8U && mask.size() == src1.size()); dst.create(src1.size(), src1.type()); const func_t func = funcs[src1.depth()]; int cn = dst.depth() != CV_64F ? dst.channels() : dst.channels() * (sizeof(double) / sizeof(unsigned int)); func(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 (*func_t)(int, int, int, const PtrStepb, const PtrStepb, const PtrStepb, PtrStepb, cudaStream_t); static func_t funcs[] = { bitwiseMaskAndCaller, bitwiseMaskAndCaller, bitwiseMaskAndCaller, bitwiseMaskAndCaller, bitwiseMaskAndCaller, bitwiseMaskAndCaller, bitwiseMaskAndCaller }; CV_Assert(src1.depth() <= CV_64F); CV_Assert(src1.size() == src2.size() && src1.type() == src2.type()); CV_Assert(mask.type() == CV_8U && mask.size() == src1.size()); dst.create(src1.size(), src1.type()); const func_t func = funcs[src1.depth()]; int cn = dst.depth() != CV_64F ? dst.channels() : dst.channels() * (sizeof(double) / sizeof(unsigned int)); func(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 (*func_t)(int, int, int, const PtrStepb, const PtrStepb, const PtrStepb, PtrStepb, cudaStream_t); static func_t funcs[] = { bitwiseMaskXorCaller, bitwiseMaskXorCaller, bitwiseMaskXorCaller, bitwiseMaskXorCaller, bitwiseMaskXorCaller, bitwiseMaskXorCaller, bitwiseMaskXorCaller }; CV_Assert(src1.depth() <= CV_64F); CV_Assert(src1.size() == src2.size() && src1.type() == src2.type()); CV_Assert(mask.type() == CV_8U && mask.size() == src1.size()); dst.create(src1.size(), src1.type()); const func_t func = funcs[src1.depth()]; int cn = dst.depth() != CV_64F ? dst.channels() : dst.channels() * (sizeof(double) / sizeof(unsigned int)); func(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, 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, 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 PtrStepSzb src1, const PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); template void max_gpu(const PtrStepSzb src1, const PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); template void min_gpu(const PtrStepSzb src, T val, PtrStepSzb dst, cudaStream_t stream); template void max_gpu(const PtrStepSzb src, T val, PtrStepSzb dst, cudaStream_t stream); }}} void cv::gpu::min(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, Stream& stream) { using namespace cv::gpu::device; typedef void (*func_t)(const PtrStepSzb src1, const PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); static const func_t funcs[] = { min_gpu, min_gpu, min_gpu, min_gpu, min_gpu, min_gpu, min_gpu }; CV_Assert(src1.depth() <= CV_64F); CV_Assert(src1.size() == src2.size() && src1.type() == src2.type()); if (src1.depth() == CV_64F) { if (!TargetArchs::builtWith(NATIVE_DOUBLE) || !DeviceInfo().supports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } dst.create(src1.size(), src1.type()); funcs[src1.depth()](src1.reshape(1), src2.reshape(1), dst.reshape(1), StreamAccessor::getStream(stream)); } void cv::gpu::max(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, Stream& stream) { using namespace cv::gpu::device; typedef void (*func_t)(const PtrStepSzb src1, const PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); static const func_t funcs[] = { max_gpu, max_gpu, max_gpu, max_gpu, max_gpu, max_gpu, max_gpu }; CV_Assert(src1.depth() <= CV_64F); CV_Assert(src1.size() == src2.size() && src1.type() == src2.type()); if (src1.depth() == CV_64F) { if (!TargetArchs::builtWith(NATIVE_DOUBLE) || !DeviceInfo().supports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } dst.create(src1.size(), src1.type()); funcs[src1.depth()](src1.reshape(1), src2.reshape(1), dst.reshape(1), StreamAccessor::getStream(stream)); } namespace { template void minScalar(const PtrStepSzb src, double val, PtrStepSzb dst, cudaStream_t stream) { cv::gpu::device::min_gpu(src, saturate_cast(val), dst, stream); } template void maxScalar(const PtrStepSzb src, double val, PtrStepSzb dst, cudaStream_t stream) { cv::gpu::device::max_gpu(src, saturate_cast(val), dst, stream); } } void cv::gpu::min(const GpuMat& src, double val, GpuMat& dst, Stream& stream) { typedef void (*func_t)(const PtrStepSzb src1, double src2, PtrStepSzb dst, cudaStream_t stream); static const func_t funcs[] = { minScalar, minScalar, minScalar, minScalar, minScalar, minScalar, minScalar }; CV_Assert(src.depth() <= CV_64F); CV_Assert(src.channels() == 1); if (src.depth() == CV_64F) { if (!TargetArchs::builtWith(NATIVE_DOUBLE) || !DeviceInfo().supports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } dst.create(src.size(), src.type()); funcs[src.depth()](src, val, dst, StreamAccessor::getStream(stream)); } void cv::gpu::max(const GpuMat& src, double val, GpuMat& dst, Stream& stream) { typedef void (*func_t)(const PtrStepSzb src1, double src2, PtrStepSzb dst, cudaStream_t stream); static const func_t funcs[] = { maxScalar, maxScalar, maxScalar, maxScalar, maxScalar, maxScalar, maxScalar }; CV_Assert(src.depth() <= CV_64F); CV_Assert(src.channels() == 1); if (src.depth() == CV_64F) { if (!TargetArchs::builtWith(NATIVE_DOUBLE) || !DeviceInfo().supports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } dst.create(src.size(), src.type()); funcs[src.depth()](src, val, dst, StreamAccessor::getStream(stream)); } //////////////////////////////////////////////////////////////////////// // threshold namespace cv { namespace gpu { namespace device { template void threshold_gpu(const PtrStepSzb& src, const PtrStepSzb& 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); if (src.depth() == CV_64F) { if (!TargetArchs::builtWith(NATIVE_DOUBLE) || !DeviceInfo().supports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } 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 (*func_t)(const GpuMat& src, GpuMat& dst, double thresh, double maxVal, int type, cudaStream_t stream); static const func_t funcs[] = { 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); } funcs[src.depth()](src, dst, thresh, maxVal, type, stream); } return thresh; } //////////////////////////////////////////////////////////////////////// // pow namespace cv { namespace gpu { namespace device { template void pow_caller(PtrStepSzb src, double power, PtrStepSzb dst, cudaStream_t stream); }}} void cv::gpu::pow(const GpuMat& src, double power, GpuMat& dst, Stream& stream) { using namespace cv::gpu::device; typedef void (*func_t)(PtrStepSzb src, double power, PtrStepSzb dst, cudaStream_t stream); static const func_t funcs[] = { pow_caller, pow_caller, pow_caller, pow_caller, pow_caller, pow_caller, pow_caller }; CV_Assert(src.depth() <= CV_64F); if (src.depth() == CV_64F) { if (!TargetArchs::builtWith(NATIVE_DOUBLE) || !DeviceInfo().supports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } dst.create(src.size(), src.type()); funcs[src.depth()](src.reshape(1), 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 }; 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()]; func(img1, img2, dst, npp_alpha_ops[alpha_op], StreamAccessor::getStream(stream)); } //////////////////////////////////////////////////////////////////////// // addWeighted namespace cv { namespace gpu { namespace device { template void addWeighted_gpu(const PtrStepSzb& src1, double alpha, const PtrStepSzb& src2, double beta, double gamma, const PtrStepSzb& 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; typedef void (*func_t)(const PtrStepSzb& src1, double alpha, const PtrStepSzb& src2, double beta, double gamma, const PtrStepSzb& dst, cudaStream_t stream); static const func_t funcs[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 } } }; 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(); CV_Assert(src1.depth() <= CV_64F && src2.depth() <= CV_64F && CV_MAT_DEPTH(dtype) <= CV_64F); if (src1.depth() == CV_64F || src2.depth() == CV_64F || CV_MAT_DEPTH(dtype) == CV_64F) { if (!TargetArchs::builtWith(NATIVE_DOUBLE) || !DeviceInfo().supports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } 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); } const func_t func = funcs[psrc1->depth()][psrc2->depth()][dst.depth()]; if (!func) CV_Error(CV_StsUnsupportedFormat, "Unsupported combination of source and destination types"); func(psrc1->reshape(1), alpha, psrc2->reshape(1), beta, gamma, dst.reshape(1), StreamAccessor::getStream(stream)); } #endif