arithm.cpp 38.0 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
/*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;
using namespace std;

#if !defined (HAVE_CUDA)

51
void cv::gpu::add(const GpuMat&, const GpuMat&, GpuMat&) { throw_nogpu(); }
52
void cv::gpu::add(const GpuMat&, const Scalar&, GpuMat&) { throw_nogpu(); }
53
void cv::gpu::subtract(const GpuMat&, const GpuMat&, GpuMat&) { throw_nogpu(); }
54
void cv::gpu::subtract(const GpuMat&, const Scalar&, GpuMat&) { throw_nogpu(); }
55
void cv::gpu::multiply(const GpuMat&, const GpuMat&, GpuMat&) { throw_nogpu(); }
56
void cv::gpu::multiply(const GpuMat&, const Scalar&, GpuMat&) { throw_nogpu(); }
57
void cv::gpu::divide(const GpuMat&, const GpuMat&, GpuMat&) { throw_nogpu(); }
58
void cv::gpu::divide(const GpuMat&, const Scalar&, GpuMat&) { throw_nogpu(); }
59 60
void cv::gpu::transpose(const GpuMat&, GpuMat&) { throw_nogpu(); }
void cv::gpu::absdiff(const GpuMat&, const GpuMat&, GpuMat&) { throw_nogpu(); }
61
void cv::gpu::absdiff(const GpuMat&, const Scalar&, GpuMat&) { throw_nogpu(); }
62 63 64 65 66 67 68
void cv::gpu::compare(const GpuMat&, const GpuMat&, GpuMat&, int) { throw_nogpu(); }
void cv::gpu::meanStdDev(const GpuMat&, Scalar&, Scalar&) { throw_nogpu(); }
double cv::gpu::norm(const GpuMat&, int) { throw_nogpu(); return 0.0; }
double cv::gpu::norm(const GpuMat&, const GpuMat&, int) { throw_nogpu(); return 0.0; }
void cv::gpu::flip(const GpuMat&, GpuMat&, int) { throw_nogpu(); }
Scalar cv::gpu::sum(const GpuMat&) { throw_nogpu(); return Scalar(); }
void cv::gpu::minMax(const GpuMat&, double*, double*) { throw_nogpu(); }
69
void cv::gpu::minMax(const GpuMat&, double*, double*, GpuMat&) { throw_nogpu(); }
70
void cv::gpu::minMaxLoc(const GpuMat&, double*, double*, Point*, Point*) { throw_nogpu(); }
71 72 73
void cv::gpu::LUT(const GpuMat&, const Mat&, GpuMat&) { throw_nogpu(); }
void cv::gpu::exp(const GpuMat&, GpuMat&) { throw_nogpu(); }
void cv::gpu::log(const GpuMat&, GpuMat&) { throw_nogpu(); }
74
void cv::gpu::magnitude(const GpuMat&, GpuMat&) { throw_nogpu(); }
75
void cv::gpu::magnitudeSqr(const GpuMat&, GpuMat&) { throw_nogpu(); }
76 77 78 79 80 81 82 83 84 85
void cv::gpu::magnitude(const GpuMat&, const GpuMat&, GpuMat&) { throw_nogpu(); }
void cv::gpu::magnitude(const GpuMat&, const GpuMat&, GpuMat&, const Stream&) { throw_nogpu(); }
void cv::gpu::magnitudeSqr(const GpuMat&, const GpuMat&, GpuMat&) { throw_nogpu(); }
void cv::gpu::magnitudeSqr(const GpuMat&, const GpuMat&, GpuMat&, const Stream&) { throw_nogpu(); }
void cv::gpu::phase(const GpuMat&, const GpuMat&, GpuMat&, bool) { throw_nogpu(); }
void cv::gpu::phase(const GpuMat&, const GpuMat&, GpuMat&, bool, const Stream&) { throw_nogpu(); }
void cv::gpu::cartToPolar(const GpuMat&, const GpuMat&, GpuMat&, GpuMat&, bool) { throw_nogpu(); }
void cv::gpu::cartToPolar(const GpuMat&, const GpuMat&, GpuMat&, GpuMat&, bool, const Stream&) { throw_nogpu(); }
void cv::gpu::polarToCart(const GpuMat&, const GpuMat&, GpuMat&, GpuMat&, bool) { throw_nogpu(); }
void cv::gpu::polarToCart(const GpuMat&, const GpuMat&, GpuMat&, GpuMat&, bool, const Stream&) { throw_nogpu(); }
86 87 88 89 90 91 92 93
void cv::gpu::bitwise_not(const GpuMat&, GpuMat&, const GpuMat&) { throw_nogpu(); }
void cv::gpu::bitwise_not(const GpuMat&, GpuMat&, const GpuMat&, const Stream&) { throw_nogpu(); }
void cv::gpu::bitwise_or(const GpuMat&, const GpuMat&, GpuMat&, const GpuMat&) { throw_nogpu(); }
void cv::gpu::bitwise_or(const GpuMat&, const GpuMat&, GpuMat&, const GpuMat&, const Stream&) { throw_nogpu(); }
void cv::gpu::bitwise_and(const GpuMat&, const GpuMat&, GpuMat&, const GpuMat&) { throw_nogpu(); }
void cv::gpu::bitwise_and(const GpuMat&, const GpuMat&, GpuMat&, const GpuMat&, const Stream&) { throw_nogpu(); }
void cv::gpu::bitwise_xor(const GpuMat&, const GpuMat&, GpuMat&, const GpuMat&) { throw_nogpu(); }
void cv::gpu::bitwise_xor(const GpuMat&, const GpuMat&, GpuMat&, const GpuMat&, const Stream&) { throw_nogpu(); }
94 95 96 97
cv::gpu::GpuMat cv::gpu::operator ~ (const GpuMat&) { throw_nogpu(); return GpuMat(); }
cv::gpu::GpuMat cv::gpu::operator | (const GpuMat&, const GpuMat&) { throw_nogpu(); return GpuMat(); }
cv::gpu::GpuMat cv::gpu::operator & (const GpuMat&, const GpuMat&) { throw_nogpu(); return GpuMat(); }
cv::gpu::GpuMat cv::gpu::operator ^ (const GpuMat&, const GpuMat&) { throw_nogpu(); return GpuMat(); }
98

99 100
#else /* !defined (HAVE_CUDA) */

101 102 103
////////////////////////////////////////////////////////////////////////
// add subtract multiply divide

104
namespace
105
{
106 107 108 109 110 111
    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);
112

113 114
    void nppArithmCaller(const GpuMat& src1, const GpuMat& src2, GpuMat& dst,
                         npp_arithm_8u_t npp_func_8uc1, npp_arithm_8u_t npp_func_8uc4,
115
                         npp_arithm_32s_t npp_func_32sc1, npp_arithm_32f_t npp_func_32fc1)
116
    {
117 118
        CV_DbgAssert(src1.size() == src2.size() && src1.type() == src2.type());

119
        CV_Assert(src1.type() == CV_8UC1 || src1.type() == CV_8UC4 || src1.type() == CV_32SC1 || src1.type() == CV_32FC1);
120 121 122

        dst.create( src1.size(), src1.type() );

123 124 125
        NppiSize sz;
        sz.width  = src1.cols;
        sz.height = src1.rows;
126

127 128 129
        switch (src1.type())
        {
        case CV_8UC1:
130 131 132
            nppSafeCall( npp_func_8uc1(src1.ptr<Npp8u>(), src1.step,
                src2.ptr<Npp8u>(), src2.step,
                dst.ptr<Npp8u>(), dst.step, sz, 0) );
133 134
            break;
        case CV_8UC4:
135 136 137
            nppSafeCall( npp_func_8uc4(src1.ptr<Npp8u>(), src1.step,
                src2.ptr<Npp8u>(), src2.step,
                dst.ptr<Npp8u>(), dst.step, sz, 0) );
138
            break;
139
        case CV_32SC1:
140 141 142
            nppSafeCall( npp_func_32sc1(src1.ptr<Npp32s>(), src1.step,
                src2.ptr<Npp32s>(), src2.step,
                dst.ptr<Npp32s>(), dst.step, sz) );
143
            break;
144
        case CV_32FC1:
145 146 147
            nppSafeCall( npp_func_32fc1(src1.ptr<Npp32f>(), src1.step,
                src2.ptr<Npp32f>(), src2.step,
                dst.ptr<Npp32f>(), dst.step, sz) );
148 149 150 151
            break;
        default:
            CV_Assert(!"Unsupported source type");
        }
152
    }
153

154 155 156
    template<int SCN> struct NppArithmScalarFunc;
    template<> struct NppArithmScalarFunc<1>
    {
157
        typedef NppStatus (*func_ptr)(const Npp32f *pSrc, int nSrcStep, Npp32f nValue, Npp32f *pDst,
158 159 160
                                      int nDstStep, NppiSize oSizeROI);
    };
    template<> struct NppArithmScalarFunc<2>
161
    {
162 163 164
        typedef NppStatus (*func_ptr)(const Npp32fc *pSrc, int nSrcStep, Npp32fc nValue, Npp32fc *pDst,
                                      int nDstStep, NppiSize oSizeROI);
    };
165

166 167 168 169
    template<int SCN, typename NppArithmScalarFunc<SCN>::func_ptr func> struct NppArithmScalar;
    template<typename NppArithmScalarFunc<1>::func_ptr func> struct NppArithmScalar<1, func>
    {
        static void calc(const GpuMat& src, const Scalar& sc, GpuMat& dst)
170
        {
171
            dst.create(src.size(), src.type());
172

173 174 175
            NppiSize sz;
            sz.width  = src.cols;
            sz.height = src.rows;
176

177 178
            nppSafeCall( func(src.ptr<Npp32f>(), src.step, (Npp32f)sc[0], dst.ptr<Npp32f>(), dst.step, sz) );
        }
179 180 181 182
    };
    template<typename NppArithmScalarFunc<2>::func_ptr func> struct NppArithmScalar<2, func>
    {
        static void calc(const GpuMat& src, const Scalar& sc, GpuMat& dst)
183
        {
184
            dst.create(src.size(), src.type());
185

186 187 188
            NppiSize sz;
            sz.width  = src.cols;
            sz.height = src.rows;
189 190 191 192 193

            Npp32fc nValue;
            nValue.re = (Npp32f)sc[0];
            nValue.im = (Npp32f)sc[1];

194 195
            nppSafeCall( func(src.ptr<Npp32fc>(), src.step, nValue, dst.ptr<Npp32fc>(), dst.step, sz) );
        }
196
    };
197 198
}

199 200
void cv::gpu::add(const GpuMat& src1, const GpuMat& src2, GpuMat& dst)
{
201
    nppArithmCaller(src1, src2, dst, nppiAdd_8u_C1RSfs, nppiAdd_8u_C4RSfs, nppiAdd_32s_C1R, nppiAdd_32f_C1R);
202 203
}

204
void cv::gpu::subtract(const GpuMat& src1, const GpuMat& src2, GpuMat& dst)
205
{
206
    nppArithmCaller(src2, src1, dst, nppiSub_8u_C1RSfs, nppiSub_8u_C4RSfs, nppiSub_32s_C1R, nppiSub_32f_C1R);
207 208 209 210
}

void cv::gpu::multiply(const GpuMat& src1, const GpuMat& src2, GpuMat& dst)
{
211
    nppArithmCaller(src1, src2, dst, nppiMul_8u_C1RSfs, nppiMul_8u_C4RSfs, nppiMul_32s_C1R, nppiMul_32f_C1R);
212 213 214 215
}

void cv::gpu::divide(const GpuMat& src1, const GpuMat& src2, GpuMat& dst)
{
216
    nppArithmCaller(src2, src1, dst, nppiDiv_8u_C1RSfs, nppiDiv_8u_C4RSfs, nppiDiv_32s_C1R, nppiDiv_32f_C1R);
217 218 219 220
}

void cv::gpu::add(const GpuMat& src, const Scalar& sc, GpuMat& dst)
{
221
    typedef void (*caller_t)(const GpuMat& src, const Scalar& sc, GpuMat& dst);
222
    static const caller_t callers[] = {0, NppArithmScalar<1, nppiAddC_32f_C1R>::calc, NppArithmScalar<2, nppiAddC_32fc_C1R>::calc};
223 224 225 226

    CV_Assert(src.type() == CV_32FC1 || src.type() == CV_32FC2);

    callers[src.channels()](src, sc, dst);
227 228 229 230
}

void cv::gpu::subtract(const GpuMat& src, const Scalar& sc, GpuMat& dst)
{
231
    typedef void (*caller_t)(const GpuMat& src, const Scalar& sc, GpuMat& dst);
232
    static const caller_t callers[] = {0, NppArithmScalar<1, nppiSubC_32f_C1R>::calc, NppArithmScalar<2, nppiSubC_32fc_C1R>::calc};
233 234 235 236

    CV_Assert(src.type() == CV_32FC1 || src.type() == CV_32FC2);

    callers[src.channels()](src, sc, dst);
237 238 239 240
}

void cv::gpu::multiply(const GpuMat& src, const Scalar& sc, GpuMat& dst)
{
241
    typedef void (*caller_t)(const GpuMat& src, const Scalar& sc, GpuMat& dst);
242
    static const caller_t callers[] = {0, NppArithmScalar<1, nppiMulC_32f_C1R>::calc, NppArithmScalar<2, nppiMulC_32fc_C1R>::calc};
243 244 245 246

    CV_Assert(src.type() == CV_32FC1 || src.type() == CV_32FC2);

    callers[src.channels()](src, sc, dst);
247 248 249 250
}

void cv::gpu::divide(const GpuMat& src, const Scalar& sc, GpuMat& dst)
{
251
    typedef void (*caller_t)(const GpuMat& src, const Scalar& sc, GpuMat& dst);
252
    static const caller_t callers[] = {0, NppArithmScalar<1, nppiDivC_32f_C1R>::calc, NppArithmScalar<2, nppiDivC_32fc_C1R>::calc};
253 254 255 256

    CV_Assert(src.type() == CV_32FC1 || src.type() == CV_32FC2);

    callers[src.channels()](src, sc, dst);
257 258
}

259 260 261
////////////////////////////////////////////////////////////////////////
// transpose

262 263 264 265 266 267 268 269 270 271
void cv::gpu::transpose(const GpuMat& src, GpuMat& dst)
{
    CV_Assert(src.type() == CV_8UC1);

    dst.create( src.cols, src.rows, src.type() );

    NppiSize sz;
    sz.width  = src.cols;
    sz.height = src.rows;

272
    nppSafeCall( nppiTranspose_8u_C1R(src.ptr<Npp8u>(), src.step, dst.ptr<Npp8u>(), dst.step, sz) );
273 274
}

275 276 277
////////////////////////////////////////////////////////////////////////
// absdiff

278 279
void cv::gpu::absdiff(const GpuMat& src1, const GpuMat& src2, GpuMat& dst)
{
280
    CV_DbgAssert(src1.size() == src2.size() && src1.type() == src2.type());
281

282
    CV_Assert(src1.type() == CV_8UC1 || src1.type() == CV_8UC4 || src1.type() == CV_32SC1 || src1.type() == CV_32FC1);
283

284 285
    dst.create( src1.size(), src1.type() );

286 287 288
    NppiSize sz;
    sz.width  = src1.cols;
    sz.height = src1.rows;
289

290
    switch (src1.type())
291
    {
292
    case CV_8UC1:
293 294
        nppSafeCall( nppiAbsDiff_8u_C1R(src1.ptr<Npp8u>(), src1.step,
            src2.ptr<Npp8u>(), src2.step,
295
            dst.ptr<Npp8u>(), dst.step, sz) );
296 297
        break;
    case CV_8UC4:
298 299
        nppSafeCall( nppiAbsDiff_8u_C4R(src1.ptr<Npp8u>(), src1.step,
            src2.ptr<Npp8u>(), src2.step,
300 301 302 303 304 305 306 307
            dst.ptr<Npp8u>(), dst.step, sz) );
        break;
    case CV_32SC1:
        nppSafeCall( nppiAbsDiff_32s_C1R(src1.ptr<Npp32s>(), src1.step,
            src2.ptr<Npp32s>(), src2.step,
            dst.ptr<Npp32s>(), dst.step, sz) );
        break;
    case CV_32FC1:
308 309 310
        nppSafeCall( nppiAbsDiff_32f_C1R(src1.ptr<Npp32f>(), src1.step,
            src2.ptr<Npp32f>(), src2.step,
            dst.ptr<Npp32f>(), dst.step, sz) );
311 312 313
        break;
    default:
        CV_Assert(!"Unsupported source type");
314 315 316
    }
}

317 318
void cv::gpu::absdiff(const GpuMat& src, const Scalar& s, GpuMat& dst)
{
319
    CV_Assert(src.type() == CV_32FC1);
320 321 322 323 324 325 326 327 328 329

    dst.create( src.size(), src.type() );

    NppiSize sz;
    sz.width  = src.cols;
    sz.height = src.rows;

    nppSafeCall( nppiAbsDiffC_32f_C1R(src.ptr<Npp32f>(), src.step, dst.ptr<Npp32f>(), dst.step, sz, (Npp32f)s[0]) );
}

330 331
////////////////////////////////////////////////////////////////////////
// compare
332

333
namespace cv { namespace gpu { namespace mathfunc
334
{
335
    void compare_ne_8uc4(const DevMem2D& src1, const DevMem2D& src2, const DevMem2D& dst);
336 337 338
    void compare_ne_32f(const DevMem2D& src1, const DevMem2D& src2, const DevMem2D& dst);
}}}

339
void cv::gpu::compare(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, int cmpop)
340 341 342
{
    CV_DbgAssert(src1.size() == src2.size() && src1.type() == src2.type());

343
    CV_Assert(src1.type() == CV_8UC4 || src1.type() == CV_32FC1);
344 345 346 347

    dst.create( src1.size(), CV_8UC1 );

    static const NppCmpOp nppCmpOp[] = { NPP_CMP_EQ, NPP_CMP_GREATER, NPP_CMP_GREATER_EQ, NPP_CMP_LESS, NPP_CMP_LESS_EQ };
348 349

    NppiSize sz;
350
    sz.width  = src1.cols;
351 352
    sz.height = src1.rows;

353
    if (src1.type() == CV_8UC4)
354
    {
355 356
        if (cmpop != CMP_NE)
        {
357 358
            nppSafeCall( nppiCompare_8u_C4R(src1.ptr<Npp8u>(), src1.step,
                src2.ptr<Npp8u>(), src2.step,
359 360 361 362
                dst.ptr<Npp8u>(), dst.step, sz, nppCmpOp[cmpop]) );
        }
        else
        {
363
            mathfunc::compare_ne_8uc4(src1, src2, dst);
364
        }
365
    }
366
    else
367
    {
368 369 370 371 372 373 374 375
        if (cmpop != CMP_NE)
        {
            nppSafeCall( nppiCompare_32f_C1R(src1.ptr<Npp32f>(), src1.step,
                src2.ptr<Npp32f>(), src2.step,
                dst.ptr<Npp8u>(), dst.step, sz, nppCmpOp[cmpop]) );
        }
        else
        {
376
            mathfunc::compare_ne_32f(src1, src2, dst);
377
        }
378 379 380
    }
}

381 382 383
////////////////////////////////////////////////////////////////////////
// meanStdDev

384
void cv::gpu::meanStdDev(const GpuMat& src, Scalar& mean, Scalar& stddev)
385 386 387 388 389 390 391
{
    CV_Assert(src.type() == CV_8UC1);

    NppiSize sz;
    sz.width  = src.cols;
    sz.height = src.rows;

392
    nppSafeCall( nppiMean_StdDev_8u_C1R(src.ptr<Npp8u>(), src.step, sz, mean.val, stddev.val) );
393 394
}

395 396 397
////////////////////////////////////////////////////////////////////////
// norm

398
double cv::gpu::norm(const GpuMat& src1, int normType)
399 400 401 402 403 404 405 406
{
    return norm(src1, GpuMat(src1.size(), src1.type(), Scalar::all(0.0)), normType);
}

double cv::gpu::norm(const GpuMat& src1, const GpuMat& src2, int normType)
{
    CV_DbgAssert(src1.size() == src2.size() && src1.type() == src2.type());

407 408
    CV_Assert(src1.type() == CV_8UC1);
    CV_Assert(normType == NORM_INF || normType == NORM_L1 || normType == NORM_L2);
409

410
    typedef NppStatus (*npp_norm_diff_func_t)(const Npp8u* pSrc1, int nSrcStep1, const Npp8u* pSrc2, int nSrcStep2,
411 412 413 414 415 416 417 418 419
        NppiSize oSizeROI, Npp64f* pRetVal);

    static const npp_norm_diff_func_t npp_norm_diff_func[] = {nppiNormDiff_Inf_8u_C1R, nppiNormDiff_L1_8u_C1R, nppiNormDiff_L2_8u_C1R};

    NppiSize sz;
    sz.width  = src1.cols;
    sz.height = src1.rows;

    int funcIdx = normType >> 1;
420
    double retVal;
421

422 423
    nppSafeCall( npp_norm_diff_func[funcIdx](src1.ptr<Npp8u>(), src1.step,
        src2.ptr<Npp8u>(), src2.step,
424
        sz, &retVal) );
425

426
    return retVal;
427 428
}

429 430 431
////////////////////////////////////////////////////////////////////////
// flip

432 433 434 435 436 437 438 439 440 441
void cv::gpu::flip(const GpuMat& src, GpuMat& dst, int flipCode)
{
    CV_Assert(src.type() == CV_8UC1 || src.type() == CV_8UC4);

    dst.create( src.size(), src.type() );

    NppiSize sz;
    sz.width  = src.cols;
    sz.height = src.rows;

442
    if (src.type() == CV_8UC1)
443
    {
444 445
        nppSafeCall( nppiMirror_8u_C1R(src.ptr<Npp8u>(), src.step,
            dst.ptr<Npp8u>(), dst.step, sz,
V
Vladislav Vinogradov 已提交
446
            (flipCode == 0 ? NPP_HORIZONTAL_AXIS : (flipCode > 0 ? NPP_VERTICAL_AXIS : NPP_BOTH_AXIS))) );
447 448 449
    }
    else
    {
450 451
        nppSafeCall( nppiMirror_8u_C4R(src.ptr<Npp8u>(), src.step,
            dst.ptr<Npp8u>(), dst.step, sz,
V
Vladislav Vinogradov 已提交
452
            (flipCode == 0 ? NPP_HORIZONTAL_AXIS : (flipCode > 0 ? NPP_VERTICAL_AXIS : NPP_BOTH_AXIS))) );
453 454 455
    }
}

456 457
////////////////////////////////////////////////////////////////////////
// sum
458 459 460

Scalar cv::gpu::sum(const GpuMat& src)
{
461 462
    CV_Assert(!"disabled until fix crash");

463
    CV_Assert(src.type() == CV_8UC1 || src.type() == CV_8UC4);
464 465 466 467 468

    NppiSize sz;
    sz.width  = src.cols;
    sz.height = src.rows;

469 470
    Scalar res;

471
    int bufsz;
472

473
    if (src.type() == CV_8UC1)
474
    {
475 476
        nppiReductionGetBufferHostSize_8u_C1R(sz, &bufsz);
        GpuMat buf(1, bufsz, CV_32S);
477

478
        nppSafeCall( nppiSum_8u_C1R(src.ptr<Npp8u>(), src.step, sz, buf.ptr<Npp32s>(), res.val) );
479 480
    }
    else
481
    {
482 483
        nppiReductionGetBufferHostSize_8u_C4R(sz, &bufsz);
        GpuMat buf(1, bufsz, CV_32S);
484

485
        nppSafeCall( nppiSum_8u_C4R(src.ptr<Npp8u>(), src.step, sz, buf.ptr<Npp32s>(), res.val) );
486
    }
487 488

    return res;
489 490
}

491 492 493
////////////////////////////////////////////////////////////////////////
// minMax

494 495
namespace cv { namespace gpu { namespace mathfunc { namespace minmax {

496
    void get_buf_size_required(int elem_size, int& cols, int& rows);
497
    
498
    template <typename T> 
499
    void min_max_caller(const DevMem2D src, double* minval, double* maxval, PtrStep buf);
500 501

    template <typename T> 
502
    void min_max_caller_2steps(const DevMem2D src, double* minval, double* maxval, PtrStep buf);
503 504

}}}}
505

506
void cv::gpu::minMax(const GpuMat& src, double* minVal, double* maxVal)
507 508 509 510 511 512 513
{
    GpuMat buf;
    minMax(src, minVal, maxVal, buf);
}


void cv::gpu::minMax(const GpuMat& src, double* minVal, double* maxVal, GpuMat& buf)
514
{
515
    using namespace mathfunc::minmax;
516

517
    double maxVal_;
518 519 520
    if (!maxVal) maxVal = &maxVal_;

    GpuMat src_ = src.reshape(1);
521 522 523 524
    
    Size bufSize;
    get_buf_size_required(src.elemSize(), bufSize.width, bufSize.height);
    buf.create(bufSize, CV_8U);
525 526 527

    int major, minor;
    getComputeCapability(getDevice(), major, minor);
528
 
529
    if (major >= 1 && minor >= 1)
530
    {
531 532
        switch (src_.type())
        {
533 534 535 536 537 538 539
        case CV_8U: min_max_caller<unsigned char>(src_, minVal, maxVal, buf); break;
        case CV_8S: min_max_caller<signed char>(src_, minVal, maxVal, buf); break;
        case CV_16U: min_max_caller<unsigned short>(src_, minVal, maxVal, buf); break;
        case CV_16S: min_max_caller<signed short>(src_, minVal, maxVal, buf); break;
        case CV_32S: min_max_caller<int>(src_, minVal, maxVal, buf); break;
        case CV_32F: min_max_caller<float>(src_, minVal, maxVal, buf); break;
        case CV_64F: min_max_caller<double>(src_, minVal, maxVal, buf); break;
540 541 542 543 544 545 546
        default: CV_Error(CV_StsBadArg, "Unsupported type");
        }
    }
    else
    {
        switch (src_.type())
        {
547 548 549 550 551 552
        case CV_8U: min_max_caller_2steps<unsigned char>(src_, minVal, maxVal, buf); break;
        case CV_8S: min_max_caller_2steps<signed char>(src_, minVal, maxVal, buf); break;
        case CV_16U: min_max_caller_2steps<unsigned short>(src_, minVal, maxVal, buf); break;
        case CV_16S: min_max_caller_2steps<signed short>(src_, minVal, maxVal, buf); break;
        case CV_32S: min_max_caller_2steps<int>(src_, minVal, maxVal, buf); break;
        case CV_32F: min_max_caller_2steps<float>(src_, minVal, maxVal, buf); break;
553 554
        default: CV_Error(CV_StsBadArg, "Unsupported type");
        }
555
    }
556 557
}

558 559 560 561

////////////////////////////////////////////////////////////////////////
// minMaxLoc

562 563
namespace cv { namespace gpu { namespace mathfunc { namespace minmaxloc {

564
    template <typename T> 
565 566 567 568
    void min_max_loc_caller(const DevMem2D src, double* minval, double* maxval, 
                            int* minlocx, int* minlocy, int* maxlocx, int* maxlocy);

}}}}
569 570 571

void cv::gpu::minMaxLoc(const GpuMat& src, double* minVal, double* maxVal, Point* minLoc, Point* maxLoc)
{
572 573
    using namespace mathfunc::minmaxloc;

574 575 576 577 578 579 580 581 582 583 584 585 586 587
    CV_Assert(src.channels() == 1);

    double maxVal_;
    if (!maxVal) maxVal = &maxVal_;

    cv::Point minLoc_;
    if (!minLoc) minLoc = &minLoc_;

    cv::Point maxLoc_;
    if (!maxLoc) maxLoc = &maxLoc_;
  
    switch (src.type())
    {
    case CV_8U:
588
        min_max_loc_caller<unsigned char>(src, minVal, maxVal, &minLoc->x, &minLoc->y, &maxLoc->x, &maxLoc->y);
589 590
        break;
    case CV_8S:
591
        min_max_loc_caller<signed char>(src, minVal, maxVal, &minLoc->x, &minLoc->y, &maxLoc->x, &maxLoc->y);
592 593
        break;
    case CV_16U:
594
        min_max_loc_caller<unsigned short>(src, minVal, maxVal, &minLoc->x, &minLoc->y, &maxLoc->x, &maxLoc->y);
595 596
        break;
    case CV_16S:
597
        min_max_loc_caller<signed short>(src, minVal, maxVal, &minLoc->x, &minLoc->y, &maxLoc->x, &maxLoc->y);
598 599
        break;
    case CV_32S:
600
        min_max_loc_caller<int>(src, minVal, maxVal, &minLoc->x, &minLoc->y, &maxLoc->x, &maxLoc->y);
601 602
        break;
    case CV_32F:
603
        min_max_loc_caller<float>(src, minVal, maxVal, &minLoc->x, &minLoc->y, &maxLoc->x, &maxLoc->y);
604 605
        break;
    case CV_64F:
606
        min_max_loc_caller<double>(src, minVal, maxVal, &minLoc->x, &minLoc->y, &maxLoc->x, &maxLoc->y);
607 608 609 610 611 612
        break;
    default:
        CV_Error(CV_StsBadArg, "Unsupported type");
    }
}

613 614
////////////////////////////////////////////////////////////////////////
// LUT
615

616 617 618
void cv::gpu::LUT(const GpuMat& src, const Mat& lut, GpuMat& dst)
{
    class LevelsInit
619
    {
620 621
    public:
        Npp32s pLevels[256];
622 623
        const Npp32s* pLevels3[3];
        int nValues3[3];
624

625
        LevelsInit()
626 627
        {
            nValues3[0] = nValues3[1] = nValues3[2] = 256;
628 629
            for (int i = 0; i < 256; ++i)
                pLevels[i] = i;
630
            pLevels3[0] = pLevels3[1] = pLevels3[2] = pLevels;
631
        }
632 633
    };
    static LevelsInit lvls;
634

635
    int cn = src.channels();
636

637 638
    CV_Assert(src.type() == CV_8UC1 || src.type() == CV_8UC3);
    CV_Assert(lut.depth() == CV_8U && (lut.channels() == 1 || lut.channels() == cn) && lut.rows * lut.cols == 256 && lut.isContinuous());
639

640
    dst.create(src.size(), CV_MAKETYPE(lut.depth(), cn));
641

642 643 644
    NppiSize sz;
    sz.height = src.rows;
    sz.width = src.cols;
645

646 647
    Mat nppLut;
    lut.convertTo(nppLut, CV_32S);
648

649 650
    if (src.type() == CV_8UC1)
    {
651
        nppSafeCall( nppiLUT_Linear_8u_C1R(src.ptr<Npp8u>(), src.step, dst.ptr<Npp8u>(), dst.step, sz,
652 653 654 655 656 657 658 659 660 661 662 663
            nppLut.ptr<Npp32s>(), lvls.pLevels, 256) );
    }
    else
    {
        Mat nppLut3[3];
        const Npp32s* pValues3[3];
        if (nppLut.channels() == 1)
            pValues3[0] = pValues3[1] = pValues3[2] = nppLut.ptr<Npp32s>();
        else
        {
            cv::split(nppLut, nppLut3);
            pValues3[0] = nppLut3[0].ptr<Npp32s>();
664
            pValues3[1] = nppLut3[1].ptr<Npp32s>();
665 666
            pValues3[2] = nppLut3[2].ptr<Npp32s>();
        }
667
        nppSafeCall( nppiLUT_Linear_8u_C3R(src.ptr<Npp8u>(), src.step, dst.ptr<Npp8u>(), dst.step, sz,
668 669
            pValues3, lvls.pLevels3, lvls.nValues3) );
    }
670 671
}

672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704
////////////////////////////////////////////////////////////////////////
// exp

void cv::gpu::exp(const GpuMat& src, GpuMat& dst)
{
    CV_Assert(src.type() == CV_32FC1);

    dst.create(src.size(), src.type());

    NppiSize sz;
    sz.width = src.cols;
    sz.height = src.rows;

    nppSafeCall( nppiExp_32f_C1R(src.ptr<Npp32f>(), src.step, dst.ptr<Npp32f>(), dst.step, sz) );
}

////////////////////////////////////////////////////////////////////////
// log

void cv::gpu::log(const GpuMat& src, GpuMat& dst)
{
    CV_Assert(src.type() == CV_32FC1);

    dst.create(src.size(), src.type());

    NppiSize sz;
    sz.width = src.cols;
    sz.height = src.rows;

    nppSafeCall( nppiLn_32f_C1R(src.ptr<Npp32f>(), src.step, dst.ptr<Npp32f>(), dst.step, sz) );
}

////////////////////////////////////////////////////////////////////////
705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723
// NPP magnitide

namespace
{
    typedef NppStatus (*nppMagnitude_t)(const Npp32fc* pSrc, int nSrcStep, Npp32f* pDst, int nDstStep, NppiSize oSizeROI);

    inline void npp_magnitude(const GpuMat& src, GpuMat& dst, nppMagnitude_t func)
    {
        CV_Assert(src.type() == CV_32FC2);

        dst.create(src.size(), CV_32FC1);

        NppiSize sz;
        sz.width = src.cols;
        sz.height = src.rows;

        nppSafeCall( func(src.ptr<Npp32fc>(), src.step, dst.ptr<Npp32f>(), dst.step, sz) );
    }
}
724

725 726
void cv::gpu::magnitude(const GpuMat& src, GpuMat& dst)
{
727 728
    ::npp_magnitude(src, dst, nppiMagnitude_32fc32f_C1R);
}
729

730 731 732 733
void cv::gpu::magnitudeSqr(const GpuMat& src, GpuMat& dst)
{
    ::npp_magnitude(src, dst, nppiMagnitudeSqr_32fc32f_C1R);
}
734

735 736
////////////////////////////////////////////////////////////////////////
// Polar <-> Cart
737

738
namespace cv { namespace gpu { namespace mathfunc
739 740 741 742 743 744 745
{
    void cartToPolar_gpu(const DevMem2Df& x, const DevMem2Df& y, const DevMem2Df& mag, bool magSqr, const DevMem2Df& angle, bool angleInDegrees, cudaStream_t stream);
    void polarToCart_gpu(const DevMem2Df& mag, const DevMem2Df& angle, const DevMem2Df& x, const DevMem2Df& y, bool angleInDegrees, cudaStream_t stream);
}}}

namespace
{
746
    inline void cartToPolar_caller(const GpuMat& x, const GpuMat& y, GpuMat* mag, bool magSqr, GpuMat* angle, bool angleInDegrees, cudaStream_t stream)
747 748 749 750
    {
        CV_DbgAssert(x.size() == y.size() && x.type() == y.type());
        CV_Assert(x.depth() == CV_32F);

751 752 753 754
        if (mag)
            mag->create(x.size(), x.type());
        if (angle)
            angle->create(x.size(), x.type());
755 756 757

        GpuMat x1cn = x.reshape(1);
        GpuMat y1cn = y.reshape(1);
758 759
        GpuMat mag1cn = mag ? mag->reshape(1) : GpuMat();
        GpuMat angle1cn = angle ? angle->reshape(1) : GpuMat();
760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778

        mathfunc::cartToPolar_gpu(x1cn, y1cn, mag1cn, magSqr, angle1cn, angleInDegrees, stream);
    }

    inline void polarToCart_caller(const GpuMat& mag, const GpuMat& angle, GpuMat& x, GpuMat& y, bool angleInDegrees, cudaStream_t stream)
    {
        CV_DbgAssert((mag.empty() || mag.size() == angle.size()) && mag.type() == angle.type());
        CV_Assert(mag.depth() == CV_32F);

        x.create(mag.size(), mag.type());
        y.create(mag.size(), mag.type());

        GpuMat mag1cn = mag.reshape(1);
        GpuMat angle1cn = angle.reshape(1);
        GpuMat x1cn = x.reshape(1);
        GpuMat y1cn = y.reshape(1);

        mathfunc::polarToCart_gpu(mag1cn, angle1cn, x1cn, y1cn, angleInDegrees, stream);
    }
779 780
}

781
void cv::gpu::magnitude(const GpuMat& x, const GpuMat& y, GpuMat& dst)
782
{
783
    ::cartToPolar_caller(x, y, &dst, false, 0, false, 0);
784
}
785

786 787
void cv::gpu::magnitude(const GpuMat& x, const GpuMat& y, GpuMat& dst, const Stream& stream)
{
788
    ::cartToPolar_caller(x, y, &dst, false, 0, false, StreamAccessor::getStream(stream));
789
}
790

791 792
void cv::gpu::magnitudeSqr(const GpuMat& x, const GpuMat& y, GpuMat& dst)
{
793
    ::cartToPolar_caller(x, y, &dst, true, 0, false, 0);
794 795
}

796
void cv::gpu::magnitudeSqr(const GpuMat& x, const GpuMat& y, GpuMat& dst, const Stream& stream)
797
{
798
    ::cartToPolar_caller(x, y, &dst, true, 0, false, StreamAccessor::getStream(stream));
799
}
800

801 802
void cv::gpu::phase(const GpuMat& x, const GpuMat& y, GpuMat& angle, bool angleInDegrees)
{
803
    ::cartToPolar_caller(x, y, 0, false, &angle, angleInDegrees, 0);
804
}
805

806
void cv::gpu::phase(const GpuMat& x, const GpuMat& y, GpuMat& angle, bool angleInDegrees, const Stream& stream)
807
{
808
    ::cartToPolar_caller(x, y, 0, false, &angle, angleInDegrees, StreamAccessor::getStream(stream));
809
}
810

811 812
void cv::gpu::cartToPolar(const GpuMat& x, const GpuMat& y, GpuMat& mag, GpuMat& angle, bool angleInDegrees)
{
813
    ::cartToPolar_caller(x, y, &mag, false, &angle, angleInDegrees, 0);
814 815
}

816
void cv::gpu::cartToPolar(const GpuMat& x, const GpuMat& y, GpuMat& mag, GpuMat& angle, bool angleInDegrees, const Stream& stream)
817
{
818
    ::cartToPolar_caller(x, y, &mag, false, &angle, angleInDegrees, StreamAccessor::getStream(stream));
819
}
820

821 822 823 824
void cv::gpu::polarToCart(const GpuMat& magnitude, const GpuMat& angle, GpuMat& x, GpuMat& y, bool angleInDegrees)
{
    ::polarToCart_caller(magnitude, angle, x, y, angleInDegrees, 0);
}
825

826 827 828
void cv::gpu::polarToCart(const GpuMat& magnitude, const GpuMat& angle, GpuMat& x, GpuMat& y, bool angleInDegrees, const Stream& stream)
{
    ::polarToCart_caller(magnitude, angle, x, y, angleInDegrees, StreamAccessor::getStream(stream));
829 830
}

831 832 833
//////////////////////////////////////////////////////////////////////////////
// Per-element bit-wise logical matrix operations

834
namespace cv { namespace gpu { namespace mathfunc
835
{
836 837 838 839 840 841 842 843 844 845 846 847
    void bitwise_not_caller(int rows, int cols, const PtrStep src, int elemSize, PtrStep dst, cudaStream_t stream);
    void bitwise_not_caller(int rows, int cols, const PtrStep src, int elemSize, PtrStep dst, const PtrStep mask, cudaStream_t stream);
    void bitwise_or_caller(int rows, int cols, const PtrStep src1, const PtrStep src2, int elemSize, PtrStep dst, cudaStream_t stream);
    void bitwise_or_caller(int rows, int cols, const PtrStep src1, const PtrStep src2, int elemSize, PtrStep dst, const PtrStep mask, cudaStream_t stream);
    void bitwise_and_caller(int rows, int cols, const PtrStep src1, const PtrStep src2, int elemSize, PtrStep dst, cudaStream_t stream);
    void bitwise_and_caller(int rows, int cols, const PtrStep src1, const PtrStep src2, int elemSize, PtrStep dst, const PtrStep mask, cudaStream_t stream);
    void bitwise_xor_caller(int rows, int cols, const PtrStep src1, const PtrStep src2, int elemSize, PtrStep dst, cudaStream_t stream);
    void bitwise_xor_caller(int rows, int cols, const PtrStep src1, const PtrStep src2, int elemSize, PtrStep dst, const PtrStep mask, cudaStream_t stream);


    template <int opid, typename Mask>
    void bitwise_bin_op(int rows, int cols, const PtrStep src1, const PtrStep src2, PtrStep dst, int elem_size, Mask mask, cudaStream_t stream);
848 849
}}}

850
namespace
851 852 853 854
{
    void bitwise_not_caller(const GpuMat& src, GpuMat& dst, cudaStream_t stream)
    {
        dst.create(src.size(), src.type());
855 856 857 858 859 860 861 862
        mathfunc::bitwise_not_caller(src.rows, src.cols, src, src.elemSize(), dst, stream);
    }

    void bitwise_not_caller(const GpuMat& src, GpuMat& dst, const GpuMat& mask, cudaStream_t stream)
    {
        CV_Assert(mask.type() == CV_8U && mask.size() == src.size());
        dst.create(src.size(), src.type());
        mathfunc::bitwise_not_caller(src.rows, src.cols, src, src.elemSize(), dst, mask, stream);
863 864 865 866
    }

    void bitwise_or_caller(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, cudaStream_t stream)
    {
867 868 869 870
        CV_Assert(src1.size() == src2.size() && src1.type() == src2.type());
        dst.create(src1.size(), src1.type());
        mathfunc::bitwise_or_caller(dst.rows, dst.cols, src1, src2, dst.elemSize(), dst, stream);
    }
871

872 873 874 875
    void bitwise_or_caller(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, const GpuMat& mask, cudaStream_t stream)
    {
        CV_Assert(src1.size() == src2.size() && src1.type() == src2.type());
        CV_Assert(mask.type() == CV_8U && mask.size() == src1.size());
876
        dst.create(src1.size(), src1.type());
877
        mathfunc::bitwise_or_caller(dst.rows, dst.cols, src1, src2, dst.elemSize(), dst, mask, stream);
878 879 880 881
    }

    void bitwise_and_caller(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, cudaStream_t stream)
    {
882 883 884 885
        CV_Assert(src1.size() == src2.size() && src1.type() == src2.type());
        dst.create(src1.size(), src1.type());
        mathfunc::bitwise_and_caller(dst.rows, dst.cols, src1, src2, dst.elemSize(), dst, stream);
    }
886

887 888 889 890
    void bitwise_and_caller(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, const GpuMat& mask, cudaStream_t stream)
    {
        CV_Assert(src1.size() == src2.size() && src1.type() == src2.type());
        CV_Assert(mask.type() == CV_8U && mask.size() == src1.size());
891
        dst.create(src1.size(), src1.type());
892
        mathfunc::bitwise_and_caller(dst.rows, dst.cols, src1, src2, dst.elemSize(), dst, mask, stream);
893 894 895 896 897 898
    }

    void bitwise_xor_caller(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, cudaStream_t stream)
    {
        CV_Assert(src1.size() == src2.size());
        CV_Assert(src1.type() == src2.type());
899 900 901
        dst.create(src1.size(), src1.type());
        mathfunc::bitwise_xor_caller(dst.rows, dst.cols, src1, src2, dst.elemSize(), dst, stream);
    }
902

903 904 905 906
    void bitwise_xor_caller(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, const GpuMat& mask, cudaStream_t stream)
    {
        CV_Assert(src1.size() == src2.size() && src1.type() == src2.type());
        CV_Assert(mask.type() == CV_8U && mask.size() == src1.size());
907
        dst.create(src1.size(), src1.type());
908
        mathfunc::bitwise_xor_caller(dst.rows, dst.cols, src1, src2, dst.elemSize(), dst, mask, stream);
909 910 911
    }
}

912
void cv::gpu::bitwise_not(const GpuMat& src, GpuMat& dst, const GpuMat& mask)
913
{
914
    if (mask.empty())
915 916 917
        ::bitwise_not_caller(src, dst, 0);
    else
        ::bitwise_not_caller(src, dst, mask, 0);
918 919
}

920
void cv::gpu::bitwise_not(const GpuMat& src, GpuMat& dst, const GpuMat& mask, const Stream& stream)
921
{
922 923 924 925
    if (mask.empty())
        ::bitwise_not_caller(src, dst, StreamAccessor::getStream(stream));
    else
        ::bitwise_not_caller(src, dst, mask, StreamAccessor::getStream(stream));
926 927
}

928
void cv::gpu::bitwise_or(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, const GpuMat& mask)
929
{
930 931 932 933
    if (mask.empty())
        ::bitwise_or_caller(src1, src2, dst, 0);
    else
        ::bitwise_or_caller(src1, src2, dst, mask, 0);
934 935
}

936
void cv::gpu::bitwise_or(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, const GpuMat& mask, const Stream& stream)
937
{
938 939 940 941
    if (mask.empty())
        ::bitwise_or_caller(src1, src2, dst, StreamAccessor::getStream(stream));
    else
        ::bitwise_or_caller(src1, src2, dst, mask, StreamAccessor::getStream(stream));
942 943
}

944
void cv::gpu::bitwise_and(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, const GpuMat& mask)
945
{
946 947 948 949
    if (mask.empty())
        ::bitwise_and_caller(src1, src2, dst, 0);
    else
        ::bitwise_and_caller(src1, src2, dst, mask, 0);
950 951
}

952
void cv::gpu::bitwise_and(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, const GpuMat& mask, const Stream& stream)
953
{
954 955 956 957
    if (mask.empty())
        ::bitwise_and_caller(src1, src2, dst, StreamAccessor::getStream(stream));
    else
        ::bitwise_and_caller(src1, src2, dst, mask, StreamAccessor::getStream(stream));
958 959
}

960
void cv::gpu::bitwise_xor(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, const GpuMat& mask)
961
{
962 963 964 965
    if (mask.empty())
        ::bitwise_xor_caller(src1, src2, dst, 0);
    else
        ::bitwise_xor_caller(src1, src2, dst, mask, 0);
966 967
}

968
void cv::gpu::bitwise_xor(const GpuMat& src1, const GpuMat& src2, GpuMat& dst, const GpuMat& mask, const Stream& stream)
969
{
970 971 972 973 974
    if (mask.empty())
        ::bitwise_xor_caller(src1, src2, dst, StreamAccessor::getStream(stream));
    else
        ::bitwise_xor_caller(src1, src2, dst, mask, StreamAccessor::getStream(stream));

975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005
}

cv::gpu::GpuMat cv::gpu::operator ~ (const GpuMat& src)
{
    GpuMat dst;
    bitwise_not(src, dst);
    return dst;
}

cv::gpu::GpuMat cv::gpu::operator | (const GpuMat& src1, const GpuMat& src2)
{
    GpuMat dst;
    bitwise_or(src1, src2, dst);
    return dst;
}

cv::gpu::GpuMat cv::gpu::operator & (const GpuMat& src1, const GpuMat& src2)
{
    GpuMat dst;
    bitwise_and(src1, src2, dst);
    return dst;
}

cv::gpu::GpuMat cv::gpu::operator ^ (const GpuMat& src1, const GpuMat& src2)
{
    GpuMat dst;
    bitwise_xor(src1, src2, dst);
    return dst;
}


1006
#endif /* !defined (HAVE_CUDA) */