/*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 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 arithm { template void vadd4(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); template void vadd2(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); template void addMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, 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 arithm; typedef void (*func_t)(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); static const func_t funcs[7][7] = { { addMat, addMat, addMat, addMat, addMat, addMat, addMat }, { addMat, addMat, addMat, addMat, addMat, addMat, addMat }, { 0 /*addMat*/, 0 /*addMat*/, addMat, addMat, addMat, addMat, addMat }, { 0 /*addMat*/, 0 /*addMat*/, addMat, addMat, addMat, addMat, addMat }, { 0 /*addMat*/, 0 /*addMat*/, 0 /*addMat*/, 0 /*addMat*/, addMat, addMat, addMat }, { 0 /*addMat*/, 0 /*addMat*/, 0 /*addMat*/, 0 /*addMat*/, 0 /*addMat*/, addMat, addMat }, { 0 /*addMat*/, 0 /*addMat*/, 0 /*addMat*/, 0 /*addMat*/, 0 /*addMat*/, 0 /*addMat*/, addMat } }; typedef void (*vfunc_t)(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); static const vfunc_t vfuncs4[4][4] = { { vadd4, vadd4, 0, 0 }, { vadd4, vadd4, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } }; static const vfunc_t vfuncs2[4][4] = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, vadd2, vadd2 }, { 0, 0, vadd2, vadd2 } }; if (dtype < 0) dtype = src1.depth(); const int sdepth = src1.depth(); const int ddepth = CV_MAT_DEPTH(dtype); const int cn = src1.channels(); CV_Assert( sdepth <= CV_64F && ddepth <= CV_64F ); CV_Assert( src2.type() == src1.type() && src2.size() == src1.size() ); CV_Assert( mask.empty() || (cn == 1 && mask.size() == src1.size() && mask.type() == CV_8U) ); if (sdepth == CV_64F || ddepth == CV_64F) { if (!deviceSupports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } dst.create(src1.size(), CV_MAKE_TYPE(ddepth, cn)); cudaStream_t stream = StreamAccessor::getStream(s); PtrStepSzb src1_(src1.rows, src1.cols * cn, src1.data, src1.step); PtrStepSzb src2_(src1.rows, src1.cols * cn, src2.data, src2.step); PtrStepSzb dst_(src1.rows, src1.cols * cn, dst.data, dst.step); if (mask.empty() && sdepth < CV_32S && ddepth < CV_32S) { const intptr_t src1ptr = reinterpret_cast(src1_.data); const intptr_t src2ptr = reinterpret_cast(src2_.data); const intptr_t dstptr = reinterpret_cast(dst_.data); const bool isAllAligned = (src1ptr & 31) == 0 && (src2ptr & 31) == 0 && (dstptr & 31) == 0; if (deviceSupports(FEATURE_SET_COMPUTE_20) && isAllAligned) { const vfunc_t vfunc4 = vfuncs4[sdepth][ddepth]; const vfunc_t vfunc2 = vfuncs2[sdepth][ddepth]; if (vfunc4 != 0 && (src1_.cols & 3) == 0) { const int vcols = src1_.cols >> 2; vfunc4(PtrStepSzb(src1_.rows, vcols, src1_.data, src1_.step), PtrStepSzb(src1_.rows, vcols, src2_.data, src2_.step), PtrStepSzb(src1_.rows, vcols, dst_.data, dst_.step), stream); return; } if (vfunc2 != 0 && (src1_.cols & 1) == 0) { const int vcols = src1_.cols >> 1; vfunc2(PtrStepSzb(src1_.rows, vcols, src1_.data, src1_.step), PtrStepSzb(src1_.rows, vcols, src2_.data, src2_.step), PtrStepSzb(src1_.rows, vcols, dst_.data, dst_.step), stream); return; } } } const func_t func = funcs[sdepth][ddepth]; if (!func) CV_Error(CV_StsUnsupportedFormat, "Unsupported combination of source and destination types"); func(src1_, src2_, dst_, mask, stream); } namespace arithm { template void addScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); } void cv::gpu::add(const GpuMat& src, const Scalar& sc, GpuMat& dst, const GpuMat& mask, int dtype, Stream& s) { using namespace arithm; typedef void (*func_t)(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); static const func_t funcs[7][7] = { { addScalar, addScalar, addScalar, addScalar, addScalar, addScalar, addScalar }, { addScalar, addScalar, addScalar, addScalar, addScalar, addScalar, addScalar }, { 0 /*addScalar*/, 0 /*addScalar*/, addScalar, addScalar, addScalar, addScalar, addScalar }, { 0 /*addScalar*/, 0 /*addScalar*/, addScalar, addScalar, addScalar, addScalar, addScalar }, { 0 /*addScalar*/, 0 /*addScalar*/, 0 /*addScalar*/, 0 /*addScalar*/, addScalar, addScalar, addScalar }, { 0 /*addScalar*/, 0 /*addScalar*/, 0 /*addScalar*/, 0 /*addScalar*/, 0 /*addScalar*/, addScalar, addScalar }, { 0 /*addScalar*/, 0 /*addScalar*/, 0 /*addScalar*/, 0 /*addScalar*/, 0 /*addScalar*/, 0 /*addScalar*/, addScalar } }; 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(); const int sdepth = src.depth(); const int ddepth = CV_MAT_DEPTH(dtype); const int cn = src.channels(); CV_Assert( sdepth <= CV_64F && ddepth <= CV_64F ); CV_Assert( cn <= 4 ); CV_Assert( mask.empty() || (cn == 1 && mask.size() == src.size() && mask.type() == CV_8U) ); if (sdepth == CV_64F || ddepth == CV_64F) { if (!deviceSupports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } dst.create(src.size(), CV_MAKE_TYPE(ddepth, cn)); cudaStream_t stream = StreamAccessor::getStream(s); const npp_func_t npp_func = npp_funcs[sdepth][cn - 1]; if (ddepth == sdepth && cn > 1 && npp_func != 0) { npp_func(src, sc, dst, stream); return; } CV_Assert( cn == 1 ); const func_t func = funcs[sdepth][ddepth]; if (!func) CV_Error(CV_StsUnsupportedFormat, "Unsupported combination of source and destination types"); func(src, sc.val[0], dst, mask, stream); } //////////////////////////////////////////////////////////////////////// // subtract namespace arithm { template void vsub4(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); template void vsub2(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); template void subMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, 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 arithm; typedef void (*func_t)(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); static const func_t funcs[7][7] = { { subMat, subMat, subMat, subMat, subMat, subMat, subMat }, { subMat, subMat, subMat, subMat, subMat, subMat, subMat }, { 0 /*subMat*/, 0 /*subMat*/, subMat, subMat, subMat, subMat, subMat }, { 0 /*subMat*/, 0 /*subMat*/, subMat, subMat, subMat, subMat, subMat }, { 0 /*subMat*/, 0 /*subMat*/, 0 /*subMat*/, 0 /*subMat*/, subMat, subMat, subMat }, { 0 /*subMat*/, 0 /*subMat*/, 0 /*subMat*/, 0 /*subMat*/, 0 /*subMat*/, subMat, subMat }, { 0 /*subMat*/, 0 /*subMat*/, 0 /*subMat*/, 0 /*subMat*/, 0 /*subMat*/, 0 /*subMat*/, subMat } }; typedef void (*vfunc_t)(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); static const vfunc_t vfuncs4[4][4] = { { vsub4, vsub4, 0, 0 }, { vsub4, vsub4, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } }; static const vfunc_t vfuncs2[4][4] = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, vsub2, vsub2 }, { 0, 0, vsub2, vsub2 } }; if (dtype < 0) dtype = src1.depth(); const int sdepth = src1.depth(); const int ddepth = CV_MAT_DEPTH(dtype); const int cn = src1.channels(); CV_Assert( sdepth <= CV_64F && ddepth <= CV_64F ); CV_Assert( src2.type() == src1.type() && src2.size() == src1.size() ); CV_Assert( mask.empty() || (cn == 1 && mask.size() == src1.size() && mask.type() == CV_8U) ); if (sdepth == CV_64F || ddepth == CV_64F) { if (!deviceSupports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } dst.create(src1.size(), CV_MAKE_TYPE(ddepth, cn)); cudaStream_t stream = StreamAccessor::getStream(s); PtrStepSzb src1_(src1.rows, src1.cols * cn, src1.data, src1.step); PtrStepSzb src2_(src1.rows, src1.cols * cn, src2.data, src2.step); PtrStepSzb dst_(src1.rows, src1.cols * cn, dst.data, dst.step); if (mask.empty() && sdepth < CV_32S && ddepth < CV_32S) { const intptr_t src1ptr = reinterpret_cast(src1_.data); const intptr_t src2ptr = reinterpret_cast(src2_.data); const intptr_t dstptr = reinterpret_cast(dst_.data); const bool isAllAligned = (src1ptr & 31) == 0 && (src2ptr & 31) == 0 && (dstptr & 31) == 0; if (deviceSupports(FEATURE_SET_COMPUTE_20) && isAllAligned) { const vfunc_t vfunc4 = vfuncs4[sdepth][ddepth]; const vfunc_t vfunc2 = vfuncs2[sdepth][ddepth]; if (vfunc4 != 0 && (src1_.cols & 3) == 0) { const int vcols = src1_.cols >> 2; vfunc4(PtrStepSzb(src1_.rows, vcols, src1_.data, src1_.step), PtrStepSzb(src1_.rows, vcols, src2_.data, src2_.step), PtrStepSzb(src1_.rows, vcols, dst_.data, dst_.step), stream); return; } if (vfunc2 != 0 && (src1_.cols & 1) == 0) { const int vcols = src1_.cols >> 1; vfunc2(PtrStepSzb(src1_.rows, vcols, src1_.data, src1_.step), PtrStepSzb(src1_.rows, vcols, src2_.data, src2_.step), PtrStepSzb(src1_.rows, vcols, dst_.data, dst_.step), stream); return; } } } const func_t func = funcs[sdepth][ddepth]; if (!func) CV_Error(CV_StsUnsupportedFormat, "Unsupported combination of source and destination types"); func(src1_, src2_, dst_, mask, stream); } namespace arithm { template void subScalar(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); } void cv::gpu::subtract(const GpuMat& src, const Scalar& sc, GpuMat& dst, const GpuMat& mask, int dtype, Stream& s) { using namespace arithm; typedef void (*func_t)(PtrStepSzb src1, double val, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); static const func_t funcs[7][7] = { { subScalar, subScalar, subScalar, subScalar, subScalar, subScalar, subScalar }, { subScalar, subScalar, subScalar, subScalar, subScalar, subScalar, subScalar }, { 0 /*subScalar*/, 0 /*subScalar*/, subScalar, subScalar, subScalar, subScalar, subScalar }, { 0 /*subScalar*/, 0 /*subScalar*/, subScalar, subScalar, subScalar, subScalar, subScalar }, { 0 /*subScalar*/, 0 /*subScalar*/, 0 /*subScalar*/, 0 /*subScalar*/, subScalar, subScalar, subScalar }, { 0 /*subScalar*/, 0 /*subScalar*/, 0 /*subScalar*/, 0 /*subScalar*/, 0 /*subScalar*/, subScalar, subScalar }, { 0 /*subScalar*/, 0 /*subScalar*/, 0 /*subScalar*/, 0 /*subScalar*/, 0 /*subScalar*/, 0 /*subScalar*/, subScalar } }; 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(); const int sdepth = src.depth(); const int ddepth = CV_MAT_DEPTH(dtype); const int cn = src.channels(); CV_Assert( sdepth <= CV_64F && ddepth <= CV_64F ); CV_Assert( cn <= 4 ); CV_Assert( mask.empty() || (cn == 1 && mask.size() == src.size() && mask.type() == CV_8U) ); if (sdepth == CV_64F || ddepth == CV_64F) { if (!deviceSupports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } dst.create(src.size(), CV_MAKE_TYPE(ddepth, cn)); cudaStream_t stream = StreamAccessor::getStream(s); const npp_func_t npp_func = npp_funcs[sdepth][cn - 1]; if (ddepth == sdepth && cn > 1 && npp_func != 0) { npp_func(src, sc, dst, stream); return; } CV_Assert( cn == 1 ); const func_t func = funcs[sdepth][ddepth]; if (!func) CV_Error(CV_StsUnsupportedFormat, "Unsupported combination of source and destination types"); func(src, sc.val[0], dst, mask, stream); } //////////////////////////////////////////////////////////////////////// // multiply namespace arithm { void mulMat_8uc4_32f(PtrStepSz src1, PtrStepSzf src2, PtrStepSz dst, cudaStream_t stream); void mulMat_16sc4_32f(PtrStepSz src1, PtrStepSzf src2, PtrStepSz dst, cudaStream_t stream); template void mulMat(PtrStepSzb src1, PtrStepSzb src2, 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 arithm; 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()); mulMat_8uc4_32f(src1, src2, dst, stream); } else if (src1.type() == CV_16SC4 && src2.type() == CV_32FC1) { CV_Assert( src1.size() == src2.size() ); dst.create(src1.size(), src1.type()); mulMat_16sc4_32f(src1, src2, dst, stream); } else { typedef void (*func_t)(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); static const func_t funcs[7][7] = { { mulMat, mulMat, mulMat, mulMat, mulMat, mulMat, mulMat }, { mulMat, mulMat, mulMat, mulMat, mulMat, mulMat, mulMat }, { 0 /*mulMat*/, 0 /*mulMat*/, mulMat, mulMat, mulMat, mulMat, mulMat }, { 0 /*mulMat*/, 0 /*mulMat*/, mulMat, mulMat, mulMat, mulMat, mulMat }, { 0 /*mulMat*/, 0 /*mulMat*/, 0 /*mulMat*/, 0 /*mulMat*/, mulMat, mulMat, mulMat }, { 0 /*mulMat*/, 0 /*mulMat*/, 0 /*mulMat*/, 0 /*mulMat*/, 0 /*mulMat*/, mulMat, mulMat }, { 0 /*mulMat*/, 0 /*mulMat*/, 0 /*mulMat*/, 0 /*mulMat*/, 0 /*mulMat*/, 0 /*mulMat*/, mulMat } }; if (dtype < 0) dtype = src1.depth(); const int sdepth = src1.depth(); const int ddepth = CV_MAT_DEPTH(dtype); const int cn = src1.channels(); CV_Assert( sdepth <= CV_64F && ddepth <= CV_64F ); CV_Assert( src2.type() == src1.type() && src2.size() == src1.size() ); if (sdepth == CV_64F || ddepth == CV_64F) { if (!deviceSupports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } dst.create(src1.size(), CV_MAKE_TYPE(ddepth, cn)); PtrStepSzb src1_(src1.rows, src1.cols * cn, src1.data, src1.step); PtrStepSzb src2_(src1.rows, src1.cols * cn, src2.data, src2.step); PtrStepSzb dst_(src1.rows, src1.cols * cn, dst.data, dst.step); const func_t func = funcs[sdepth][ddepth]; if (!func) CV_Error(CV_StsUnsupportedFormat, "Unsupported combination of source and destination types"); func(src1_, src2_, dst_, scale, stream); } } namespace arithm { template void mulScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); } void cv::gpu::multiply(const GpuMat& src, const Scalar& sc, GpuMat& dst, double scale, int dtype, Stream& s) { using namespace arithm; typedef void (*func_t)(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); static const func_t funcs[7][7] = { { mulScalar, mulScalar, mulScalar, mulScalar, mulScalar, mulScalar, mulScalar }, { mulScalar, mulScalar, mulScalar, mulScalar, mulScalar, mulScalar, mulScalar }, { 0 /*mulScalar*/, 0 /*mulScalar*/, mulScalar, mulScalar, mulScalar, mulScalar, mulScalar }, { 0 /*mulScalar*/, 0 /*mulScalar*/, mulScalar, mulScalar, mulScalar, mulScalar, mulScalar }, { 0 /*mulScalar*/, 0 /*mulScalar*/, 0 /*mulScalar*/, 0 /*mulScalar*/, mulScalar, mulScalar, mulScalar }, { 0 /*mulScalar*/, 0 /*mulScalar*/, 0 /*mulScalar*/, 0 /*mulScalar*/, 0 /*mulScalar*/, mulScalar, mulScalar }, { 0 /*mulScalar*/, 0 /*mulScalar*/, 0 /*mulScalar*/, 0 /*mulScalar*/, 0 /*mulScalar*/, 0 /*mulScalar*/, mulScalar } }; 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(); const int sdepth = src.depth(); const int ddepth = CV_MAT_DEPTH(dtype); const int cn = src.channels(); CV_Assert( sdepth <= CV_64F && ddepth <= CV_64F ); CV_Assert( cn <= 4 ); if (sdepth == CV_64F || ddepth == CV_64F) { if (!deviceSupports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } dst.create(src.size(), CV_MAKE_TYPE(ddepth, cn)); cudaStream_t stream = StreamAccessor::getStream(s); const Scalar nsc(sc.val[0] * scale, sc.val[1] * scale, sc.val[2] * scale, sc.val[3] * scale); const npp_func_t npp_func = npp_funcs[sdepth][cn - 1]; if (ddepth == sdepth && cn > 1 && npp_func != 0) { npp_func(src, nsc, dst, stream); return; } CV_Assert( cn == 1 ); const func_t func = funcs[sdepth][ddepth]; if (!func) CV_Error(CV_StsUnsupportedFormat, "Unsupported combination of source and destination types"); func(src, nsc.val[0], dst, stream); } //////////////////////////////////////////////////////////////////////// // divide namespace arithm { void divMat_8uc4_32f(PtrStepSz src1, PtrStepSzf src2, PtrStepSz dst, cudaStream_t stream); void divMat_16sc4_32f(PtrStepSz src1, PtrStepSzf src2, PtrStepSz dst, cudaStream_t stream); template void divMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); } void cv::gpu::divide(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, double scale, int dtype, Stream& s) { using namespace arithm; 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()); divMat_8uc4_32f(src1, src2, dst, stream); } else if (src1.type() == CV_16SC4 && src2.type() == CV_32FC1) { CV_Assert( src1.size() == src2.size() ); dst.create(src1.size(), src1.type()); divMat_16sc4_32f(src1, src2, dst, stream); } else { typedef void (*func_t)(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, double scale, cudaStream_t stream); static const func_t funcs[7][7] = { { divMat, divMat, divMat, divMat, divMat, divMat, divMat }, { divMat, divMat, divMat, divMat, divMat, divMat, divMat }, { 0 /*divMat*/, 0 /*divMat*/, divMat, divMat, divMat, divMat, divMat }, { 0 /*divMat*/, 0 /*divMat*/, divMat, divMat, divMat, divMat, divMat }, { 0 /*divMat*/, 0 /*divMat*/, 0 /*divMat*/, 0 /*divMat*/, divMat, divMat, divMat }, { 0 /*divMat*/, 0 /*divMat*/, 0 /*divMat*/, 0 /*divMat*/, 0 /*divMat*/, divMat, divMat }, { 0 /*divMat*/, 0 /*divMat*/, 0 /*divMat*/, 0 /*divMat*/, 0 /*divMat*/, 0 /*divMat*/, divMat } }; if (dtype < 0) dtype = src1.depth(); const int sdepth = src1.depth(); const int ddepth = CV_MAT_DEPTH(dtype); const int cn = src1.channels(); CV_Assert( sdepth <= CV_64F && ddepth <= CV_64F ); CV_Assert( src2.type() == src1.type() && src2.size() == src1.size() ); if (sdepth == CV_64F || ddepth == CV_64F) { if (!deviceSupports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } dst.create(src1.size(), CV_MAKE_TYPE(ddepth, cn)); PtrStepSzb src1_(src1.rows, src1.cols * cn, src1.data, src1.step); PtrStepSzb src2_(src1.rows, src1.cols * cn, src2.data, src2.step); PtrStepSzb dst_(src1.rows, src1.cols * cn, dst.data, dst.step); const func_t func = funcs[sdepth][ddepth]; if (!func) CV_Error(CV_StsUnsupportedFormat, "Unsupported combination of source and destination types"); func(src1_, src2_, dst_, scale, stream); } } namespace arithm { template void divScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); } void cv::gpu::divide(const GpuMat& src, const Scalar& sc, GpuMat& dst, double scale, int dtype, Stream& s) { using namespace arithm; typedef void (*func_t)(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); static const func_t funcs[7][7] = { { divScalar, divScalar, divScalar, divScalar, divScalar, divScalar, divScalar }, { divScalar, divScalar, divScalar, divScalar, divScalar, divScalar, divScalar }, { 0 /*divScalar*/, 0 /*divScalar*/, divScalar, divScalar, divScalar, divScalar, divScalar }, { 0 /*divScalar*/, 0 /*divScalar*/, divScalar, divScalar, divScalar, divScalar, divScalar }, { 0 /*divScalar*/, 0 /*divScalar*/, 0 /*divScalar*/, 0 /*divScalar*/, divScalar, divScalar, divScalar }, { 0 /*divScalar*/, 0 /*divScalar*/, 0 /*divScalar*/, 0 /*divScalar*/, 0 /*divScalar*/, divScalar, divScalar }, { 0 /*divScalar*/, 0 /*divScalar*/, 0 /*divScalar*/, 0 /*divScalar*/, 0 /*divScalar*/, 0 /*divScalar*/, divScalar } }; 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(); const int sdepth = src.depth(); const int ddepth = CV_MAT_DEPTH(dtype); const int cn = src.channels(); CV_Assert( sdepth <= CV_64F && ddepth <= CV_64F ); CV_Assert( cn <= 4 ); if (sdepth == CV_64F || ddepth == CV_64F) { if (!deviceSupports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } dst.create(src.size(), CV_MAKE_TYPE(ddepth, cn)); cudaStream_t stream = StreamAccessor::getStream(s); const Scalar nsc(sc.val[0] / scale, sc.val[1] / scale, sc.val[2] / scale, sc.val[3] / scale); const npp_func_t npp_func = npp_funcs[sdepth][cn - 1]; if (ddepth == sdepth && cn > 1 && npp_func != 0) { npp_func(src, nsc, dst, stream); return; } CV_Assert( cn == 1 ); const func_t func = funcs[sdepth][ddepth]; if (!func) CV_Error(CV_StsUnsupportedFormat, "Unsupported combination of source and destination types"); func(src, nsc.val[0], dst, stream); } namespace arithm { template void divInv(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); } void cv::gpu::divide(double scale, const GpuMat& src, GpuMat& dst, int dtype, Stream& s) { using namespace arithm; typedef void (*func_t)(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); static const func_t funcs[7][7] = { { divInv, divInv, divInv, divInv, divInv, divInv, divInv }, { divInv, divInv, divInv, divInv, divInv, divInv, divInv }, { 0 /*divInv*/, 0 /*divInv*/, divInv, divInv, divInv, divInv, divInv }, { 0 /*divInv*/, 0 /*divInv*/, divInv, divInv, divInv, divInv, divInv }, { 0 /*divInv*/, 0 /*divInv*/, 0 /*divInv*/, 0 /*divInv*/, divInv, divInv, divInv }, { 0 /*divInv*/, 0 /*divInv*/, 0 /*divInv*/, 0 /*divInv*/, 0 /*divInv*/, divInv, divInv }, { 0 /*divInv*/, 0 /*divInv*/, 0 /*divInv*/, 0 /*divInv*/, 0 /*divInv*/, 0 /*divInv*/, divInv } }; if (dtype < 0) dtype = src.depth(); const int sdepth = src.depth(); const int ddepth = CV_MAT_DEPTH(dtype); const int cn = src.channels(); CV_Assert( sdepth <= CV_64F && ddepth <= CV_64F ); CV_Assert( cn == 1 ); if (sdepth == CV_64F || ddepth == CV_64F) { if (!deviceSupports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } dst.create(src.size(), CV_MAKE_TYPE(ddepth, cn)); cudaStream_t stream = StreamAccessor::getStream(s); const func_t func = funcs[sdepth][ddepth]; if (!func) CV_Error(CV_StsUnsupportedFormat, "Unsupported combination of source and destination types"); func(src, scale, dst, stream); } ////////////////////////////////////////////////////////////////////////////// // absdiff namespace arithm { template void vabsDiff4(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); template void vabsDiff2(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); template void absDiffMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); } void cv::gpu::absdiff(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, Stream& s) { using namespace arithm; typedef void (*func_t)(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); static const func_t funcs[] = { absDiffMat, absDiffMat, absDiffMat, absDiffMat, absDiffMat, absDiffMat, absDiffMat }; static const func_t vfuncs4[] = { vabsDiff4, vabsDiff4, 0, 0 }; static const func_t vfuncs2[] = { 0, 0, vabsDiff2, vabsDiff2 }; const int depth = src1.depth(); const int cn = src1.channels(); CV_Assert( depth <= CV_64F ); CV_Assert( src2.type() == src1.type() && src2.size() == src1.size() ); if (depth == CV_64F) { if (!deviceSupports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } dst.create(src1.size(), src1.type()); cudaStream_t stream = StreamAccessor::getStream(s); PtrStepSzb src1_(src1.rows, src1.cols * cn, src1.data, src1.step); PtrStepSzb src2_(src1.rows, src1.cols * cn, src2.data, src2.step); PtrStepSzb dst_(src1.rows, src1.cols * cn, dst.data, dst.step); if (depth < CV_32S) { const intptr_t src1ptr = reinterpret_cast(src1_.data); const intptr_t src2ptr = reinterpret_cast(src2_.data); const intptr_t dstptr = reinterpret_cast(dst_.data); const bool isAllAligned = (src1ptr & 31) == 0 && (src2ptr & 31) == 0 && (dstptr & 31) == 0; if (deviceSupports(FEATURE_SET_COMPUTE_20) && isAllAligned) { const func_t vfunc4 = vfuncs4[depth]; const func_t vfunc2 = vfuncs2[depth]; if (vfunc4 != 0 && (src1_.cols & 3) == 0) { const int vcols = src1_.cols >> 2; vfunc4(PtrStepSzb(src1_.rows, vcols, src1_.data, src1_.step), PtrStepSzb(src1_.rows, vcols, src2_.data, src2_.step), PtrStepSzb(src1_.rows, vcols, dst_.data, dst_.step), stream); return; } if (vfunc2 != 0 && (src1_.cols & 1) == 0) { const int vcols = src1_.cols >> 1; vfunc2(PtrStepSzb(src1_.rows, vcols, src1_.data, src1_.step), PtrStepSzb(src1_.rows, vcols, src2_.data, src2_.step), PtrStepSzb(src1_.rows, vcols, dst_.data, dst_.step), stream); return; } } } const func_t func = funcs[depth]; if (!func) CV_Error(CV_StsUnsupportedFormat, "Unsupported combination of source and destination types"); func(src1_, src2_, dst_, stream); } namespace arithm { template void absDiffScalar(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); } void cv::gpu::absdiff(const GpuMat& src1, const Scalar& src2, GpuMat& dst, Stream& stream) { using namespace arithm; typedef void (*func_t)(PtrStepSzb src1, double val, PtrStepSzb dst, cudaStream_t stream); static const func_t funcs[] = { absDiffScalar, absDiffScalar, absDiffScalar, absDiffScalar, absDiffScalar, absDiffScalar, absDiffScalar }; const int depth = src1.depth(); CV_Assert( depth <= CV_64F ); CV_Assert( src1.channels() == 1 ); if (depth == CV_64F) { if (!deviceSupports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } dst.create(src1.size(), src1.type()); funcs[depth](src1, src2.val[0], dst, StreamAccessor::getStream(stream)); } ////////////////////////////////////////////////////////////////////////////// // abs namespace arithm { template void absMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); } void cv::gpu::abs(const GpuMat& src, GpuMat& dst, Stream& stream) { using namespace arithm; typedef void (*func_t)(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); static const func_t funcs[] = { absMat, absMat, absMat, absMat, absMat, absMat, absMat }; const int depth = src.depth(); CV_Assert( depth <= CV_64F ); CV_Assert( src.channels() == 1 ); if (depth == CV_64F) { if (!deviceSupports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } dst.create(src.size(), src.type()); funcs[depth](src, dst, StreamAccessor::getStream(stream)); } ////////////////////////////////////////////////////////////////////////////// // sqr namespace arithm { template void sqrMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); } void cv::gpu::sqr(const GpuMat& src, GpuMat& dst, Stream& stream) { using namespace arithm; typedef void (*func_t)(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); static const func_t funcs[] = { sqrMat, sqrMat, sqrMat, sqrMat, sqrMat, sqrMat, sqrMat }; const int depth = src.depth(); CV_Assert( depth <= CV_64F ); CV_Assert( src.channels() == 1 ); if (depth == CV_64F) { if (!deviceSupports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } dst.create(src.size(), src.type()); funcs[depth](src, dst, StreamAccessor::getStream(stream)); } ////////////////////////////////////////////////////////////////////////////// // sqrt namespace arithm { template void sqrtMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); } void cv::gpu::sqrt(const GpuMat& src, GpuMat& dst, Stream& stream) { using namespace arithm; typedef void (*func_t)(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); static const func_t funcs[] = { sqrtMat, sqrtMat, sqrtMat, sqrtMat, sqrtMat, sqrtMat, sqrtMat }; const int depth = src.depth(); CV_Assert( depth <= CV_64F ); CV_Assert( src.channels() == 1 ); if (depth == CV_64F) { if (!deviceSupports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } dst.create(src.size(), src.type()); funcs[depth](src, dst, StreamAccessor::getStream(stream)); } //////////////////////////////////////////////////////////////////////// // log namespace arithm { template void logMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); } void cv::gpu::log(const GpuMat& src, GpuMat& dst, Stream& stream) { using namespace arithm; typedef void (*func_t)(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); static const func_t funcs[] = { logMat, logMat, logMat, logMat, logMat, logMat, logMat }; const int depth = src.depth(); CV_Assert( depth <= CV_64F ); CV_Assert( src.channels() == 1 ); if (depth == CV_64F) { if (!deviceSupports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } dst.create(src.size(), src.type()); funcs[depth](src, dst, StreamAccessor::getStream(stream)); } //////////////////////////////////////////////////////////////////////// // exp namespace arithm { template void expMat(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); } void cv::gpu::exp(const GpuMat& src, GpuMat& dst, Stream& stream) { using namespace arithm; typedef void (*func_t)(PtrStepSzb src, PtrStepSzb dst, cudaStream_t stream); static const func_t funcs[] = { expMat, expMat, expMat, expMat, expMat, expMat, expMat }; const int depth = src.depth(); CV_Assert( depth <= CV_64F ); CV_Assert( src.channels() == 1 ); if (depth == CV_64F) { if (!deviceSupports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } dst.create(src.size(), src.type()); funcs[depth](src, dst, StreamAccessor::getStream(stream)); } ////////////////////////////////////////////////////////////////////////////// // compare namespace arithm { template void cmpMatEq(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); template void cmpMatNe(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); template void cmpMatLt(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); template void cmpMatLe(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); } void cv::gpu::compare(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, int cmpop, Stream& s) { using namespace arithm; typedef void (*func_t)(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); static const func_t funcs[7][4] = { {cmpMatEq , cmpMatNe , cmpMatLt , cmpMatLe }, {cmpMatEq , cmpMatNe , cmpMatLt , cmpMatLe }, {cmpMatEq, cmpMatNe, cmpMatLt, cmpMatLe}, {cmpMatEq , cmpMatNe , cmpMatLt , cmpMatLe }, {cmpMatEq , cmpMatNe , cmpMatLt , cmpMatLe }, {cmpMatEq , cmpMatNe , cmpMatLt , cmpMatLe }, {cmpMatEq , cmpMatNe , cmpMatLt , cmpMatLe } }; const int depth = src1.depth(); const int cn = src1.channels(); CV_Assert( depth <= CV_64F ); CV_Assert( src2.size() == src1.size() && src2.type() == src1.type() ); CV_Assert( cmpop >= CMP_EQ && cmpop <= CMP_NE ); if (depth == CV_64F) { if (!deviceSupports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } dst.create(src1.size(), CV_MAKE_TYPE(CV_8U, cn)); cudaStream_t stream = StreamAccessor::getStream(s); 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 }; const int code = codes[cmpop]; PtrStepSzb src1_(src1.rows, src1.cols * cn, psrc1[cmpop]->data, psrc1[cmpop]->step); PtrStepSzb src2_(src1.rows, src1.cols * cn, psrc2[cmpop]->data, psrc2[cmpop]->step); PtrStepSzb dst_(src1.rows, src1.cols * cn, dst.data, dst.step); const func_t func = funcs[depth][code]; func(src1_, src2_, dst_, stream); } ////////////////////////////////////////////////////////////////////////////// // Unary bitwise logical operations namespace arithm { template void bitMatNot(PtrStepSzb src, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); } void cv::gpu::bitwise_not(const GpuMat& src, GpuMat& dst, const GpuMat& mask, Stream& s) { using namespace arithm; const int depth = src.depth(); CV_Assert( depth <= CV_64F ); CV_Assert( mask.empty() || (mask.type() == CV_8UC1 && mask.size() == src.size()) ); dst.create(src.size(), src.type()); cudaStream_t stream = StreamAccessor::getStream(s); const int bcols = (int) (src.cols * src.elemSize()); if ((bcols & 3) == 0) { const int vcols = bcols >> 2; bitMatNot( PtrStepSzb(src.rows, vcols, src.data, src.step), PtrStepSzb(src.rows, vcols, dst.data, dst.step), mask, stream); } else if ((bcols & 1) == 0) { const int vcols = bcols >> 1; bitMatNot( PtrStepSzb(src.rows, vcols, src.data, src.step), PtrStepSzb(src.rows, vcols, dst.data, dst.step), mask, stream); } else { bitMatNot( PtrStepSzb(src.rows, bcols, src.data, src.step), PtrStepSzb(src.rows, bcols, dst.data, dst.step), mask, stream); } } ////////////////////////////////////////////////////////////////////////////// // Binary bitwise logical operations namespace arithm { template void bitMatAnd(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); template void bitMatOr(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); template void bitMatXor(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, PtrStepb mask, cudaStream_t stream); } void cv::gpu::bitwise_and(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, const GpuMat& mask, Stream& s) { using namespace arithm; const int depth = src1.depth(); CV_Assert( depth <= CV_64F ); CV_Assert( src2.size() == src1.size() && src2.type() == src1.type() ); CV_Assert( mask.empty() || (mask.type() == CV_8UC1 && mask.size() == src1.size()) ); dst.create(src1.size(), src1.type()); cudaStream_t stream = StreamAccessor::getStream(s); const int bcols = (int) (src1.cols * src1.elemSize()); if ((bcols & 3) == 0) { const int vcols = bcols >> 2; bitMatAnd( PtrStepSzb(src1.rows, vcols, src1.data, src1.step), PtrStepSzb(src1.rows, vcols, src2.data, src2.step), PtrStepSzb(src1.rows, vcols, dst.data, dst.step), mask, stream); } else if ((bcols & 1) == 0) { const int vcols = bcols >> 1; bitMatAnd( PtrStepSzb(src1.rows, vcols, src1.data, src1.step), PtrStepSzb(src1.rows, vcols, src2.data, src2.step), PtrStepSzb(src1.rows, vcols, dst.data, dst.step), mask, stream); } else { bitMatAnd( PtrStepSzb(src1.rows, bcols, src1.data, src1.step), PtrStepSzb(src1.rows, bcols, src2.data, src2.step), PtrStepSzb(src1.rows, bcols, dst.data, dst.step), mask, stream); } } void cv::gpu::bitwise_or(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, const GpuMat& mask, Stream& s) { using namespace arithm; const int depth = src1.depth(); CV_Assert( depth <= CV_64F ); CV_Assert( src2.size() == src1.size() && src2.type() == src1.type() ); CV_Assert( mask.empty() || (mask.type() == CV_8UC1 && mask.size() == src1.size()) ); dst.create(src1.size(), src1.type()); cudaStream_t stream = StreamAccessor::getStream(s); const int bcols = (int) (src1.cols * src1.elemSize()); if ((bcols & 3) == 0) { const int vcols = bcols >> 2; bitMatOr( PtrStepSzb(src1.rows, vcols, src1.data, src1.step), PtrStepSzb(src1.rows, vcols, src2.data, src2.step), PtrStepSzb(src1.rows, vcols, dst.data, dst.step), mask, stream); } else if ((bcols & 1) == 0) { const int vcols = bcols >> 1; bitMatOr( PtrStepSzb(src1.rows, vcols, src1.data, src1.step), PtrStepSzb(src1.rows, vcols, src2.data, src2.step), PtrStepSzb(src1.rows, vcols, dst.data, dst.step), mask, stream); } else { bitMatOr( PtrStepSzb(src1.rows, bcols, src1.data, src1.step), PtrStepSzb(src1.rows, bcols, src2.data, src2.step), PtrStepSzb(src1.rows, bcols, dst.data, dst.step), mask, stream); } } void cv::gpu::bitwise_xor(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, const GpuMat& mask, Stream& s) { using namespace arithm; const int depth = src1.depth(); CV_Assert( depth <= CV_64F ); CV_Assert( src2.size() == src1.size() && src2.type() == src1.type() ); CV_Assert( mask.empty() || (mask.type() == CV_8UC1 && mask.size() == src1.size()) ); dst.create(src1.size(), src1.type()); cudaStream_t stream = StreamAccessor::getStream(s); const int bcols = (int) (src1.cols * src1.elemSize()); if ((bcols & 3) == 0) { const int vcols = bcols >> 2; bitMatXor( PtrStepSzb(src1.rows, vcols, src1.data, src1.step), PtrStepSzb(src1.rows, vcols, src2.data, src2.step), PtrStepSzb(src1.rows, vcols, dst.data, dst.step), mask, stream); } else if ((bcols & 1) == 0) { const int vcols = bcols >> 1; bitMatXor( PtrStepSzb(src1.rows, vcols, src1.data, src1.step), PtrStepSzb(src1.rows, vcols, src2.data, src2.step), PtrStepSzb(src1.rows, vcols, dst.data, dst.step), mask, stream); } else { bitMatXor( PtrStepSzb(src1.rows, bcols, src1.data, src1.step), PtrStepSzb(src1.rows, bcols, src2.data, src2.step), PtrStepSzb(src1.rows, bcols, dst.data, dst.step), mask, stream); } } ////////////////////////////////////////////////////////////////////////////// // Binary bitwise logical operations with scalars namespace arithm { template void bitScalarAnd(PtrStepSzb src1, unsigned int src2, PtrStepSzb dst, cudaStream_t stream); template void bitScalarOr(PtrStepSzb src1, unsigned int src2, PtrStepSzb dst, cudaStream_t stream); template void bitScalarXor(PtrStepSzb src1, unsigned int src2, PtrStepSzb dst, cudaStream_t stream); } namespace { typedef void (*bit_scalar_func_t)(PtrStepSzb src1, unsigned int src2, PtrStepSzb dst, cudaStream_t stream); template struct BitScalar { static void call(const GpuMat& src, Scalar sc, GpuMat& dst, cudaStream_t stream) { func(src, static_cast(sc.val[0]), dst, stream); } }; template struct BitScalar4 { static void call(const GpuMat& src, Scalar sc, GpuMat& dst, cudaStream_t stream) { Scalar_ isc = sc; unsigned int packedVal = 0; packedVal |= (isc.val[0] & 0xffff); packedVal |= (isc.val[1] & 0xffff) << 8; packedVal |= (isc.val[2] & 0xffff) << 16; packedVal |= (isc.val[3] & 0xffff) << 24; func(src, packedVal, dst, stream); } }; 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_and(const GpuMat& src, const Scalar& sc, GpuMat& dst, Stream& stream) { using namespace arithm; typedef void (*func_t)(const GpuMat& src, Scalar sc, GpuMat& dst, cudaStream_t stream); static const func_t funcs[5][4] = { {BitScalar< bitScalarAnd >::call , 0, NppBitwiseC::call, BitScalar4< bitScalarAnd >::call}, {0,0,0,0}, {BitScalar< bitScalarAnd >::call, 0, NppBitwiseC::call, NppBitwiseC::call}, {0,0,0,0}, {BitScalar< bitScalarAnd >::call , 0, NppBitwiseC::call, NppBitwiseC::call} }; const int depth = src.depth(); const int cn = src.channels(); CV_Assert( depth == CV_8U || depth == CV_16U || depth == CV_32S ); CV_Assert( cn == 1 || cn == 3 || cn == 4 ); dst.create(src.size(), src.type()); funcs[depth][cn - 1](src, sc, dst, StreamAccessor::getStream(stream)); } void cv::gpu::bitwise_or(const GpuMat& src, const Scalar& sc, GpuMat& dst, Stream& stream) { using namespace arithm; typedef void (*func_t)(const GpuMat& src, Scalar sc, GpuMat& dst, cudaStream_t stream); static const func_t funcs[5][4] = { {BitScalar< bitScalarOr >::call , 0, NppBitwiseC::call, BitScalar4< bitScalarOr >::call}, {0,0,0,0}, {BitScalar< bitScalarOr >::call, 0, NppBitwiseC::call, NppBitwiseC::call}, {0,0,0,0}, {BitScalar< bitScalarOr >::call , 0, NppBitwiseC::call, NppBitwiseC::call} }; const int depth = src.depth(); const int cn = src.channels(); CV_Assert( depth == CV_8U || depth == CV_16U || depth == CV_32S ); CV_Assert( cn == 1 || cn == 3 || cn == 4 ); dst.create(src.size(), src.type()); funcs[depth][cn - 1](src, sc, dst, StreamAccessor::getStream(stream)); } void cv::gpu::bitwise_xor(const GpuMat& src, const Scalar& sc, GpuMat& dst, Stream& stream) { using namespace arithm; typedef void (*func_t)(const GpuMat& src, Scalar sc, GpuMat& dst, cudaStream_t stream); static const func_t funcs[5][4] = { {BitScalar< bitScalarXor >::call , 0, NppBitwiseC::call, BitScalar4< bitScalarXor >::call}, {0,0,0,0}, {BitScalar< bitScalarXor >::call, 0, NppBitwiseC::call, NppBitwiseC::call}, {0,0,0,0}, {BitScalar< bitScalarXor >::call , 0, NppBitwiseC::call, NppBitwiseC::call} }; const int depth = src.depth(); const int cn = src.channels(); CV_Assert( depth == CV_8U || depth == CV_16U || depth == CV_32S ); CV_Assert( cn == 1 || cn == 3 || cn == 4 ); dst.create(src.size(), src.type()); funcs[depth][cn - 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 arithm { template void vmin4(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); template void vmin2(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); template void minMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); template void minScalar(PtrStepSzb src1, double src2, PtrStepSzb dst, cudaStream_t stream); template void vmax4(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); template void vmax2(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); template void maxMat(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); template void maxScalar(PtrStepSzb src1, double src2, PtrStepSzb dst, cudaStream_t stream); } void cv::gpu::min(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, Stream& s) { using namespace arithm; typedef void (*func_t)(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); static const func_t funcs[] = { minMat, minMat, minMat, minMat, minMat, minMat, minMat }; static const func_t vfuncs4[] = { vmin4, vmin4, 0, 0 }; static const func_t vfuncs2[] = { 0, 0, vmin2, vmin2 }; const int depth = src1.depth(); const int cn = src1.channels(); CV_Assert( depth <= CV_64F ); CV_Assert( src2.type() == src1.type() && src2.size() == src1.size() ); if (depth == CV_64F) { if (!deviceSupports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } dst.create(src1.size(), src1.type()); cudaStream_t stream = StreamAccessor::getStream(s); PtrStepSzb src1_(src1.rows, src1.cols * cn, src1.data, src1.step); PtrStepSzb src2_(src1.rows, src1.cols * cn, src2.data, src2.step); PtrStepSzb dst_(src1.rows, src1.cols * cn, dst.data, dst.step); if (depth < CV_32S) { const intptr_t src1ptr = reinterpret_cast(src1_.data); const intptr_t src2ptr = reinterpret_cast(src2_.data); const intptr_t dstptr = reinterpret_cast(dst_.data); const bool isAllAligned = (src1ptr & 31) == 0 && (src2ptr & 31) == 0 && (dstptr & 31) == 0; if (deviceSupports(FEATURE_SET_COMPUTE_20) && isAllAligned) { const func_t vfunc4 = vfuncs4[depth]; const func_t vfunc2 = vfuncs2[depth]; if (vfunc4 != 0 && (src1_.cols & 3) == 0) { const int vcols = src1_.cols >> 2; vfunc4(PtrStepSzb(src1_.rows, vcols, src1_.data, src1_.step), PtrStepSzb(src1_.rows, vcols, src2_.data, src2_.step), PtrStepSzb(src1_.rows, vcols, dst_.data, dst_.step), stream); return; } if (vfunc2 != 0 && (src1_.cols & 1) == 0) { const int vcols = src1_.cols >> 1; vfunc2(PtrStepSzb(src1_.rows, vcols, src1_.data, src1_.step), PtrStepSzb(src1_.rows, vcols, src2_.data, src2_.step), PtrStepSzb(src1_.rows, vcols, dst_.data, dst_.step), stream); return; } } } const func_t func = funcs[depth]; if (!func) CV_Error(CV_StsUnsupportedFormat, "Unsupported combination of source and destination types"); func(src1_, src2_, dst_, stream); } void cv::gpu::max(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, Stream& s) { using namespace arithm; typedef void (*func_t)(PtrStepSzb src1, PtrStepSzb src2, PtrStepSzb dst, cudaStream_t stream); static const func_t funcs[] = { maxMat, maxMat, maxMat, maxMat, maxMat, maxMat, maxMat }; static const func_t vfuncs4[] = { vmax4, vmax4, 0, 0 }; static const func_t vfuncs2[] = { 0, 0, vmax2, vmax2 }; const int depth = src1.depth(); const int cn = src1.channels(); CV_Assert( depth <= CV_64F ); CV_Assert( src2.type() == src1.type() && src2.size() == src1.size() ); if (depth == CV_64F) { if (!deviceSupports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } dst.create(src1.size(), src1.type()); cudaStream_t stream = StreamAccessor::getStream(s); PtrStepSzb src1_(src1.rows, src1.cols * cn, src1.data, src1.step); PtrStepSzb src2_(src1.rows, src1.cols * cn, src2.data, src2.step); PtrStepSzb dst_(src1.rows, src1.cols * cn, dst.data, dst.step); if (depth < CV_32S) { const intptr_t src1ptr = reinterpret_cast(src1_.data); const intptr_t src2ptr = reinterpret_cast(src2_.data); const intptr_t dstptr = reinterpret_cast(dst_.data); const bool isAllAligned = (src1ptr & 31) == 0 && (src2ptr & 31) == 0 && (dstptr & 31) == 0; if (deviceSupports(FEATURE_SET_COMPUTE_20) && isAllAligned) { const func_t vfunc4 = vfuncs4[depth]; const func_t vfunc2 = vfuncs2[depth]; if (vfunc4 != 0 && (src1_.cols & 3) == 0) { const int vcols = src1_.cols >> 2; vfunc4(PtrStepSzb(src1_.rows, vcols, src1_.data, src1_.step), PtrStepSzb(src1_.rows, vcols, src2_.data, src2_.step), PtrStepSzb(src1_.rows, vcols, dst_.data, dst_.step), stream); return; } if (vfunc2 != 0 && (src1_.cols & 1) == 0) { const int vcols = src1_.cols >> 1; vfunc2(PtrStepSzb(src1_.rows, vcols, src1_.data, src1_.step), PtrStepSzb(src1_.rows, vcols, src2_.data, src2_.step), PtrStepSzb(src1_.rows, vcols, dst_.data, dst_.step), stream); return; } } } const func_t func = funcs[depth]; if (!func) CV_Error(CV_StsUnsupportedFormat, "Unsupported combination of source and destination types"); func(src1_, src2_, dst_, stream); } namespace { template double castScalar(double val) { return saturate_cast(val); } } void cv::gpu::min(const GpuMat& src, double val, GpuMat& dst, Stream& stream) { using namespace arithm; typedef void (*func_t)(PtrStepSzb src1, double src2, PtrStepSzb dst, cudaStream_t stream); static const func_t funcs[] = { minScalar, minScalar, minScalar, minScalar, minScalar, minScalar, minScalar }; typedef double (*cast_func_t)(double sc); static const cast_func_t cast_func[] = { castScalar, castScalar, castScalar, castScalar, castScalar, castScalar, castScalar }; const int depth = src.depth(); CV_Assert( depth <= CV_64F ); CV_Assert( src.channels() == 1 ); if (depth == CV_64F) { if (!deviceSupports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } dst.create(src.size(), src.type()); funcs[depth](src, cast_func[depth](val), dst, StreamAccessor::getStream(stream)); } void cv::gpu::max(const GpuMat& src, double val, GpuMat& dst, Stream& stream) { using namespace arithm; typedef void (*func_t)(PtrStepSzb src1, double src2, PtrStepSzb dst, cudaStream_t stream); static const func_t funcs[] = { maxScalar, maxScalar, maxScalar, maxScalar, maxScalar, maxScalar, maxScalar }; typedef double (*cast_func_t)(double sc); static const cast_func_t cast_func[] = { castScalar, castScalar, castScalar, castScalar, castScalar, castScalar, castScalar }; const int depth = src.depth(); CV_Assert( depth <= CV_64F ); CV_Assert( src.channels() == 1 ); if (depth == CV_64F) { if (!deviceSupports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } dst.create(src.size(), src.type()); funcs[depth](src, cast_func[depth](val), dst, StreamAccessor::getStream(stream)); } //////////////////////////////////////////////////////////////////////// // threshold namespace arithm { template void threshold(PtrStepSzb src, PtrStepSzb dst, double thresh, double maxVal, int type, cudaStream_t stream); } double cv::gpu::threshold(const GpuMat& src, GpuMat& dst, double thresh, double maxVal, int type, Stream& s) { const int depth = src.depth(); CV_Assert( src.channels() == 1 && depth <= CV_64F ); CV_Assert( type <= THRESH_TOZERO_INV ); if (depth == CV_64F) { if (!deviceSupports(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)(PtrStepSzb src, PtrStepSzb dst, double thresh, double maxVal, int type, cudaStream_t stream); static const func_t funcs[] = { arithm::threshold, arithm::threshold, arithm::threshold, arithm::threshold, arithm::threshold, arithm::threshold, arithm::threshold }; if (depth != CV_32F && depth != CV_64F) { thresh = cvFloor(thresh); maxVal = cvRound(maxVal); } funcs[depth](src, dst, thresh, maxVal, type, stream); } return thresh; } //////////////////////////////////////////////////////////////////////// // pow namespace arithm { template void pow(PtrStepSzb src, double power, PtrStepSzb dst, cudaStream_t stream); } void cv::gpu::pow(const GpuMat& src, double power, GpuMat& dst, Stream& stream) { typedef void (*func_t)(PtrStepSzb src, double power, PtrStepSzb dst, cudaStream_t stream); static const func_t funcs[] = { arithm::pow, arithm::pow, arithm::pow, arithm::pow, arithm::pow, arithm::pow, arithm::pow }; const int depth = src.depth(); const int cn = src.channels(); CV_Assert(depth <= CV_64F); if (depth == CV_64F) { if (!deviceSupports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } dst.create(src.size(), src.type()); PtrStepSzb src_(src.rows, src.cols * cn, src.data, src.step); PtrStepSzb dst_(src.rows, src.cols * cn, dst.data, dst.step); funcs[depth](src_, power, dst_, 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 arithm { template void addWeighted(PtrStepSzb src1, double alpha, PtrStepSzb src2, double beta, double gamma, PtrStepSzb dst, cudaStream_t stream); } void cv::gpu::addWeighted(const GpuMat& src1, double alpha, const GpuMat& src2, double beta, double gamma, GpuMat& dst, int ddepth, Stream& stream) { typedef void (*func_t)(PtrStepSzb src1, double alpha, PtrStepSzb src2, double beta, double gamma, PtrStepSzb dst, cudaStream_t stream); static const func_t funcs[7][7][7] = { { { arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted }, { arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted }, { arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted }, { arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted }, { arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted }, { arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted }, { arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted } }, { { 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/ }, { arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted }, { arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted }, { arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted }, { arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted }, { arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted }, { arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted } }, { { 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/ }, { 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/ }, { arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted }, { arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted }, { arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted }, { arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted }, { arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted } }, { { 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/ }, { 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/ }, { 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/ }, { arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted }, { arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted }, { arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted }, { arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted } }, { { 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/ }, { 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/ }, { 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/ }, { 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/ }, { arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted }, { arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted }, { arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted } }, { { 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/ }, { 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/ }, { 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/ }, { 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/ }, { 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/ }, { arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted }, { arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted } }, { { 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/ }, { 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/ }, { 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/ }, { 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/ }, { 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/ }, { 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/, 0/*arithm::addWeighted*/ }, { arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted, arithm::addWeighted } } }; int sdepth1 = src1.depth(); int sdepth2 = src2.depth(); ddepth = ddepth >= 0 ? CV_MAT_DEPTH(ddepth) : std::max(sdepth1, sdepth2); const int cn = src1.channels(); CV_Assert( src2.size() == src1.size() && src2.channels() == cn ); CV_Assert( sdepth1 <= CV_64F && sdepth2 <= CV_64F && ddepth <= CV_64F ); if (sdepth1 == CV_64F || sdepth2 == CV_64F || ddepth == CV_64F) { if (!deviceSupports(NATIVE_DOUBLE)) CV_Error(CV_StsUnsupportedFormat, "The device doesn't support double"); } dst.create(src1.size(), CV_MAKE_TYPE(ddepth, cn)); PtrStepSzb src1_(src1.rows, src1.cols * cn, src1.data, src1.step); PtrStepSzb src2_(src1.rows, src1.cols * cn, src2.data, src2.step); PtrStepSzb dst_(src1.rows, src1.cols * cn, dst.data, dst.step); if (sdepth1 > sdepth2) { std::swap(src1_.data, src2_.data); std::swap(src1_.step, src2_.step); std::swap(alpha, beta); std::swap(sdepth1, sdepth2); } const func_t func = funcs[sdepth1][sdepth2][ddepth]; if (!func) CV_Error(CV_StsUnsupportedFormat, "Unsupported combination of source and destination types"); func(src1_, alpha, src2_, beta, gamma, dst_, StreamAccessor::getStream(stream)); } #endif