Home | History | Annotate | Download | only in test
      1 /*M///////////////////////////////////////////////////////////////////////////////////////
      2 //
      3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
      4 //
      5 //  By downloading, copying, installing or using the software you agree to this license.
      6 //  If you do not agree to this license, do not download, install,
      7 //  copy or use the software.
      8 //
      9 //
     10 //                           License Agreement
     11 //                For Open Source Computer Vision Library
     12 //
     13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
     14 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
     15 // Third party copyrights are property of their respective owners.
     16 //
     17 // Redistribution and use in source and binary forms, with or without modification,
     18 // are permitted provided that the following conditions are met:
     19 //
     20 //   * Redistribution's of source code must retain the above copyright notice,
     21 //     this list of conditions and the following disclaimer.
     22 //
     23 //   * Redistribution's in binary form must reproduce the above copyright notice,
     24 //     this list of conditions and the following disclaimer in the documentation
     25 //     and/or other materials provided with the distribution.
     26 //
     27 //   * The name of the copyright holders may not be used to endorse or promote products
     28 //     derived from this software without specific prior written permission.
     29 //
     30 // This software is provided by the copyright holders and contributors "as is" and
     31 // any express or implied warranties, including, but not limited to, the implied
     32 // warranties of merchantability and fitness for a particular purpose are disclaimed.
     33 // In no event shall the Intel Corporation or contributors be liable for any direct,
     34 // indirect, incidental, special, exemplary, or consequential damages
     35 // (including, but not limited to, procurement of substitute goods or services;
     36 // loss of use, data, or profits; or business interruption) however caused
     37 // and on any theory of liability, whether in contract, strict liability,
     38 // or tort (including negligence or otherwise) arising in any way out of
     39 // the use of this software, even if advised of the possibility of such damage.
     40 //
     41 //M*/
     42 
     43 #include "test_precomp.hpp"
     44 
     45 #ifdef HAVE_CUDA
     46 
     47 using namespace cvtest;
     48 
     49 ////////////////////////////////////////////////////////////////////////////////
     50 // Norm
     51 
     52 PARAM_TEST_CASE(Norm, cv::cuda::DeviceInfo, cv::Size, MatDepth, NormCode, UseRoi)
     53 {
     54     cv::cuda::DeviceInfo devInfo;
     55     cv::Size size;
     56     int depth;
     57     int normCode;
     58     bool useRoi;
     59 
     60     virtual void SetUp()
     61     {
     62         devInfo = GET_PARAM(0);
     63         size = GET_PARAM(1);
     64         depth = GET_PARAM(2);
     65         normCode = GET_PARAM(3);
     66         useRoi = GET_PARAM(4);
     67 
     68         cv::cuda::setDevice(devInfo.deviceID());
     69     }
     70 };
     71 
     72 CUDA_TEST_P(Norm, Accuracy)
     73 {
     74     cv::Mat src = randomMat(size, depth);
     75     cv::Mat mask = randomMat(size, CV_8UC1, 0, 2);
     76 
     77     double val = cv::cuda::norm(loadMat(src, useRoi), normCode, loadMat(mask, useRoi));
     78 
     79     double val_gold = cv::norm(src, normCode, mask);
     80 
     81     EXPECT_NEAR(val_gold, val, depth < CV_32F ? 0.0 : 1.0);
     82 }
     83 
     84 CUDA_TEST_P(Norm, Async)
     85 {
     86     cv::Mat src = randomMat(size, depth);
     87     cv::Mat mask = randomMat(size, CV_8UC1, 0, 2);
     88 
     89     cv::cuda::Stream stream;
     90 
     91     cv::cuda::HostMem dst;
     92     cv::cuda::calcNorm(loadMat(src, useRoi), dst, normCode, loadMat(mask, useRoi), stream);
     93 
     94     stream.waitForCompletion();
     95 
     96     double val;
     97     dst.createMatHeader().convertTo(cv::Mat(1, 1, CV_64FC1, &val), CV_64F);
     98 
     99     double val_gold = cv::norm(src, normCode, mask);
    100 
    101     EXPECT_NEAR(val_gold, val, depth < CV_32F ? 0.0 : 1.0);
    102 }
    103 
    104 INSTANTIATE_TEST_CASE_P(CUDA_Arithm, Norm, testing::Combine(
    105     ALL_DEVICES,
    106     DIFFERENT_SIZES,
    107     testing::Values(MatDepth(CV_8U),
    108                     MatDepth(CV_8S),
    109                     MatDepth(CV_16U),
    110                     MatDepth(CV_16S),
    111                     MatDepth(CV_32S),
    112                     MatDepth(CV_32F)),
    113     testing::Values(NormCode(cv::NORM_L1), NormCode(cv::NORM_L2), NormCode(cv::NORM_INF)),
    114     WHOLE_SUBMAT));
    115 
    116 ////////////////////////////////////////////////////////////////////////////////
    117 // normDiff
    118 
    119 PARAM_TEST_CASE(NormDiff, cv::cuda::DeviceInfo, cv::Size, NormCode, UseRoi)
    120 {
    121     cv::cuda::DeviceInfo devInfo;
    122     cv::Size size;
    123     int normCode;
    124     bool useRoi;
    125 
    126     virtual void SetUp()
    127     {
    128         devInfo = GET_PARAM(0);
    129         size = GET_PARAM(1);
    130         normCode = GET_PARAM(2);
    131         useRoi = GET_PARAM(3);
    132 
    133         cv::cuda::setDevice(devInfo.deviceID());
    134     }
    135 };
    136 
    137 CUDA_TEST_P(NormDiff, Accuracy)
    138 {
    139     cv::Mat src1 = randomMat(size, CV_8UC1);
    140     cv::Mat src2 = randomMat(size, CV_8UC1);
    141 
    142     double val = cv::cuda::norm(loadMat(src1, useRoi), loadMat(src2, useRoi), normCode);
    143 
    144     double val_gold = cv::norm(src1, src2, normCode);
    145 
    146     EXPECT_NEAR(val_gold, val, 0.0);
    147 }
    148 
    149 CUDA_TEST_P(NormDiff, Async)
    150 {
    151     cv::Mat src1 = randomMat(size, CV_8UC1);
    152     cv::Mat src2 = randomMat(size, CV_8UC1);
    153 
    154     cv::cuda::Stream stream;
    155 
    156     cv::cuda::HostMem dst;
    157     cv::cuda::calcNormDiff(loadMat(src1, useRoi), loadMat(src2, useRoi), dst, normCode, stream);
    158 
    159     stream.waitForCompletion();
    160 
    161     double val;
    162     const cv::Mat val_mat(1, 1, CV_64FC1, &val);
    163     dst.createMatHeader().convertTo(val_mat, CV_64F);
    164 
    165     double val_gold = cv::norm(src1, src2, normCode);
    166 
    167     EXPECT_NEAR(val_gold, val, 0.0);
    168 }
    169 
    170 INSTANTIATE_TEST_CASE_P(CUDA_Arithm, NormDiff, testing::Combine(
    171     ALL_DEVICES,
    172     DIFFERENT_SIZES,
    173     testing::Values(NormCode(cv::NORM_L1), NormCode(cv::NORM_L2), NormCode(cv::NORM_INF)),
    174     WHOLE_SUBMAT));
    175 
    176 //////////////////////////////////////////////////////////////////////////////
    177 // Sum
    178 
    179 namespace
    180 {
    181     template <typename T>
    182     cv::Scalar absSumImpl(const cv::Mat& src)
    183     {
    184         const int cn = src.channels();
    185 
    186         cv::Scalar sum = cv::Scalar::all(0);
    187 
    188         for (int y = 0; y < src.rows; ++y)
    189         {
    190             for (int x = 0; x < src.cols; ++x)
    191             {
    192                 for (int c = 0; c < cn; ++c)
    193                     sum[c] += std::abs(src.at<T>(y, x * cn + c));
    194             }
    195         }
    196 
    197         return sum;
    198     }
    199 
    200     cv::Scalar absSumGold(const cv::Mat& src)
    201     {
    202         typedef cv::Scalar (*func_t)(const cv::Mat& src);
    203 
    204         static const func_t funcs[] =
    205         {
    206             absSumImpl<uchar>,
    207             absSumImpl<schar>,
    208             absSumImpl<ushort>,
    209             absSumImpl<short>,
    210             absSumImpl<int>,
    211             absSumImpl<float>,
    212             absSumImpl<double>
    213         };
    214 
    215         return funcs[src.depth()](src);
    216     }
    217 
    218     template <typename T>
    219     cv::Scalar sqrSumImpl(const cv::Mat& src)
    220     {
    221         const int cn = src.channels();
    222 
    223         cv::Scalar sum = cv::Scalar::all(0);
    224 
    225         for (int y = 0; y < src.rows; ++y)
    226         {
    227             for (int x = 0; x < src.cols; ++x)
    228             {
    229                 for (int c = 0; c < cn; ++c)
    230                 {
    231                     const T val = src.at<T>(y, x * cn + c);
    232                     sum[c] += val * val;
    233                 }
    234             }
    235         }
    236 
    237         return sum;
    238     }
    239 
    240     cv::Scalar sqrSumGold(const cv::Mat& src)
    241     {
    242         typedef cv::Scalar (*func_t)(const cv::Mat& src);
    243 
    244         static const func_t funcs[] =
    245         {
    246             sqrSumImpl<uchar>,
    247             sqrSumImpl<schar>,
    248             sqrSumImpl<ushort>,
    249             sqrSumImpl<short>,
    250             sqrSumImpl<int>,
    251             sqrSumImpl<float>,
    252             sqrSumImpl<double>
    253         };
    254 
    255         return funcs[src.depth()](src);
    256     }
    257 }
    258 
    259 PARAM_TEST_CASE(Sum, cv::cuda::DeviceInfo, cv::Size, MatType, UseRoi)
    260 {
    261     cv::cuda::DeviceInfo devInfo;
    262     cv::Size size;
    263     int type;
    264     bool useRoi;
    265 
    266     cv::Mat src;
    267 
    268     virtual void SetUp()
    269     {
    270         devInfo = GET_PARAM(0);
    271         size = GET_PARAM(1);
    272         type = GET_PARAM(2);
    273         useRoi = GET_PARAM(3);
    274 
    275         cv::cuda::setDevice(devInfo.deviceID());
    276 
    277         src = randomMat(size, type, -128.0, 128.0);
    278     }
    279 };
    280 
    281 CUDA_TEST_P(Sum, Simple)
    282 {
    283     cv::Scalar val = cv::cuda::sum(loadMat(src, useRoi));
    284 
    285     cv::Scalar val_gold = cv::sum(src);
    286 
    287     EXPECT_SCALAR_NEAR(val_gold, val, CV_MAT_DEPTH(type) < CV_32F ? 0.0 : 0.5);
    288 }
    289 
    290 CUDA_TEST_P(Sum, Simple_Async)
    291 {
    292     cv::cuda::Stream stream;
    293 
    294     cv::cuda::HostMem dst;
    295     cv::cuda::calcSum(loadMat(src, useRoi), dst, cv::noArray(), stream);
    296 
    297     stream.waitForCompletion();
    298 
    299     cv::Scalar val;
    300     cv::Mat val_mat(dst.size(), CV_64FC(dst.channels()), val.val);
    301     dst.createMatHeader().convertTo(val_mat, CV_64F);
    302 
    303     cv::Scalar val_gold = cv::sum(src);
    304 
    305     EXPECT_SCALAR_NEAR(val_gold, val, CV_MAT_DEPTH(type) < CV_32F ? 0.0 : 0.5);
    306 }
    307 
    308 CUDA_TEST_P(Sum, Abs)
    309 {
    310     cv::Scalar val = cv::cuda::absSum(loadMat(src, useRoi));
    311 
    312     cv::Scalar val_gold = absSumGold(src);
    313 
    314     EXPECT_SCALAR_NEAR(val_gold, val, CV_MAT_DEPTH(type) < CV_32F ? 0.0 : 0.5);
    315 }
    316 
    317 CUDA_TEST_P(Sum, Abs_Async)
    318 {
    319     cv::cuda::Stream stream;
    320 
    321     cv::cuda::HostMem dst;
    322     cv::cuda::calcAbsSum(loadMat(src, useRoi), dst, cv::noArray(), stream);
    323 
    324     stream.waitForCompletion();
    325 
    326     cv::Scalar val;
    327     cv::Mat val_mat(dst.size(), CV_64FC(dst.channels()), val.val);
    328     dst.createMatHeader().convertTo(val_mat, CV_64F);
    329 
    330     cv::Scalar val_gold = absSumGold(src);
    331 
    332     EXPECT_SCALAR_NEAR(val_gold, val, CV_MAT_DEPTH(type) < CV_32F ? 0.0 : 0.5);
    333 }
    334 
    335 CUDA_TEST_P(Sum, Sqr)
    336 {
    337     cv::Scalar val = cv::cuda::sqrSum(loadMat(src, useRoi));
    338 
    339     cv::Scalar val_gold = sqrSumGold(src);
    340 
    341     EXPECT_SCALAR_NEAR(val_gold, val, CV_MAT_DEPTH(type) < CV_32F ? 0.0 : 0.5);
    342 }
    343 
    344 CUDA_TEST_P(Sum, Sqr_Async)
    345 {
    346     cv::cuda::Stream stream;
    347 
    348     cv::cuda::HostMem dst;
    349     cv::cuda::calcSqrSum(loadMat(src, useRoi), dst, cv::noArray(), stream);
    350 
    351     stream.waitForCompletion();
    352 
    353     cv::Scalar val;
    354     cv::Mat val_mat(dst.size(), CV_64FC(dst.channels()), val.val);
    355     dst.createMatHeader().convertTo(val_mat, CV_64F);
    356 
    357     cv::Scalar val_gold = sqrSumGold(src);
    358 
    359     EXPECT_SCALAR_NEAR(val_gold, val, CV_MAT_DEPTH(type) < CV_32F ? 0.0 : 0.5);
    360 }
    361 
    362 INSTANTIATE_TEST_CASE_P(CUDA_Arithm, Sum, testing::Combine(
    363     ALL_DEVICES,
    364     DIFFERENT_SIZES,
    365     TYPES(CV_8U, CV_64F, 1, 4),
    366     WHOLE_SUBMAT));
    367 
    368 ////////////////////////////////////////////////////////////////////////////////
    369 // MinMax
    370 
    371 PARAM_TEST_CASE(MinMax, cv::cuda::DeviceInfo, cv::Size, MatDepth, UseRoi)
    372 {
    373     cv::cuda::DeviceInfo devInfo;
    374     cv::Size size;
    375     int depth;
    376     bool useRoi;
    377 
    378     virtual void SetUp()
    379     {
    380         devInfo = GET_PARAM(0);
    381         size = GET_PARAM(1);
    382         depth = GET_PARAM(2);
    383         useRoi = GET_PARAM(3);
    384 
    385         cv::cuda::setDevice(devInfo.deviceID());
    386     }
    387 };
    388 
    389 CUDA_TEST_P(MinMax, WithoutMask)
    390 {
    391     cv::Mat src = randomMat(size, depth);
    392 
    393     if (depth == CV_64F && !supportFeature(devInfo, cv::cuda::NATIVE_DOUBLE))
    394     {
    395         try
    396         {
    397             double minVal, maxVal;
    398             cv::cuda::minMax(loadMat(src), &minVal, &maxVal);
    399         }
    400         catch (const cv::Exception& e)
    401         {
    402             ASSERT_EQ(cv::Error::StsUnsupportedFormat, e.code);
    403         }
    404     }
    405     else
    406     {
    407         double minVal, maxVal;
    408         cv::cuda::minMax(loadMat(src, useRoi), &minVal, &maxVal);
    409 
    410         double minVal_gold, maxVal_gold;
    411         minMaxLocGold(src, &minVal_gold, &maxVal_gold);
    412 
    413         EXPECT_DOUBLE_EQ(minVal_gold, minVal);
    414         EXPECT_DOUBLE_EQ(maxVal_gold, maxVal);
    415     }
    416 }
    417 
    418 CUDA_TEST_P(MinMax, Async)
    419 {
    420     cv::Mat src = randomMat(size, depth);
    421 
    422     cv::cuda::Stream stream;
    423 
    424     cv::cuda::HostMem dst;
    425     cv::cuda::findMinMax(loadMat(src, useRoi), dst, cv::noArray(), stream);
    426 
    427     stream.waitForCompletion();
    428 
    429     double vals[2];
    430     const cv::Mat vals_mat(1, 2, CV_64FC1, &vals[0]);
    431     dst.createMatHeader().convertTo(vals_mat, CV_64F);
    432 
    433     double minVal_gold, maxVal_gold;
    434     minMaxLocGold(src, &minVal_gold, &maxVal_gold);
    435 
    436     EXPECT_DOUBLE_EQ(minVal_gold, vals[0]);
    437     EXPECT_DOUBLE_EQ(maxVal_gold, vals[1]);
    438 }
    439 
    440 CUDA_TEST_P(MinMax, WithMask)
    441 {
    442     cv::Mat src = randomMat(size, depth);
    443     cv::Mat mask = randomMat(size, CV_8UC1, 0.0, 2.0);
    444 
    445     if (depth == CV_64F && !supportFeature(devInfo, cv::cuda::NATIVE_DOUBLE))
    446     {
    447         try
    448         {
    449             double minVal, maxVal;
    450             cv::cuda::minMax(loadMat(src), &minVal, &maxVal, loadMat(mask));
    451         }
    452         catch (const cv::Exception& e)
    453         {
    454             ASSERT_EQ(cv::Error::StsUnsupportedFormat, e.code);
    455         }
    456     }
    457     else
    458     {
    459         double minVal, maxVal;
    460         cv::cuda::minMax(loadMat(src, useRoi), &minVal, &maxVal, loadMat(mask, useRoi));
    461 
    462         double minVal_gold, maxVal_gold;
    463         minMaxLocGold(src, &minVal_gold, &maxVal_gold, 0, 0, mask);
    464 
    465         EXPECT_DOUBLE_EQ(minVal_gold, minVal);
    466         EXPECT_DOUBLE_EQ(maxVal_gold, maxVal);
    467     }
    468 }
    469 
    470 CUDA_TEST_P(MinMax, NullPtr)
    471 {
    472     cv::Mat src = randomMat(size, depth);
    473 
    474     if (depth == CV_64F && !supportFeature(devInfo, cv::cuda::NATIVE_DOUBLE))
    475     {
    476         try
    477         {
    478             double minVal, maxVal;
    479             cv::cuda::minMax(loadMat(src), &minVal, 0);
    480             cv::cuda::minMax(loadMat(src), 0, &maxVal);
    481         }
    482         catch (const cv::Exception& e)
    483         {
    484             ASSERT_EQ(cv::Error::StsUnsupportedFormat, e.code);
    485         }
    486     }
    487     else
    488     {
    489         double minVal, maxVal;
    490         cv::cuda::minMax(loadMat(src, useRoi), &minVal, 0);
    491         cv::cuda::minMax(loadMat(src, useRoi), 0, &maxVal);
    492 
    493         double minVal_gold, maxVal_gold;
    494         minMaxLocGold(src, &minVal_gold, &maxVal_gold, 0, 0);
    495 
    496         EXPECT_DOUBLE_EQ(minVal_gold, minVal);
    497         EXPECT_DOUBLE_EQ(maxVal_gold, maxVal);
    498     }
    499 }
    500 
    501 INSTANTIATE_TEST_CASE_P(CUDA_Arithm, MinMax, testing::Combine(
    502     ALL_DEVICES,
    503     DIFFERENT_SIZES,
    504     ALL_DEPTH,
    505     WHOLE_SUBMAT));
    506 
    507 ////////////////////////////////////////////////////////////////////////////////
    508 // MinMaxLoc
    509 
    510 namespace
    511 {
    512     template <typename T>
    513     void expectEqualImpl(const cv::Mat& src, cv::Point loc_gold, cv::Point loc)
    514     {
    515         EXPECT_EQ(src.at<T>(loc_gold.y, loc_gold.x), src.at<T>(loc.y, loc.x));
    516     }
    517 
    518     void expectEqual(const cv::Mat& src, cv::Point loc_gold, cv::Point loc)
    519     {
    520         typedef void (*func_t)(const cv::Mat& src, cv::Point loc_gold, cv::Point loc);
    521 
    522         static const func_t funcs[] =
    523         {
    524             expectEqualImpl<uchar>,
    525             expectEqualImpl<schar>,
    526             expectEqualImpl<ushort>,
    527             expectEqualImpl<short>,
    528             expectEqualImpl<int>,
    529             expectEqualImpl<float>,
    530             expectEqualImpl<double>
    531         };
    532 
    533         funcs[src.depth()](src, loc_gold, loc);
    534     }
    535 }
    536 
    537 PARAM_TEST_CASE(MinMaxLoc, cv::cuda::DeviceInfo, cv::Size, MatDepth, UseRoi)
    538 {
    539     cv::cuda::DeviceInfo devInfo;
    540     cv::Size size;
    541     int depth;
    542     bool useRoi;
    543 
    544     virtual void SetUp()
    545     {
    546         devInfo = GET_PARAM(0);
    547         size = GET_PARAM(1);
    548         depth = GET_PARAM(2);
    549         useRoi = GET_PARAM(3);
    550 
    551         cv::cuda::setDevice(devInfo.deviceID());
    552     }
    553 };
    554 
    555 CUDA_TEST_P(MinMaxLoc, WithoutMask)
    556 {
    557     cv::Mat src = randomMat(size, depth);
    558 
    559     if (depth == CV_64F && !supportFeature(devInfo, cv::cuda::NATIVE_DOUBLE))
    560     {
    561         try
    562         {
    563             double minVal, maxVal;
    564             cv::Point minLoc, maxLoc;
    565             cv::cuda::minMaxLoc(loadMat(src), &minVal, &maxVal, &minLoc, &maxLoc);
    566         }
    567         catch (const cv::Exception& e)
    568         {
    569             ASSERT_EQ(cv::Error::StsUnsupportedFormat, e.code);
    570         }
    571     }
    572     else
    573     {
    574         double minVal, maxVal;
    575         cv::Point minLoc, maxLoc;
    576         cv::cuda::minMaxLoc(loadMat(src, useRoi), &minVal, &maxVal, &minLoc, &maxLoc);
    577 
    578         double minVal_gold, maxVal_gold;
    579         cv::Point minLoc_gold, maxLoc_gold;
    580         minMaxLocGold(src, &minVal_gold, &maxVal_gold, &minLoc_gold, &maxLoc_gold);
    581 
    582         EXPECT_DOUBLE_EQ(minVal_gold, minVal);
    583         EXPECT_DOUBLE_EQ(maxVal_gold, maxVal);
    584 
    585         expectEqual(src, minLoc_gold, minLoc);
    586         expectEqual(src, maxLoc_gold, maxLoc);
    587     }
    588 }
    589 
    590 CUDA_TEST_P(MinMaxLoc, OneRowMat)
    591 {
    592     cv::Mat src = randomMat(cv::Size(size.width, 1), depth);
    593 
    594     double minVal, maxVal;
    595     cv::Point minLoc, maxLoc;
    596     cv::cuda::minMaxLoc(loadMat(src, useRoi), &minVal, &maxVal, &minLoc, &maxLoc);
    597 
    598     double minVal_gold, maxVal_gold;
    599     cv::Point minLoc_gold, maxLoc_gold;
    600     minMaxLocGold(src, &minVal_gold, &maxVal_gold, &minLoc_gold, &maxLoc_gold);
    601 
    602     EXPECT_DOUBLE_EQ(minVal_gold, minVal);
    603     EXPECT_DOUBLE_EQ(maxVal_gold, maxVal);
    604 
    605     expectEqual(src, minLoc_gold, minLoc);
    606     expectEqual(src, maxLoc_gold, maxLoc);
    607 }
    608 
    609 CUDA_TEST_P(MinMaxLoc, OneColumnMat)
    610 {
    611     cv::Mat src = randomMat(cv::Size(1, size.height), depth);
    612 
    613     double minVal, maxVal;
    614     cv::Point minLoc, maxLoc;
    615     cv::cuda::minMaxLoc(loadMat(src, useRoi), &minVal, &maxVal, &minLoc, &maxLoc);
    616 
    617     double minVal_gold, maxVal_gold;
    618     cv::Point minLoc_gold, maxLoc_gold;
    619     minMaxLocGold(src, &minVal_gold, &maxVal_gold, &minLoc_gold, &maxLoc_gold);
    620 
    621     EXPECT_DOUBLE_EQ(minVal_gold, minVal);
    622     EXPECT_DOUBLE_EQ(maxVal_gold, maxVal);
    623 
    624     expectEqual(src, minLoc_gold, minLoc);
    625     expectEqual(src, maxLoc_gold, maxLoc);
    626 }
    627 
    628 CUDA_TEST_P(MinMaxLoc, Async)
    629 {
    630     cv::Mat src = randomMat(size, depth);
    631 
    632     cv::cuda::Stream stream;
    633 
    634     cv::cuda::HostMem minMaxVals, locVals;
    635     cv::cuda::findMinMaxLoc(loadMat(src, useRoi), minMaxVals, locVals, cv::noArray(), stream);
    636 
    637     stream.waitForCompletion();
    638 
    639     double vals[2];
    640     const cv::Mat vals_mat(2, 1, CV_64FC1, &vals[0]);
    641     minMaxVals.createMatHeader().convertTo(vals_mat, CV_64F);
    642 
    643     int locs[2];
    644     const cv::Mat locs_mat(2, 1, CV_32SC1, &locs[0]);
    645     locVals.createMatHeader().copyTo(locs_mat);
    646 
    647     cv::Point locs2D[] = {
    648         cv::Point(locs[0] % src.cols, locs[0] / src.cols),
    649         cv::Point(locs[1] % src.cols, locs[1] / src.cols),
    650     };
    651 
    652     double minVal_gold, maxVal_gold;
    653     cv::Point minLoc_gold, maxLoc_gold;
    654     minMaxLocGold(src, &minVal_gold, &maxVal_gold, &minLoc_gold, &maxLoc_gold);
    655 
    656     EXPECT_DOUBLE_EQ(minVal_gold, vals[0]);
    657     EXPECT_DOUBLE_EQ(maxVal_gold, vals[1]);
    658 
    659     expectEqual(src, minLoc_gold, locs2D[0]);
    660     expectEqual(src, maxLoc_gold, locs2D[1]);
    661 }
    662 
    663 CUDA_TEST_P(MinMaxLoc, WithMask)
    664 {
    665     cv::Mat src = randomMat(size, depth);
    666     cv::Mat mask = randomMat(size, CV_8UC1, 0.0, 2.0);
    667 
    668     if (depth == CV_64F && !supportFeature(devInfo, cv::cuda::NATIVE_DOUBLE))
    669     {
    670         try
    671         {
    672             double minVal, maxVal;
    673             cv::Point minLoc, maxLoc;
    674             cv::cuda::minMaxLoc(loadMat(src), &minVal, &maxVal, &minLoc, &maxLoc, loadMat(mask));
    675         }
    676         catch (const cv::Exception& e)
    677         {
    678             ASSERT_EQ(cv::Error::StsUnsupportedFormat, e.code);
    679         }
    680     }
    681     else
    682     {
    683         double minVal, maxVal;
    684         cv::Point minLoc, maxLoc;
    685         cv::cuda::minMaxLoc(loadMat(src, useRoi), &minVal, &maxVal, &minLoc, &maxLoc, loadMat(mask, useRoi));
    686 
    687         double minVal_gold, maxVal_gold;
    688         cv::Point minLoc_gold, maxLoc_gold;
    689         minMaxLocGold(src, &minVal_gold, &maxVal_gold, &minLoc_gold, &maxLoc_gold, mask);
    690 
    691         EXPECT_DOUBLE_EQ(minVal_gold, minVal);
    692         EXPECT_DOUBLE_EQ(maxVal_gold, maxVal);
    693 
    694         expectEqual(src, minLoc_gold, minLoc);
    695         expectEqual(src, maxLoc_gold, maxLoc);
    696     }
    697 }
    698 
    699 CUDA_TEST_P(MinMaxLoc, NullPtr)
    700 {
    701     cv::Mat src = randomMat(size, depth);
    702 
    703     if (depth == CV_64F && !supportFeature(devInfo, cv::cuda::NATIVE_DOUBLE))
    704     {
    705         try
    706         {
    707             double minVal, maxVal;
    708             cv::Point minLoc, maxLoc;
    709             cv::cuda::minMaxLoc(loadMat(src, useRoi), &minVal, 0, 0, 0);
    710             cv::cuda::minMaxLoc(loadMat(src, useRoi), 0, &maxVal, 0, 0);
    711             cv::cuda::minMaxLoc(loadMat(src, useRoi), 0, 0, &minLoc, 0);
    712             cv::cuda::minMaxLoc(loadMat(src, useRoi), 0, 0, 0, &maxLoc);
    713         }
    714         catch (const cv::Exception& e)
    715         {
    716             ASSERT_EQ(cv::Error::StsUnsupportedFormat, e.code);
    717         }
    718     }
    719     else
    720     {
    721         double minVal, maxVal;
    722         cv::Point minLoc, maxLoc;
    723         cv::cuda::minMaxLoc(loadMat(src, useRoi), &minVal, 0, 0, 0);
    724         cv::cuda::minMaxLoc(loadMat(src, useRoi), 0, &maxVal, 0, 0);
    725         cv::cuda::minMaxLoc(loadMat(src, useRoi), 0, 0, &minLoc, 0);
    726         cv::cuda::minMaxLoc(loadMat(src, useRoi), 0, 0, 0, &maxLoc);
    727 
    728         double minVal_gold, maxVal_gold;
    729         cv::Point minLoc_gold, maxLoc_gold;
    730         minMaxLocGold(src, &minVal_gold, &maxVal_gold, &minLoc_gold, &maxLoc_gold);
    731 
    732         EXPECT_DOUBLE_EQ(minVal_gold, minVal);
    733         EXPECT_DOUBLE_EQ(maxVal_gold, maxVal);
    734 
    735         expectEqual(src, minLoc_gold, minLoc);
    736         expectEqual(src, maxLoc_gold, maxLoc);
    737     }
    738 }
    739 
    740 INSTANTIATE_TEST_CASE_P(CUDA_Arithm, MinMaxLoc, testing::Combine(
    741     ALL_DEVICES,
    742     DIFFERENT_SIZES,
    743     ALL_DEPTH,
    744     WHOLE_SUBMAT));
    745 
    746 ////////////////////////////////////////////////////////////////////////////
    747 // CountNonZero
    748 
    749 PARAM_TEST_CASE(CountNonZero, cv::cuda::DeviceInfo, cv::Size, MatDepth, UseRoi)
    750 {
    751     cv::cuda::DeviceInfo devInfo;
    752     cv::Size size;
    753     int depth;
    754     bool useRoi;
    755 
    756     cv::Mat src;
    757 
    758     virtual void SetUp()
    759     {
    760         devInfo = GET_PARAM(0);
    761         size = GET_PARAM(1);
    762         depth = GET_PARAM(2);
    763         useRoi = GET_PARAM(3);
    764 
    765         cv::cuda::setDevice(devInfo.deviceID());
    766 
    767         cv::Mat srcBase = randomMat(size, CV_8U, 0.0, 1.5);
    768         srcBase.convertTo(src, depth);
    769     }
    770 };
    771 
    772 CUDA_TEST_P(CountNonZero, Accuracy)
    773 {
    774     if (depth == CV_64F && !supportFeature(devInfo, cv::cuda::NATIVE_DOUBLE))
    775     {
    776         try
    777         {
    778             cv::cuda::countNonZero(loadMat(src));
    779         }
    780         catch (const cv::Exception& e)
    781         {
    782             ASSERT_EQ(cv::Error::StsUnsupportedFormat, e.code);
    783         }
    784     }
    785     else
    786     {
    787         int val = cv::cuda::countNonZero(loadMat(src, useRoi));
    788 
    789         int val_gold = cv::countNonZero(src);
    790 
    791         ASSERT_EQ(val_gold, val);
    792     }
    793 }
    794 
    795 CUDA_TEST_P(CountNonZero, Async)
    796 {
    797     cv::cuda::Stream stream;
    798 
    799     cv::cuda::HostMem dst;
    800     cv::cuda::countNonZero(loadMat(src, useRoi), dst, stream);
    801 
    802     stream.waitForCompletion();
    803 
    804     int val;
    805     const cv::Mat val_mat(1, 1, CV_32SC1, &val);
    806     dst.createMatHeader().copyTo(val_mat);
    807 
    808     int val_gold = cv::countNonZero(src);
    809 
    810     ASSERT_EQ(val_gold, val);
    811 }
    812 
    813 INSTANTIATE_TEST_CASE_P(CUDA_Arithm, CountNonZero, testing::Combine(
    814     ALL_DEVICES,
    815     DIFFERENT_SIZES,
    816     ALL_DEPTH,
    817     WHOLE_SUBMAT));
    818 
    819 //////////////////////////////////////////////////////////////////////////////
    820 // Reduce
    821 
    822 CV_ENUM(ReduceCode, cv::REDUCE_SUM, cv::REDUCE_AVG, cv::REDUCE_MAX, cv::REDUCE_MIN)
    823 #define ALL_REDUCE_CODES testing::Values(ReduceCode(cv::REDUCE_SUM), ReduceCode(cv::REDUCE_AVG), ReduceCode(cv::REDUCE_MAX), ReduceCode(cv::REDUCE_MIN))
    824 
    825 PARAM_TEST_CASE(Reduce, cv::cuda::DeviceInfo, cv::Size, MatDepth, Channels, ReduceCode, UseRoi)
    826 {
    827     cv::cuda::DeviceInfo devInfo;
    828     cv::Size size;
    829     int depth;
    830     int channels;
    831     int reduceOp;
    832     bool useRoi;
    833 
    834     int type;
    835     int dst_depth;
    836     int dst_type;
    837 
    838     virtual void SetUp()
    839     {
    840         devInfo = GET_PARAM(0);
    841         size = GET_PARAM(1);
    842         depth = GET_PARAM(2);
    843         channels = GET_PARAM(3);
    844         reduceOp = GET_PARAM(4);
    845         useRoi = GET_PARAM(5);
    846 
    847         cv::cuda::setDevice(devInfo.deviceID());
    848 
    849         type = CV_MAKE_TYPE(depth, channels);
    850 
    851         if (reduceOp == cv::REDUCE_MAX || reduceOp == cv::REDUCE_MIN)
    852             dst_depth = depth;
    853         else if (reduceOp == cv::REDUCE_SUM)
    854             dst_depth = depth == CV_8U ? CV_32S : depth < CV_64F ? CV_32F : depth;
    855         else
    856             dst_depth = depth < CV_32F ? CV_32F : depth;
    857 
    858         dst_type = CV_MAKE_TYPE(dst_depth, channels);
    859     }
    860 
    861 };
    862 
    863 CUDA_TEST_P(Reduce, Rows)
    864 {
    865     cv::Mat src = randomMat(size, type);
    866 
    867     cv::cuda::GpuMat dst = createMat(cv::Size(src.cols, 1), dst_type, useRoi);
    868     cv::cuda::reduce(loadMat(src, useRoi), dst, 0, reduceOp, dst_depth);
    869 
    870     cv::Mat dst_gold;
    871     cv::reduce(src, dst_gold, 0, reduceOp, dst_depth);
    872 
    873     EXPECT_MAT_NEAR(dst_gold, dst, dst_depth < CV_32F ? 0.0 : 0.02);
    874 }
    875 
    876 CUDA_TEST_P(Reduce, Cols)
    877 {
    878     cv::Mat src = randomMat(size, type);
    879 
    880     cv::cuda::GpuMat dst = createMat(cv::Size(src.rows, 1), dst_type, useRoi);
    881     cv::cuda::reduce(loadMat(src, useRoi), dst, 1, reduceOp, dst_depth);
    882 
    883     cv::Mat dst_gold;
    884     cv::reduce(src, dst_gold, 1, reduceOp, dst_depth);
    885     dst_gold.cols = dst_gold.rows;
    886     dst_gold.rows = 1;
    887     dst_gold.step = dst_gold.cols * dst_gold.elemSize();
    888 
    889     EXPECT_MAT_NEAR(dst_gold, dst, dst_depth < CV_32F ? 0.0 : 0.02);
    890 }
    891 
    892 INSTANTIATE_TEST_CASE_P(CUDA_Arithm, Reduce, testing::Combine(
    893     ALL_DEVICES,
    894     DIFFERENT_SIZES,
    895     testing::Values(MatDepth(CV_8U),
    896                     MatDepth(CV_16U),
    897                     MatDepth(CV_16S),
    898                     MatDepth(CV_32F),
    899                     MatDepth(CV_64F)),
    900     ALL_CHANNELS,
    901     ALL_REDUCE_CODES,
    902     WHOLE_SUBMAT));
    903 
    904 //////////////////////////////////////////////////////////////////////////////
    905 // Normalize
    906 
    907 PARAM_TEST_CASE(Normalize, cv::cuda::DeviceInfo, cv::Size, MatDepth, NormCode, UseRoi)
    908 {
    909     cv::cuda::DeviceInfo devInfo;
    910     cv::Size size;
    911     int type;
    912     int norm_type;
    913     bool useRoi;
    914 
    915     double alpha;
    916     double beta;
    917 
    918     virtual void SetUp()
    919     {
    920         devInfo = GET_PARAM(0);
    921         size = GET_PARAM(1);
    922         type = GET_PARAM(2);
    923         norm_type = GET_PARAM(3);
    924         useRoi = GET_PARAM(4);
    925 
    926         cv::cuda::setDevice(devInfo.deviceID());
    927 
    928         alpha = 1;
    929         beta = 0;
    930     }
    931 
    932 };
    933 
    934 CUDA_TEST_P(Normalize, WithOutMask)
    935 {
    936     cv::Mat src = randomMat(size, type);
    937 
    938     cv::cuda::GpuMat dst = createMat(size, type, useRoi);
    939     cv::cuda::normalize(loadMat(src, useRoi), dst, alpha, beta, norm_type, type);
    940 
    941     cv::Mat dst_gold;
    942     cv::normalize(src, dst_gold, alpha, beta, norm_type, type);
    943 
    944     EXPECT_MAT_NEAR(dst_gold, dst, type < CV_32F ? 1.0 : 1e-4);
    945 }
    946 
    947 CUDA_TEST_P(Normalize, WithMask)
    948 {
    949     cv::Mat src = randomMat(size, type);
    950     cv::Mat mask = randomMat(size, CV_8UC1, 0, 2);
    951 
    952     cv::cuda::GpuMat dst = createMat(size, type, useRoi);
    953     dst.setTo(cv::Scalar::all(0));
    954     cv::cuda::normalize(loadMat(src, useRoi), dst, alpha, beta, norm_type, type, loadMat(mask, useRoi));
    955 
    956     cv::Mat dst_gold(size, type);
    957     dst_gold.setTo(cv::Scalar::all(0));
    958     cv::normalize(src, dst_gold, alpha, beta, norm_type, type, mask);
    959 
    960     EXPECT_MAT_NEAR(dst_gold, dst, type < CV_32F ? 1.0 : 1e-4);
    961 }
    962 
    963 INSTANTIATE_TEST_CASE_P(CUDA_Arithm, Normalize, testing::Combine(
    964     ALL_DEVICES,
    965     DIFFERENT_SIZES,
    966     ALL_DEPTH,
    967     testing::Values(NormCode(cv::NORM_L1), NormCode(cv::NORM_L2), NormCode(cv::NORM_INF), NormCode(cv::NORM_MINMAX)),
    968     WHOLE_SUBMAT));
    969 
    970 ////////////////////////////////////////////////////////////////////////////////
    971 // MeanStdDev
    972 
    973 PARAM_TEST_CASE(MeanStdDev, cv::cuda::DeviceInfo, cv::Size, UseRoi)
    974 {
    975     cv::cuda::DeviceInfo devInfo;
    976     cv::Size size;
    977     bool useRoi;
    978 
    979     virtual void SetUp()
    980     {
    981         devInfo = GET_PARAM(0);
    982         size = GET_PARAM(1);
    983         useRoi = GET_PARAM(2);
    984 
    985         cv::cuda::setDevice(devInfo.deviceID());
    986     }
    987 };
    988 
    989 CUDA_TEST_P(MeanStdDev, Accuracy)
    990 {
    991     cv::Mat src = randomMat(size, CV_8UC1);
    992 
    993     if (!supportFeature(devInfo, cv::cuda::FEATURE_SET_COMPUTE_13))
    994     {
    995         try
    996         {
    997             cv::Scalar mean;
    998             cv::Scalar stddev;
    999             cv::cuda::meanStdDev(loadMat(src, useRoi), mean, stddev);
   1000         }
   1001         catch (const cv::Exception& e)
   1002         {
   1003             ASSERT_EQ(cv::Error::StsNotImplemented, e.code);
   1004         }
   1005     }
   1006     else
   1007     {
   1008         cv::Scalar mean;
   1009         cv::Scalar stddev;
   1010         cv::cuda::meanStdDev(loadMat(src, useRoi), mean, stddev);
   1011 
   1012         cv::Scalar mean_gold;
   1013         cv::Scalar stddev_gold;
   1014         cv::meanStdDev(src, mean_gold, stddev_gold);
   1015 
   1016         EXPECT_SCALAR_NEAR(mean_gold, mean, 1e-5);
   1017         EXPECT_SCALAR_NEAR(stddev_gold, stddev, 1e-5);
   1018     }
   1019 }
   1020 
   1021 CUDA_TEST_P(MeanStdDev, Async)
   1022 {
   1023     cv::Mat src = randomMat(size, CV_8UC1);
   1024 
   1025     cv::cuda::Stream stream;
   1026 
   1027     cv::cuda::HostMem dst;
   1028     cv::cuda::meanStdDev(loadMat(src, useRoi), dst, stream);
   1029 
   1030     stream.waitForCompletion();
   1031 
   1032     double vals[2];
   1033     dst.createMatHeader().copyTo(cv::Mat(1, 2, CV_64FC1, &vals[0]));
   1034 
   1035     cv::Scalar mean_gold;
   1036     cv::Scalar stddev_gold;
   1037     cv::meanStdDev(src, mean_gold, stddev_gold);
   1038 
   1039     EXPECT_SCALAR_NEAR(mean_gold, cv::Scalar(vals[0]), 1e-5);
   1040     EXPECT_SCALAR_NEAR(stddev_gold, cv::Scalar(vals[1]), 1e-5);
   1041 }
   1042 
   1043 INSTANTIATE_TEST_CASE_P(CUDA_Arithm, MeanStdDev, testing::Combine(
   1044     ALL_DEVICES,
   1045     DIFFERENT_SIZES,
   1046     WHOLE_SUBMAT));
   1047 
   1048 ///////////////////////////////////////////////////////////////////////////////////////////////////////
   1049 // Integral
   1050 
   1051 PARAM_TEST_CASE(Integral, cv::cuda::DeviceInfo, cv::Size, UseRoi)
   1052 {
   1053     cv::cuda::DeviceInfo devInfo;
   1054     cv::Size size;
   1055     bool useRoi;
   1056 
   1057     virtual void SetUp()
   1058     {
   1059         devInfo = GET_PARAM(0);
   1060         size = GET_PARAM(1);
   1061         useRoi = GET_PARAM(2);
   1062 
   1063         cv::cuda::setDevice(devInfo.deviceID());
   1064     }
   1065 };
   1066 
   1067 CUDA_TEST_P(Integral, Accuracy)
   1068 {
   1069     cv::Mat src = randomMat(size, CV_8UC1);
   1070 
   1071     cv::cuda::GpuMat dst = createMat(cv::Size(src.cols + 1, src.rows + 1), CV_32SC1, useRoi);
   1072     cv::cuda::integral(loadMat(src, useRoi), dst);
   1073 
   1074     cv::Mat dst_gold;
   1075     cv::integral(src, dst_gold, CV_32S);
   1076 
   1077     EXPECT_MAT_NEAR(dst_gold, dst, 0.0);
   1078 }
   1079 
   1080 INSTANTIATE_TEST_CASE_P(CUDA_Arithm, Integral, testing::Combine(
   1081     ALL_DEVICES,
   1082     testing::Values(cv::Size(128, 128), cv::Size(113, 113), cv::Size(768, 1066)),
   1083     WHOLE_SUBMAT));
   1084 
   1085 ///////////////////////////////////////////////////////////////////////////////////////////////////////
   1086 // IntegralSqr
   1087 
   1088 PARAM_TEST_CASE(IntegralSqr, cv::cuda::DeviceInfo, cv::Size, UseRoi)
   1089 {
   1090     cv::cuda::DeviceInfo devInfo;
   1091     cv::Size size;
   1092     bool useRoi;
   1093 
   1094     virtual void SetUp()
   1095     {
   1096         devInfo = GET_PARAM(0);
   1097         size = GET_PARAM(1);
   1098         useRoi = GET_PARAM(2);
   1099 
   1100         cv::cuda::setDevice(devInfo.deviceID());
   1101     }
   1102 };
   1103 
   1104 CUDA_TEST_P(IntegralSqr, Accuracy)
   1105 {
   1106     cv::Mat src = randomMat(size, CV_8UC1);
   1107 
   1108     cv::cuda::GpuMat dst = createMat(cv::Size(src.cols + 1, src.rows + 1), CV_64FC1, useRoi);
   1109     cv::cuda::sqrIntegral(loadMat(src, useRoi), dst);
   1110 
   1111     cv::Mat dst_gold, temp;
   1112     cv::integral(src, temp, dst_gold);
   1113 
   1114     EXPECT_MAT_NEAR(dst_gold, dst, 0.0);
   1115 }
   1116 
   1117 INSTANTIATE_TEST_CASE_P(CUDA_Arithm, IntegralSqr, testing::Combine(
   1118     ALL_DEVICES,
   1119     DIFFERENT_SIZES,
   1120     WHOLE_SUBMAT));
   1121 
   1122 #endif // HAVE_CUDA
   1123