/*M/////////////////////////////////////////////////////////////////////////////////////// // // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. // // By downloading, copying, installing or using the software you agree to this license. // If you do not agree to this license, do not download, install, // copy or use the software. // // // License Agreement // For Open Source Computer Vision Library // // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. // Copyright (C) 2009, Willow Garage Inc., all rights reserved. // Third party copyrights are property of their respective owners. // // Redistribution and use in source and binary forms, with or without modification, // are permitted provided that the following conditions are met: // // * Redistribution's of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // // * Redistribution's in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other GpuMaterials provided with the distribution. // // * The name of the copyright holders may not be used to endorse or promote products // derived from this software without specific prior written permission. // // This software is provided by the copyright holders and contributors "as is" and // any express or bpied warranties, including, but not limited to, the bpied // warranties of merchantability and fitness for a particular purpose are disclaimed. // In no event shall the Intel Corporation or contributors be liable for any direct, // indirect, incidental, special, exemplary, or consequential damages // (including, but not limited to, procurement of substitute goods or services; // loss of use, data, or profits; or business interruption) however caused // and on any theory of liability, whether in contract, strict liability, // or tort (including negligence or otherwise) arising in any way out of // the use of this software, even if advised of the possibility of such damage. // //M*/ #include "precomp.hpp" using namespace cv; using namespace cv::gpu; #if !defined (HAVE_CUDA) void cv::gpu::add(const GpuMat&, const GpuMat&, GpuMat&, const GpuMat&, int, Stream&) { throw_nogpu(); } void cv::gpu::add(const GpuMat&, const Scalar&, GpuMat&, const GpuMat&, int, Stream&) { throw_nogpu(); } void cv::gpu::subtract(const GpuMat&, const GpuMat&, GpuMat&, const GpuMat&, int, Stream&) { throw_nogpu(); } void cv::gpu::subtract(const GpuMat&, const Scalar&, GpuMat&, const GpuMat&, int, Stream&) { throw_nogpu(); } void cv::gpu::multiply(const GpuMat&, const GpuMat&, GpuMat&, double, int, Stream&) { throw_nogpu(); } void cv::gpu::multiply(const GpuMat&, const Scalar&, GpuMat&, double, int, Stream&) { throw_nogpu(); } void cv::gpu::divide(const GpuMat&, const GpuMat&, GpuMat&, double, int, Stream&) { throw_nogpu(); } void cv::gpu::divide(const GpuMat&, const Scalar&, GpuMat&, double, int, Stream&) { throw_nogpu(); } void cv::gpu::divide(double, const GpuMat&, GpuMat&, int, Stream&) { throw_nogpu(); } void cv::gpu::absdiff(const GpuMat&, const GpuMat&, GpuMat&, Stream&) { throw_nogpu(); } void cv::gpu::absdiff(const GpuMat&, const Scalar&, GpuMat&, Stream&) { throw_nogpu(); } void cv::gpu::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_and(const GpuMat&, const GpuMat&, GpuMat&, const GpuMat&, Stream&) { throw_nogpu(); } void cv::gpu::bitwise_xor(const GpuMat&, const GpuMat&, GpuMat&, const 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::addWeighted(const GpuMat&, double, const GpuMat&, double, double, GpuMat&, int, Stream&) { throw_nogpu(); } #else //////////////////////////////////////////////////////////////////////// // Basic arithmetical operations (add subtract multiply divide) namespace { typedef NppStatus (*npp_arithm_8u_t)(const Npp8u* pSrc1, int nSrc1Step, const Npp8u* pSrc2, int nSrc2Step, Npp8u* pDst, int nDstStep, NppiSize oSizeROI, int nScaleFactor); typedef NppStatus (*npp_arithm_32s_t)(const Npp32s* pSrc1, int nSrc1Step, const Npp32s* pSrc2, int nSrc2Step, Npp32s* pDst, int nDstStep, NppiSize oSizeROI); typedef NppStatus (*npp_arithm_32f_t)(const Npp32f* pSrc1, int nSrc1Step, const Npp32f* pSrc2, int nSrc2Step, Npp32f* pDst, int nDstStep, NppiSize oSizeROI); void nppArithmCaller(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, npp_arithm_8u_t npp_func_8uc1, npp_arithm_8u_t npp_func_8uc4, npp_arithm_32s_t npp_func_32sc1, npp_arithm_32f_t npp_func_32fc1, cudaStream_t stream) { NppiSize sz; sz.width = src1.cols * src1.channels(); sz.height = src1.rows; NppStreamHandler h(stream); if (src1.depth() == CV_8U && (src1.cols * src1.channels()) % 4 == 0) { sz.width /= 4; nppSafeCall( npp_func_8uc4(src1.ptr(), static_cast(src1.step), src2.ptr(), static_cast(src2.step), dst.ptr(), static_cast(dst.step), sz, 0) ); } else if (src1.depth() == CV_8U) { nppSafeCall( npp_func_8uc1(src1.ptr(), static_cast(src1.step), src2.ptr(), static_cast(src2.step), dst.ptr(), static_cast(dst.step), sz, 0) ); } else if (src1.depth() == CV_32S) { nppSafeCall( npp_func_32sc1(src1.ptr(), static_cast(src1.step), src2.ptr(), static_cast(src2.step), dst.ptr(), static_cast(dst.step), sz) ); } else if (src1.depth() == CV_32F) { nppSafeCall( npp_func_32fc1(src1.ptr(), static_cast(src1.step), src2.ptr(), static_cast(src2.step), dst.ptr(), static_cast(dst.step), sz) ); } if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); } } //////////////////////////////////////////////////////////////////////// // add namespace cv { namespace gpu { namespace device { template void add_gpu(const DevMem2Db& src1, const DevMem2Db& src2, const DevMem2Db& dst, const PtrStepb& mask, cudaStream_t stream); template void add_gpu(const DevMem2Db& src1, double val, const DevMem2Db& dst, const PtrStepb& mask, cudaStream_t stream); }}} void cv::gpu::add(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, const GpuMat& mask, int dtype, Stream& s) { using namespace ::cv::gpu::device; typedef void (*func_t)(const DevMem2Db& src1, const DevMem2Db& src2, const DevMem2Db& dst, const PtrStepb& mask, cudaStream_t stream); static const func_t funcs[7][7] = { {add_gpu, 0/*add_gpu*/, add_gpu, add_gpu, add_gpu, add_gpu, add_gpu}, {0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/}, {0/*add_gpu*/, 0/*add_gpu*/, add_gpu, 0/*add_gpu*/, add_gpu, add_gpu, add_gpu}, {0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, add_gpu, add_gpu, add_gpu, add_gpu}, {0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, add_gpu, add_gpu, add_gpu}, {0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, add_gpu, add_gpu}, {0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, add_gpu} }; CV_Assert(src1.type() == src2.type() && src1.size() == src2.size()); CV_Assert(mask.empty() || (src1.channels() == 1 && mask.size() == src1.size() && mask.type() == CV_8U)); if (dtype < 0) dtype = src1.depth(); dst.create(src1.size(), CV_MAKE_TYPE(CV_MAT_DEPTH(dtype), src1.channels())); cudaStream_t stream = StreamAccessor::getStream(s); if (mask.empty() && dst.type() == src1.type() && (src1.depth() == CV_8U || src1.depth() == CV_32S || src1.depth() == CV_32F)) { nppArithmCaller(src1, src2, dst, nppiAdd_8u_C1RSfs, nppiAdd_8u_C4RSfs, nppiAdd_32s_C1R, nppiAdd_32f_C1R, stream); return; } const func_t func = funcs[src1.depth()][dst.depth()]; CV_Assert(func != 0); func(src1.reshape(1), src2.reshape(1), dst.reshape(1), mask, stream); } void cv::gpu::add(const GpuMat& src, const Scalar& sc, GpuMat& dst, const GpuMat& mask, int dtype, Stream& s) { using namespace ::cv::gpu::device; typedef void (*func_t)(const DevMem2Db& src1, double val, const DevMem2Db& dst, const PtrStepb& mask, cudaStream_t stream); static const func_t funcs[7][7] = { {add_gpu, 0/*add_gpu*/, add_gpu, add_gpu, add_gpu, add_gpu, add_gpu}, {0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/}, {0/*add_gpu*/, 0/*add_gpu*/, add_gpu, 0/*add_gpu*/, add_gpu, add_gpu, add_gpu}, {0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, add_gpu, add_gpu, add_gpu, add_gpu}, {0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, add_gpu, add_gpu, add_gpu}, {0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, add_gpu, add_gpu}, {0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, 0/*add_gpu*/, add_gpu} }; CV_Assert(src.channels() == 1 || src.type() == CV_32FC2); CV_Assert(mask.empty() || (src.channels() == 1 && mask.size() == src.size() && mask.type() == CV_8U)); if (dtype < 0) dtype = src.depth(); dst.create(src.size(), CV_MAKE_TYPE(CV_MAT_DEPTH(dtype), src.channels())); cudaStream_t stream = StreamAccessor::getStream(s); if (mask.empty() && dst.type() == src.type() && src.depth() == CV_32F) { NppiSize sz; sz.width = src.cols; sz.height = src.rows; NppStreamHandler h(stream); if (src.type() == CV_32FC1) { nppSafeCall( nppiAddC_32f_C1R(src.ptr(), static_cast(src.step), static_cast(sc.val[0]), dst.ptr(), static_cast(dst.step), sz) ); } else { Npp32fc nValue; nValue.re = static_cast(sc.val[0]); nValue.im = static_cast(sc.val[1]); nppSafeCall( nppiAddC_32fc_C1R(src.ptr(), static_cast(src.step), nValue, dst.ptr(), static_cast(dst.step), sz) ); } if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); return; } const func_t func = funcs[src.depth()][dst.depth()]; CV_Assert(func != 0); func(src, sc.val[0], dst, mask, stream); } //////////////////////////////////////////////////////////////////////// // subtract namespace cv { namespace gpu { namespace device { template void subtract_gpu(const DevMem2Db& src1, const DevMem2Db& src2, const DevMem2Db& dst, const PtrStepb& mask, cudaStream_t stream); template void subtract_gpu(const DevMem2Db& src1, double val, const DevMem2Db& dst, const PtrStepb& mask, cudaStream_t stream); }}} void cv::gpu::subtract(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, const GpuMat& mask, int dtype, Stream& s) { using namespace ::cv::gpu::device; typedef void (*func_t)(const DevMem2Db& src1, const DevMem2Db& src2, const DevMem2Db& dst, const PtrStepb& mask, cudaStream_t stream); static const func_t funcs[7][7] = { {subtract_gpu, 0/*subtract_gpu*/, subtract_gpu, subtract_gpu, subtract_gpu, subtract_gpu, subtract_gpu}, {0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/}, {0/*subtract_gpu*/, 0/*subtract_gpu*/, subtract_gpu, 0/*subtract_gpu*/, subtract_gpu, subtract_gpu, subtract_gpu}, {0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, subtract_gpu, subtract_gpu, subtract_gpu, subtract_gpu}, {0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, subtract_gpu, subtract_gpu, subtract_gpu}, {0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, subtract_gpu, subtract_gpu}, {0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, subtract_gpu} }; CV_Assert(src1.type() == src2.type() && src1.size() == src2.size()); CV_Assert(mask.empty() || (src1.channels() == 1 && mask.size() == src1.size() && mask.type() == CV_8U)); if (dtype < 0) dtype = src1.depth(); dst.create(src1.size(), CV_MAKE_TYPE(CV_MAT_DEPTH(dtype), src1.channels())); cudaStream_t stream = StreamAccessor::getStream(s); if (mask.empty() && dst.type() == src1.type() && (src1.depth() == CV_8U || src1.depth() == CV_32S || src1.depth() == CV_32F)) { nppArithmCaller(src2, src1, dst, nppiSub_8u_C1RSfs, nppiSub_8u_C4RSfs, nppiSub_32s_C1R, nppiSub_32f_C1R, stream); return; } const func_t func = funcs[src1.depth()][dst.depth()]; CV_Assert(func != 0); func(src1.reshape(1), src2.reshape(1), dst.reshape(1), mask, stream); } void cv::gpu::subtract(const GpuMat& src, const Scalar& sc, GpuMat& dst, const GpuMat& mask, int dtype, Stream& s) { using namespace ::cv::gpu::device; typedef void (*func_t)(const DevMem2Db& src1, double val, const DevMem2Db& dst, const PtrStepb& mask, cudaStream_t stream); static const func_t funcs[7][7] = { {subtract_gpu, 0/*subtract_gpu*/, subtract_gpu, subtract_gpu, subtract_gpu, subtract_gpu, subtract_gpu}, {0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/}, {0/*subtract_gpu*/, 0/*subtract_gpu*/, subtract_gpu, 0/*subtract_gpu*/, subtract_gpu, subtract_gpu, subtract_gpu}, {0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, subtract_gpu, subtract_gpu, subtract_gpu, subtract_gpu}, {0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, subtract_gpu, subtract_gpu, subtract_gpu}, {0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, subtract_gpu, subtract_gpu}, {0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, 0/*subtract_gpu*/, subtract_gpu} }; CV_Assert(src.channels() == 1 || src.type() == CV_32FC2); CV_Assert(mask.empty() || (src.channels() == 1 && mask.size() == src.size() && mask.type() == CV_8U)); if (dtype < 0) dtype = src.depth(); dst.create(src.size(), CV_MAKE_TYPE(CV_MAT_DEPTH(dtype), src.channels())); cudaStream_t stream = StreamAccessor::getStream(s); if (mask.empty() && dst.type() == src.type() && src.depth() == CV_32F) { NppiSize sz; sz.width = src.cols; sz.height = src.rows; NppStreamHandler h(stream); if (src.type() == CV_32FC1) { nppSafeCall( nppiSubC_32f_C1R(src.ptr(), static_cast(src.step), static_cast(sc.val[0]), dst.ptr(), static_cast(dst.step), sz) ); } else { Npp32fc nValue; nValue.re = static_cast(sc.val[0]); nValue.im = static_cast(sc.val[1]); nppSafeCall( nppiSubC_32fc_C1R(src.ptr(), static_cast(src.step), nValue, dst.ptr(), static_cast(dst.step), sz) ); } if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); return; } const func_t func = funcs[src.depth()][dst.depth()]; CV_Assert(func != 0); func(src, sc.val[0], dst, mask, stream); } //////////////////////////////////////////////////////////////////////// // multiply namespace cv { namespace gpu { namespace device { void multiply_gpu(const DevMem2D_& src1, const DevMem2Df& src2, const DevMem2D_& dst, cudaStream_t stream); void multiply_gpu(const DevMem2D_& src1, const DevMem2Df& src2, const DevMem2D_& dst, cudaStream_t stream); template void multiply_gpu(const DevMem2Db& src1, const DevMem2Db& src2, const DevMem2Db& dst, double scale, cudaStream_t stream); template void multiply_gpu(const DevMem2Db& src1, double val, const DevMem2Db& dst, double scale, cudaStream_t stream); }}} void cv::gpu::multiply(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, double scale, int dtype, Stream& s) { using namespace ::cv::gpu::device; typedef void (*func_t)(const DevMem2Db& src1, const DevMem2Db& src2, const DevMem2Db& dst, double scale, cudaStream_t stream); static const func_t funcs[7][7] = { {multiply_gpu, 0/*multiply_gpu*/, multiply_gpu, multiply_gpu, multiply_gpu, multiply_gpu, multiply_gpu}, {0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/}, {0/*multiply_gpu*/, 0/*multiply_gpu*/, multiply_gpu, 0/*multiply_gpu*/, multiply_gpu, multiply_gpu, multiply_gpu}, {0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, multiply_gpu, multiply_gpu, multiply_gpu, multiply_gpu}, {0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, multiply_gpu, multiply_gpu, multiply_gpu}, {0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, multiply_gpu, multiply_gpu}, {0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, multiply_gpu} }; cudaStream_t stream = StreamAccessor::getStream(s); if (src1.type() == CV_8UC4 && src2.type() == CV_32FC1) { CV_Assert(src1.size() == src2.size()); dst.create(src1.size(), src1.type()); multiply_gpu(static_cast >(src1), static_cast(src2), static_cast >(dst), stream); } else if (src1.type() == CV_16SC4 && src2.type() == CV_32FC1) { CV_Assert(src1.size() == src2.size()); dst.create(src1.size(), src1.type()); multiply_gpu(static_cast >(src1), static_cast(src2), static_cast >(dst), stream); } else { CV_Assert(src1.type() == src2.type() && src1.size() == src2.size()); if (dtype < 0) dtype = src1.depth(); dst.create(src1.size(), CV_MAKE_TYPE(CV_MAT_DEPTH(dtype), src1.channels())); if (scale == 1 && dst.type() == src1.type() && (src1.depth() == CV_8U || src1.depth() == CV_32S || src1.depth() == CV_32F)) { nppArithmCaller(src2, src1, dst, nppiMul_8u_C1RSfs, nppiMul_8u_C4RSfs, nppiMul_32s_C1R, nppiMul_32f_C1R, stream); return; } const func_t func = funcs[src1.depth()][dst.depth()]; CV_Assert(func != 0); func(src1.reshape(1), src2.reshape(1), dst.reshape(1), scale, stream); } } void cv::gpu::multiply(const GpuMat& src, const Scalar& sc, GpuMat& dst, double scale, int dtype, Stream& s) { using namespace ::cv::gpu::device; typedef void (*func_t)(const DevMem2Db& src1, double val, const DevMem2Db& dst, double scale, cudaStream_t stream); static const func_t funcs[7][7] = { {multiply_gpu, 0/*multiply_gpu*/, multiply_gpu, multiply_gpu, multiply_gpu, multiply_gpu, multiply_gpu}, {0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/}, {0/*multiply_gpu*/, 0/*multiply_gpu*/, multiply_gpu, 0/*multiply_gpu*/, multiply_gpu, multiply_gpu, multiply_gpu}, {0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, multiply_gpu, multiply_gpu, multiply_gpu, multiply_gpu}, {0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, multiply_gpu, multiply_gpu, multiply_gpu}, {0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, multiply_gpu, multiply_gpu}, {0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, 0/*multiply_gpu*/, multiply_gpu} }; //CV_Assert(src.channels() == 1); if (dtype < 0) dtype = src.depth(); dst.create(src.size(), CV_MAKE_TYPE(CV_MAT_DEPTH(dtype), src.channels())); cudaStream_t stream = StreamAccessor::getStream(s); if (dst.type() == src.type() && src.type() == CV_32FC1 && scale == 1) { NppiSize sz; sz.width = src.cols; sz.height = src.rows; NppStreamHandler h(stream); nppSafeCall( nppiMulC_32f_C1R(src.ptr(), static_cast(src.step), static_cast(sc.val[0]), dst.ptr(), static_cast(dst.step), sz) ); if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); return; } const func_t func = funcs[src.depth()][dst.depth()]; CV_Assert(func != 0); func(src.reshape(1), sc.val[0], dst.reshape(1), scale, stream); } //////////////////////////////////////////////////////////////////////// // divide namespace cv { namespace gpu { namespace device { void divide_gpu(const DevMem2D_& src1, const DevMem2Df& src2, const DevMem2D_& dst, cudaStream_t stream); void divide_gpu(const DevMem2D_& src1, const DevMem2Df& src2, const DevMem2D_& dst, cudaStream_t stream); template void divide_gpu(const DevMem2Db& src1, const DevMem2Db& src2, const DevMem2Db& dst, double scale, cudaStream_t stream); template void divide_gpu(const DevMem2Db& src1, double val, const DevMem2Db& dst, double scale, cudaStream_t stream); template void divide_gpu(double scalar, const DevMem2Db& src2, const DevMem2Db& dst, cudaStream_t stream); }}} void cv::gpu::divide(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, double scale, int dtype, Stream& s) { using namespace ::cv::gpu::device; typedef void (*func_t)(const DevMem2Db& src1, const DevMem2Db& src2, const DevMem2Db& dst, double scale, cudaStream_t stream); static const func_t funcs[7][7] = { {divide_gpu, 0/*divide_gpu*/, divide_gpu, divide_gpu, divide_gpu, divide_gpu, divide_gpu}, {0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/}, {0/*divide_gpu*/, 0/*divide_gpu*/, divide_gpu, 0/*divide_gpu*/, divide_gpu, divide_gpu, divide_gpu}, {0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, divide_gpu, divide_gpu, divide_gpu, divide_gpu}, {0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, divide_gpu, divide_gpu, divide_gpu}, {0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, divide_gpu, divide_gpu}, {0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, divide_gpu} }; cudaStream_t stream = StreamAccessor::getStream(s); if (src1.type() == CV_8UC4 && src2.type() == CV_32FC1) { CV_Assert(src1.size() == src2.size()); dst.create(src1.size(), src1.type()); multiply_gpu(static_cast >(src1), static_cast(src2), static_cast >(dst), stream); } else if (src1.type() == CV_16SC4 && src2.type() == CV_32FC1) { CV_Assert(src1.size() == src2.size()); dst.create(src1.size(), src1.type()); multiply_gpu(static_cast >(src1), static_cast(src2), static_cast >(dst), stream); } else { CV_Assert(src1.type() == src2.type() && src1.size() == src2.size()); if (dtype < 0) dtype = src1.depth(); dst.create(src1.size(), CV_MAKE_TYPE(CV_MAT_DEPTH(dtype), src1.channels())); if (scale == 1 && dst.type() == src1.type() && (src1.depth() == CV_8U || src1.depth() == CV_32S || src1.depth() == CV_32F)) { nppArithmCaller(src2, src1, dst, nppiDiv_8u_C1RSfs, nppiDiv_8u_C4RSfs, nppiDiv_32s_C1R, nppiDiv_32f_C1R, stream); return; } const func_t func = funcs[src1.depth()][dst.depth()]; CV_Assert(func != 0); func(src1.reshape(1), src2.reshape(1), dst.reshape(1), scale, stream); } } void cv::gpu::divide(const GpuMat& src, const Scalar& sc, GpuMat& dst, double scale, int dtype, Stream& s) { using namespace ::cv::gpu::device; typedef void (*func_t)(const DevMem2Db& src1, double val, const DevMem2Db& dst, double scale, cudaStream_t stream); static const func_t funcs[7][7] = { {divide_gpu, 0/*divide_gpu*/, divide_gpu, divide_gpu, divide_gpu, divide_gpu, divide_gpu}, {0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/}, {0/*divide_gpu*/, 0/*divide_gpu*/, divide_gpu, 0/*divide_gpu*/, divide_gpu, divide_gpu, divide_gpu}, {0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, divide_gpu, divide_gpu, divide_gpu, divide_gpu}, {0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, divide_gpu, divide_gpu, divide_gpu}, {0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, divide_gpu, divide_gpu}, {0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, divide_gpu} }; CV_Assert(src.channels() == 1); if (dtype < 0) dtype = src.depth(); dst.create(src.size(), CV_MAKE_TYPE(CV_MAT_DEPTH(dtype), src.channels())); cudaStream_t stream = StreamAccessor::getStream(s); if (dst.type() == src.type() && src.type() == CV_32FC1 && scale == 1) { NppiSize sz; sz.width = src.cols; sz.height = src.rows; NppStreamHandler h(stream); nppSafeCall( nppiDivC_32f_C1R(src.ptr(), static_cast(src.step), static_cast(sc.val[0]), dst.ptr(), static_cast(dst.step), sz) ); if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); return; } const func_t func = funcs[src.depth()][dst.depth()]; CV_Assert(func != 0); 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 DevMem2Db& src2, const DevMem2Db& dst, cudaStream_t stream); static const func_t funcs[7][7] = { {divide_gpu, 0/*divide_gpu*/, divide_gpu, divide_gpu, divide_gpu, divide_gpu, divide_gpu}, {0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/}, {0/*divide_gpu*/, 0/*divide_gpu*/, divide_gpu, 0/*divide_gpu*/, divide_gpu, divide_gpu, divide_gpu}, {0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, divide_gpu, divide_gpu, divide_gpu, divide_gpu}, {0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, divide_gpu, divide_gpu, divide_gpu}, {0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, divide_gpu, divide_gpu}, {0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, 0/*divide_gpu*/, divide_gpu} }; CV_Assert(src.channels() == 1); if (dtype < 0) dtype = src.depth(); dst.create(src.size(), CV_MAKE_TYPE(CV_MAT_DEPTH(dtype), src.channels())); cudaStream_t stream = StreamAccessor::getStream(s); const func_t func = funcs[src.depth()][dst.depth()]; CV_Assert(func != 0); func(scale, src, dst, stream); } ////////////////////////////////////////////////////////////////////////////// // absdiff namespace cv { namespace gpu { namespace device { template void absdiff_gpu(const DevMem2Db& src1, const DevMem2Db& src2, const DevMem2Db& dst, cudaStream_t stream); template void absdiff_gpu(const DevMem2Db& src1, double val, const DevMem2Db& dst, cudaStream_t stream); }}} void cv::gpu::absdiff(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, Stream& s) { using namespace ::cv::gpu::device; typedef void (*func_t)(const DevMem2Db& src1, const DevMem2Db& src2, const DevMem2Db& dst, cudaStream_t stream); static const func_t funcs[] = { 0/*absdiff_gpu*/, absdiff_gpu, absdiff_gpu, absdiff_gpu, 0/*absdiff_gpu*/, 0/*absdiff_gpu*/, absdiff_gpu }; CV_Assert(src1.size() == src2.size() && src1.type() == src2.type()); dst.create( src1.size(), src1.type() ); cudaStream_t stream = StreamAccessor::getStream(s); NppiSize sz; sz.width = src1.cols * src1.channels(); sz.height = src1.rows; if (src1.depth() == CV_8U && (src1.cols * src1.channels()) % 4 == 0) { NppStreamHandler h(stream); sz.width /= 4; nppSafeCall( nppiAbsDiff_8u_C4R(src1.ptr(), static_cast(src1.step), src2.ptr(), static_cast(src2.step), dst.ptr(), static_cast(dst.step), sz) ); if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); } else if (src1.depth() == CV_8U) { NppStreamHandler h(stream); nppSafeCall( nppiAbsDiff_8u_C1R(src1.ptr(), static_cast(src1.step), src2.ptr(), static_cast(src2.step), dst.ptr(), static_cast(dst.step), sz) ); if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); } else if (src1.depth() == CV_32S) { NppStreamHandler h(stream); nppSafeCall( nppiAbsDiff_32s_C1R(src1.ptr(), static_cast(src1.step), src2.ptr(), static_cast(src2.step), dst.ptr(), static_cast(dst.step), sz) ); if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); } else if (src1.depth() == CV_32F) { NppStreamHandler h(stream); nppSafeCall( nppiAbsDiff_32f_C1R(src1.ptr(), static_cast(src1.step), src2.ptr(), static_cast(src2.step), dst.ptr(), static_cast(dst.step), sz) ); if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); } else { const func_t func = funcs[src1.depth()]; CV_Assert(func != 0); func(src1.reshape(1), src2.reshape(1), dst.reshape(1), stream); } } void cv::gpu::absdiff(const GpuMat& src1, const Scalar& src2, GpuMat& dst, Stream& s) { using namespace ::cv::gpu::device; typedef void (*func_t)(const DevMem2Db& src1, double val, const DevMem2Db& dst, cudaStream_t stream); static const func_t funcs[] = { absdiff_gpu, absdiff_gpu, absdiff_gpu, absdiff_gpu,absdiff_gpu, 0/*absdiff_gpu*/, absdiff_gpu }; CV_Assert(src1.channels() == 1); dst.create(src1.size(), src1.type()); cudaStream_t stream = StreamAccessor::getStream(s); if (src1.type() == CV_32FC1) { NppiSize sz; sz.width = src1.cols; sz.height = src1.rows; cudaStream_t stream = StreamAccessor::getStream(s); NppStreamHandler h(stream); nppSafeCall( nppiAbsDiffC_32f_C1R(src1.ptr(), static_cast(src1.step), dst.ptr(), static_cast(dst.step), sz, static_cast(src2.val[0])) ); if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); return; } const func_t func = funcs[src1.depth()]; CV_Assert(func != 0); func(src1, src2.val[0], dst, stream); } ////////////////////////////////////////////////////////////////////////////// // Comparison of two matrixes namespace cv { namespace gpu { namespace device { template void compare_eq(const DevMem2Db& src1, const DevMem2Db& src2, const DevMem2Db& dst, cudaStream_t stream); template void compare_ne(const DevMem2Db& src1, const DevMem2Db& src2, const DevMem2Db& dst, cudaStream_t stream); template void compare_lt(const DevMem2Db& src1, const DevMem2Db& src2, const DevMem2Db& dst, cudaStream_t stream); template void compare_le(const DevMem2Db& src1, const DevMem2Db& src2, const DevMem2Db& dst, cudaStream_t stream); }}} void cv::gpu::compare(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, int cmpop, Stream& stream) { using namespace ::cv::gpu::device; typedef void (*func_t)(const DevMem2Db& src1, const DevMem2Db& src2, const DevMem2Db& dst, cudaStream_t stream); static const func_t funcs[7][4] = { {compare_eq, compare_ne, compare_lt, compare_le}, {compare_eq, compare_ne, compare_lt, compare_le}, {compare_eq, compare_ne, compare_lt, compare_le}, {compare_eq, compare_ne, compare_lt, compare_le}, {compare_eq, compare_ne, compare_lt, compare_le}, {compare_eq, compare_ne, compare_lt, compare_le}, {compare_eq, compare_ne, compare_lt, compare_le} }; CV_Assert(src1.size() == src2.size() && src1.type() == src2.type()); int code; const GpuMat* psrc1; const GpuMat* psrc2; switch (cmpop) { case CMP_EQ: code = 0; psrc1 = &src1; psrc2 = &src2; break; case CMP_GE: code = 3; psrc1 = &src2; psrc2 = &src1; break; case CMP_GT: code = 2; psrc1 = &src2; psrc2 = &src1; break; case CMP_LE: code = 3; psrc1 = &src1; psrc2 = &src2; break; case CMP_LT: code = 2; psrc1 = &src1; psrc2 = &src2; break; case CMP_NE: code = 1; psrc1 = &src1; psrc2 = &src2; break; default: CV_Error(CV_StsBadFlag, "Incorrect compare operation"); }; dst.create(src1.size(), CV_MAKE_TYPE(CV_8U, src1.channels())); funcs[src1.depth()][code](psrc1->reshape(1), psrc2->reshape(1), dst.reshape(1), StreamAccessor::getStream(stream)); } ////////////////////////////////////////////////////////////////////////////// // Unary bitwise logical operations namespace cv { namespace gpu { namespace device { void bitwiseNotCaller(int rows, int cols, size_t elem_size1, int cn, const PtrStepb src, PtrStepb dst, cudaStream_t stream); template void bitwiseMaskNotCaller(int rows, int cols, int cn, const PtrStepb src, const PtrStepb mask, PtrStepb dst, cudaStream_t stream); }}} namespace { void bitwiseNotCaller(const GpuMat& src, GpuMat& dst, cudaStream_t stream) { dst.create(src.size(), src.type()); ::cv::gpu::device::bitwiseNotCaller(src.rows, src.cols, src.elemSize1(), dst.channels(), src, dst, stream); } void bitwiseNotCaller(const GpuMat& src, GpuMat& dst, const GpuMat& mask, cudaStream_t stream) { using namespace ::cv::gpu::device; typedef void (*Caller)(int, int, int, const PtrStepb, const PtrStepb, PtrStepb, cudaStream_t); static Caller callers[] = { bitwiseMaskNotCaller, bitwiseMaskNotCaller, bitwiseMaskNotCaller, bitwiseMaskNotCaller, bitwiseMaskNotCaller, bitwiseMaskNotCaller, bitwiseMaskNotCaller }; CV_Assert(mask.type() == CV_8U && mask.size() == src.size()); dst.create(src.size(), src.type()); Caller caller = callers[src.depth()]; CV_Assert(caller); int cn = src.depth() != CV_64F ? src.channels() : src.channels() * (sizeof(double) / sizeof(unsigned int)); caller(src.rows, src.cols, cn, src, mask, dst, stream); } } void cv::gpu::bitwise_not(const GpuMat& src, GpuMat& dst, const GpuMat& mask, Stream& stream) { if (mask.empty()) bitwiseNotCaller(src, dst, StreamAccessor::getStream(stream)); else bitwiseNotCaller(src, dst, mask, StreamAccessor::getStream(stream)); } ////////////////////////////////////////////////////////////////////////////// // Binary bitwise logical operations namespace cv { namespace gpu { namespace device { void bitwiseOrCaller(int rows, int cols, size_t elem_size1, int cn, const PtrStepb src1, const PtrStepb src2, PtrStepb dst, cudaStream_t stream); template void bitwiseMaskOrCaller(int rows, int cols, int cn, const PtrStepb src1, const PtrStepb src2, const PtrStepb mask, PtrStepb dst, cudaStream_t stream); void bitwiseAndCaller(int rows, int cols, size_t elem_size1, int cn, const PtrStepb src1, const PtrStepb src2, PtrStepb dst, cudaStream_t stream); template void bitwiseMaskAndCaller(int rows, int cols, int cn, const PtrStepb src1, const PtrStepb src2, const PtrStepb mask, PtrStepb dst, cudaStream_t stream); void bitwiseXorCaller(int rows, int cols, size_t elem_size1, int cn, const PtrStepb src1, const PtrStepb src2, PtrStepb dst, cudaStream_t stream); template void bitwiseMaskXorCaller(int rows, int cols, int cn, const PtrStepb src1, const PtrStepb src2, const PtrStepb mask, PtrStepb dst, cudaStream_t stream); }}} namespace { void bitwiseOrCaller(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, cudaStream_t stream) { CV_Assert(src1.size() == src2.size() && src1.type() == src2.type()); dst.create(src1.size(), src1.type()); ::cv::gpu::device::bitwiseOrCaller(dst.rows, dst.cols, dst.elemSize1(), dst.channels(), src1, src2, dst, stream); } void bitwiseOrCaller(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, const GpuMat& mask, cudaStream_t stream) { using namespace ::cv::gpu::device; typedef void (*Caller)(int, int, int, const PtrStepb, const PtrStepb, const PtrStepb, PtrStepb, cudaStream_t); static Caller callers[] = { bitwiseMaskOrCaller, bitwiseMaskOrCaller, bitwiseMaskOrCaller, bitwiseMaskOrCaller, bitwiseMaskOrCaller, bitwiseMaskOrCaller, bitwiseMaskOrCaller }; CV_Assert(src1.size() == src2.size() && src1.type() == src2.type()); dst.create(src1.size(), src1.type()); Caller caller = callers[src1.depth()]; CV_Assert(caller); int cn = dst.depth() != CV_64F ? dst.channels() : dst.channels() * (sizeof(double) / sizeof(unsigned int)); caller(dst.rows, dst.cols, cn, src1, src2, mask, dst, stream); } void bitwiseAndCaller(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, cudaStream_t stream) { CV_Assert(src1.size() == src2.size() && src1.type() == src2.type()); dst.create(src1.size(), src1.type()); ::cv::gpu::device::bitwiseAndCaller(dst.rows, dst.cols, dst.elemSize1(), dst.channels(), src1, src2, dst, stream); } void bitwiseAndCaller(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, const GpuMat& mask, cudaStream_t stream) { using namespace ::cv::gpu::device; typedef void (*Caller)(int, int, int, const PtrStepb, const PtrStepb, const PtrStepb, PtrStepb, cudaStream_t); static Caller callers[] = { bitwiseMaskAndCaller, bitwiseMaskAndCaller, bitwiseMaskAndCaller, bitwiseMaskAndCaller, bitwiseMaskAndCaller, bitwiseMaskAndCaller, bitwiseMaskAndCaller }; CV_Assert(src1.size() == src2.size() && src1.type() == src2.type()); dst.create(src1.size(), src1.type()); Caller caller = callers[src1.depth()]; CV_Assert(caller); int cn = dst.depth() != CV_64F ? dst.channels() : dst.channels() * (sizeof(double) / sizeof(unsigned int)); caller(dst.rows, dst.cols, cn, src1, src2, mask, dst, stream); } void bitwiseXorCaller(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, cudaStream_t stream) { CV_Assert(src1.size() == src2.size() && src1.type() == src2.type()); dst.create(src1.size(), src1.type()); ::cv::gpu::device::bitwiseXorCaller(dst.rows, dst.cols, dst.elemSize1(), dst.channels(), src1, src2, dst, stream); } void bitwiseXorCaller(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, const GpuMat& mask, cudaStream_t stream) { using namespace ::cv::gpu::device; typedef void (*Caller)(int, int, int, const PtrStepb, const PtrStepb, const PtrStepb, PtrStepb, cudaStream_t); static Caller callers[] = { bitwiseMaskXorCaller, bitwiseMaskXorCaller, bitwiseMaskXorCaller, bitwiseMaskXorCaller, bitwiseMaskXorCaller, bitwiseMaskXorCaller, bitwiseMaskXorCaller }; CV_Assert(src1.size() == src2.size() && src1.type() == src2.type()); dst.create(src1.size(), src1.type()); Caller caller = callers[src1.depth()]; CV_Assert(caller); int cn = dst.depth() != CV_64F ? dst.channels() : dst.channels() * (sizeof(double) / sizeof(unsigned int)); caller(dst.rows, dst.cols, cn, src1, src2, mask, dst, stream); } } void cv::gpu::bitwise_or(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, const GpuMat& mask, Stream& stream) { if (mask.empty()) bitwiseOrCaller(src1, src2, dst, StreamAccessor::getStream(stream)); else bitwiseOrCaller(src1, src2, dst, mask, StreamAccessor::getStream(stream)); } void cv::gpu::bitwise_and(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, const GpuMat& mask, Stream& stream) { if (mask.empty()) bitwiseAndCaller(src1, src2, dst, StreamAccessor::getStream(stream)); else bitwiseAndCaller(src1, src2, dst, mask, StreamAccessor::getStream(stream)); } void cv::gpu::bitwise_xor(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, const GpuMat& mask, Stream& stream) { if (mask.empty()) bitwiseXorCaller(src1, src2, dst, StreamAccessor::getStream(stream)); else bitwiseXorCaller(src1, src2, dst, mask, StreamAccessor::getStream(stream)); } ////////////////////////////////////////////////////////////////////////////// // Minimum and maximum operations namespace cv { namespace gpu { namespace device { template void min_gpu(const DevMem2D_& src1, const DevMem2D_& src2, const DevMem2D_& dst, cudaStream_t stream); template void max_gpu(const DevMem2D_& src1, const DevMem2D_& src2, const DevMem2D_& dst, cudaStream_t stream); template void min_gpu(const DevMem2D_& src1, T src2, const DevMem2D_& dst, cudaStream_t stream); template void max_gpu(const DevMem2D_& src1, T src2, const DevMem2D_& dst, cudaStream_t stream); }}} namespace { template void min_caller(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, cudaStream_t stream) { CV_Assert(src1.size() == src2.size() && src1.type() == src2.type()); dst.create(src1.size(), src1.type()); ::cv::gpu::device::min_gpu(src1.reshape(1), src2.reshape(1), dst.reshape(1), stream); } template void min_caller(const GpuMat& src1, double src2, GpuMat& dst, cudaStream_t stream) { dst.create(src1.size(), src1.type()); ::cv::gpu::device::min_gpu(src1.reshape(1), saturate_cast(src2), dst.reshape(1), stream); } template void max_caller(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, cudaStream_t stream) { CV_Assert(src1.size() == src2.size() && src1.type() == src2.type()); dst.create(src1.size(), src1.type()); ::cv::gpu::device::max_gpu(src1.reshape(1), src2.reshape(1), dst.reshape(1), stream); } template void max_caller(const GpuMat& src1, double src2, GpuMat& dst, cudaStream_t stream) { dst.create(src1.size(), src1.type()); ::cv::gpu::device::max_gpu(src1.reshape(1), saturate_cast(src2), dst.reshape(1), stream); } } void cv::gpu::min(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, Stream& stream) { CV_Assert(src1.size() == src2.size() && src1.type() == src2.type()); CV_Assert((src1.depth() != CV_64F) || (TargetArchs::builtWith(NATIVE_DOUBLE) && DeviceInfo().supports(NATIVE_DOUBLE))); typedef void (*func_t)(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, cudaStream_t stream); static const func_t funcs[] = { min_caller, min_caller, min_caller, min_caller, min_caller, min_caller, min_caller }; funcs[src1.depth()](src1, src2, dst, StreamAccessor::getStream(stream)); } void cv::gpu::min(const GpuMat& src1, double src2, GpuMat& dst, Stream& stream) { CV_Assert((src1.depth() != CV_64F) || (TargetArchs::builtWith(NATIVE_DOUBLE) && DeviceInfo().supports(NATIVE_DOUBLE))); typedef void (*func_t)(const GpuMat& src1, double src2, GpuMat& dst, cudaStream_t stream); static const func_t funcs[] = { min_caller, min_caller, min_caller, min_caller, min_caller, min_caller, min_caller }; funcs[src1.depth()](src1, src2, dst, StreamAccessor::getStream(stream)); } void cv::gpu::max(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, Stream& stream) { CV_Assert(src1.size() == src2.size() && src1.type() == src2.type()); CV_Assert((src1.depth() != CV_64F) || (TargetArchs::builtWith(NATIVE_DOUBLE) && DeviceInfo().supports(NATIVE_DOUBLE))); typedef void (*func_t)(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, cudaStream_t stream); static const func_t funcs[] = { max_caller, max_caller, max_caller, max_caller, max_caller, max_caller, max_caller }; funcs[src1.depth()](src1, src2, dst, StreamAccessor::getStream(stream)); } void cv::gpu::max(const GpuMat& src1, double src2, GpuMat& dst, Stream& stream) { CV_Assert((src1.depth() != CV_64F) || (TargetArchs::builtWith(NATIVE_DOUBLE) && DeviceInfo().supports(NATIVE_DOUBLE))); typedef void (*func_t)(const GpuMat& src1, double src2, GpuMat& dst, cudaStream_t stream); static const func_t funcs[] = { max_caller, max_caller, max_caller, max_caller, max_caller, max_caller, max_caller }; funcs[src1.depth()](src1, src2, dst, StreamAccessor::getStream(stream)); } //////////////////////////////////////////////////////////////////////// // threshold namespace cv { namespace gpu { namespace device { template void threshold_gpu(const DevMem2Db& src, const DevMem2Db& dst, T thresh, T maxVal, int type, cudaStream_t stream); }}} namespace { template void threshold_caller(const GpuMat& src, GpuMat& dst, double thresh, double maxVal, int type, cudaStream_t stream) { ::cv::gpu::device::threshold_gpu(src, dst, saturate_cast(thresh), saturate_cast(maxVal), type, stream); } } double cv::gpu::threshold(const GpuMat& src, GpuMat& dst, double thresh, double maxVal, int type, Stream& s) { CV_Assert(src.channels() == 1 && src.depth() <= CV_64F); CV_Assert(type <= THRESH_TOZERO_INV); dst.create(src.size(), src.type()); cudaStream_t stream = StreamAccessor::getStream(s); if (src.type() == CV_32FC1 && type == THRESH_TRUNC) { NppStreamHandler h(stream); NppiSize sz; sz.width = src.cols; sz.height = src.rows; nppSafeCall( nppiThreshold_32f_C1R(src.ptr(), static_cast(src.step), dst.ptr(), static_cast(dst.step), sz, static_cast(thresh), NPP_CMP_GREATER) ); if (stream == 0) cudaSafeCall( cudaDeviceSynchronize() ); } else { CV_Assert((src.depth() != CV_64F) || (TargetArchs::builtWith(NATIVE_DOUBLE) && DeviceInfo().supports(NATIVE_DOUBLE))); typedef void (*caller_t)(const GpuMat& src, GpuMat& dst, double thresh, double maxVal, int type, cudaStream_t stream); static const caller_t callers[] = { threshold_caller, threshold_caller, threshold_caller, threshold_caller, threshold_caller, threshold_caller, threshold_caller }; if (src.depth() != CV_32F && src.depth() != CV_64F) { thresh = cvFloor(thresh); maxVal = cvRound(maxVal); } callers[src.depth()](src, dst, thresh, maxVal, type, stream); } return thresh; } //////////////////////////////////////////////////////////////////////// // pow namespace cv { namespace gpu { namespace device { template void pow_caller(const DevMem2Db& src, float power, DevMem2Db dst, cudaStream_t stream); }}} void cv::gpu::pow(const GpuMat& src, double power, GpuMat& dst, Stream& stream) { using namespace ::cv::gpu::device; CV_Assert(src.depth() != CV_64F); dst.create(src.size(), src.type()); typedef void (*caller_t)(const DevMem2Db& src, float power, DevMem2Db dst, cudaStream_t stream); static const caller_t callers[] = { pow_caller, pow_caller, pow_caller, pow_caller, pow_caller, pow_caller }; callers[src.depth()](src.reshape(1), (float)power, dst.reshape(1), StreamAccessor::getStream(stream)); } //////////////////////////////////////////////////////////////////////// // addWeighted namespace cv { namespace gpu { namespace device { template void addWeighted_gpu(const DevMem2Db& src1, double alpha, const DevMem2Db& src2, double beta, double gamma, const DevMem2Db& dst, cudaStream_t stream); }}} void cv::gpu::addWeighted(const GpuMat& src1, double alpha, const GpuMat& src2, double beta, double gamma, GpuMat& dst, int dtype, Stream& stream) { using namespace ::cv::gpu::device; CV_Assert(src1.size() == src2.size()); CV_Assert(src1.type() == src2.type() || (dtype >= 0 && src1.channels() == src2.channels())); dtype = dtype >= 0 ? CV_MAKETYPE(dtype, src1.channels()) : src1.type(); dst.create(src1.size(), dtype); const GpuMat* psrc1 = &src1; const GpuMat* psrc2 = &src2; if (src1.depth() > src2.depth()) { std::swap(psrc1, psrc2); std::swap(alpha, beta); } typedef void (*caller_t)(const DevMem2Db& src1, double alpha, const DevMem2Db& src2, double beta, double gamma, const DevMem2Db& dst, cudaStream_t stream); static const caller_t callers[7][7][7] = { { { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu } }, { { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu } }, { { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu } }, { { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu } }, { { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu } }, { { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu } }, { { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/, 0/*addWeighted_gpu*/ }, { addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu, addWeighted_gpu } } }; callers[psrc1->depth()][psrc2->depth()][dst.depth()](psrc1->reshape(1), alpha, psrc2->reshape(1), beta, gamma, dst.reshape(1), StreamAccessor::getStream(stream)); } #endif