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 namespace
     50 {
     51     cv::Mat createTransfomMatrix(cv::Size srcSize, double angle)
     52     {
     53         cv::Mat M(2, 3, CV_64FC1);
     54 
     55         M.at<double>(0, 0) = std::cos(angle); M.at<double>(0, 1) = -std::sin(angle); M.at<double>(0, 2) = srcSize.width / 2;
     56         M.at<double>(1, 0) = std::sin(angle); M.at<double>(1, 1) =  std::cos(angle); M.at<double>(1, 2) = 0.0;
     57 
     58         return M;
     59     }
     60 }
     61 
     62 ///////////////////////////////////////////////////////////////////
     63 // Test buildWarpAffineMaps
     64 
     65 PARAM_TEST_CASE(BuildWarpAffineMaps, cv::cuda::DeviceInfo, cv::Size, Inverse)
     66 {
     67     cv::cuda::DeviceInfo devInfo;
     68     cv::Size size;
     69     bool inverse;
     70 
     71     virtual void SetUp()
     72     {
     73         devInfo = GET_PARAM(0);
     74         size = GET_PARAM(1);
     75         inverse = GET_PARAM(2);
     76 
     77         cv::cuda::setDevice(devInfo.deviceID());
     78     }
     79 };
     80 
     81 CUDA_TEST_P(BuildWarpAffineMaps, Accuracy)
     82 {
     83     cv::Mat M = createTransfomMatrix(size, CV_PI / 4);
     84     cv::Mat src = randomMat(randomSize(200, 400), CV_8UC1);
     85 
     86     cv::cuda::GpuMat xmap, ymap;
     87     cv::cuda::buildWarpAffineMaps(M, inverse, size, xmap, ymap);
     88 
     89     int interpolation = cv::INTER_NEAREST;
     90     int borderMode = cv::BORDER_CONSTANT;
     91     int flags = interpolation;
     92     if (inverse)
     93         flags |= cv::WARP_INVERSE_MAP;
     94 
     95     cv::Mat dst;
     96     cv::remap(src, dst, cv::Mat(xmap), cv::Mat(ymap), interpolation, borderMode);
     97 
     98     cv::Mat dst_gold;
     99     cv::warpAffine(src, dst_gold, M, size, flags, borderMode);
    100 
    101     EXPECT_MAT_NEAR(dst_gold, dst, 0.0);
    102 }
    103 
    104 INSTANTIATE_TEST_CASE_P(CUDA_Warping, BuildWarpAffineMaps, testing::Combine(
    105     ALL_DEVICES,
    106     DIFFERENT_SIZES,
    107     DIRECT_INVERSE));
    108 
    109 ///////////////////////////////////////////////////////////////////
    110 // Gold implementation
    111 
    112 namespace
    113 {
    114     template <typename T, template <typename> class Interpolator> void warpAffineImpl(const cv::Mat& src, const cv::Mat& M, cv::Size dsize, cv::Mat& dst, int borderType, cv::Scalar borderVal)
    115     {
    116         const int cn = src.channels();
    117 
    118         dst.create(dsize, src.type());
    119 
    120         for (int y = 0; y < dsize.height; ++y)
    121         {
    122             for (int x = 0; x < dsize.width; ++x)
    123             {
    124                 float xcoo = static_cast<float>(M.at<double>(0, 0) * x + M.at<double>(0, 1) * y + M.at<double>(0, 2));
    125                 float ycoo = static_cast<float>(M.at<double>(1, 0) * x + M.at<double>(1, 1) * y + M.at<double>(1, 2));
    126 
    127                 for (int c = 0; c < cn; ++c)
    128                     dst.at<T>(y, x * cn + c) = Interpolator<T>::getValue(src, ycoo, xcoo, c, borderType, borderVal);
    129             }
    130         }
    131     }
    132 
    133     void warpAffineGold(const cv::Mat& src, const cv::Mat& M, bool inverse, cv::Size dsize, cv::Mat& dst, int interpolation, int borderType, cv::Scalar borderVal)
    134     {
    135         typedef void (*func_t)(const cv::Mat& src, const cv::Mat& M, cv::Size dsize, cv::Mat& dst, int borderType, cv::Scalar borderVal);
    136 
    137         static const func_t nearest_funcs[] =
    138         {
    139             warpAffineImpl<unsigned char, NearestInterpolator>,
    140             warpAffineImpl<signed char, NearestInterpolator>,
    141             warpAffineImpl<unsigned short, NearestInterpolator>,
    142             warpAffineImpl<short, NearestInterpolator>,
    143             warpAffineImpl<int, NearestInterpolator>,
    144             warpAffineImpl<float, NearestInterpolator>
    145         };
    146 
    147         static const func_t linear_funcs[] =
    148         {
    149             warpAffineImpl<unsigned char, LinearInterpolator>,
    150             warpAffineImpl<signed char, LinearInterpolator>,
    151             warpAffineImpl<unsigned short, LinearInterpolator>,
    152             warpAffineImpl<short, LinearInterpolator>,
    153             warpAffineImpl<int, LinearInterpolator>,
    154             warpAffineImpl<float, LinearInterpolator>
    155         };
    156 
    157         static const func_t cubic_funcs[] =
    158         {
    159             warpAffineImpl<unsigned char, CubicInterpolator>,
    160             warpAffineImpl<signed char, CubicInterpolator>,
    161             warpAffineImpl<unsigned short, CubicInterpolator>,
    162             warpAffineImpl<short, CubicInterpolator>,
    163             warpAffineImpl<int, CubicInterpolator>,
    164             warpAffineImpl<float, CubicInterpolator>
    165         };
    166 
    167         static const func_t* funcs[] = {nearest_funcs, linear_funcs, cubic_funcs};
    168 
    169         if (inverse)
    170             funcs[interpolation][src.depth()](src, M, dsize, dst, borderType, borderVal);
    171         else
    172         {
    173             cv::Mat iM;
    174             cv::invertAffineTransform(M, iM);
    175             funcs[interpolation][src.depth()](src, iM, dsize, dst, borderType, borderVal);
    176         }
    177     }
    178 }
    179 
    180 ///////////////////////////////////////////////////////////////////
    181 // Test
    182 
    183 PARAM_TEST_CASE(WarpAffine, cv::cuda::DeviceInfo, cv::Size, MatType, Inverse, Interpolation, BorderType, UseRoi)
    184 {
    185     cv::cuda::DeviceInfo devInfo;
    186     cv::Size size;
    187     int type;
    188     bool inverse;
    189     int interpolation;
    190     int borderType;
    191     bool useRoi;
    192 
    193     virtual void SetUp()
    194     {
    195         devInfo = GET_PARAM(0);
    196         size = GET_PARAM(1);
    197         type = GET_PARAM(2);
    198         inverse = GET_PARAM(3);
    199         interpolation = GET_PARAM(4);
    200         borderType = GET_PARAM(5);
    201         useRoi = GET_PARAM(6);
    202 
    203         cv::cuda::setDevice(devInfo.deviceID());
    204     }
    205 };
    206 
    207 CUDA_TEST_P(WarpAffine, Accuracy)
    208 {
    209     cv::Mat src = randomMat(size, type);
    210     cv::Mat M = createTransfomMatrix(size, CV_PI / 3);
    211     int flags = interpolation;
    212     if (inverse)
    213         flags |= cv::WARP_INVERSE_MAP;
    214     cv::Scalar val = randomScalar(0.0, 255.0);
    215 
    216     cv::cuda::GpuMat dst = createMat(size, type, useRoi);
    217     cv::cuda::warpAffine(loadMat(src, useRoi), dst, M, size, flags, borderType, val);
    218 
    219     cv::Mat dst_gold;
    220     warpAffineGold(src, M, inverse, size, dst_gold, interpolation, borderType, val);
    221 
    222     EXPECT_MAT_NEAR(dst_gold, dst, src.depth() == CV_32F ? 1e-1 : 1.0);
    223 }
    224 
    225 INSTANTIATE_TEST_CASE_P(CUDA_Warping, WarpAffine, testing::Combine(
    226     ALL_DEVICES,
    227     DIFFERENT_SIZES,
    228     testing::Values(MatType(CV_8UC1), MatType(CV_8UC3), MatType(CV_8UC4), MatType(CV_16UC1), MatType(CV_16UC3), MatType(CV_16UC4), MatType(CV_32FC1), MatType(CV_32FC3), MatType(CV_32FC4)),
    229     DIRECT_INVERSE,
    230     testing::Values(Interpolation(cv::INTER_NEAREST), Interpolation(cv::INTER_LINEAR), Interpolation(cv::INTER_CUBIC)),
    231     testing::Values(BorderType(cv::BORDER_REFLECT101), BorderType(cv::BORDER_REPLICATE), BorderType(cv::BORDER_REFLECT), BorderType(cv::BORDER_WRAP)),
    232     WHOLE_SUBMAT));
    233 
    234 ///////////////////////////////////////////////////////////////////
    235 // Test NPP
    236 
    237 PARAM_TEST_CASE(WarpAffineNPP, cv::cuda::DeviceInfo, MatType, Inverse, Interpolation)
    238 {
    239     cv::cuda::DeviceInfo devInfo;
    240     int type;
    241     bool inverse;
    242     int interpolation;
    243 
    244     virtual void SetUp()
    245     {
    246         devInfo = GET_PARAM(0);
    247         type = GET_PARAM(1);
    248         inverse = GET_PARAM(2);
    249         interpolation = GET_PARAM(3);
    250 
    251         cv::cuda::setDevice(devInfo.deviceID());
    252     }
    253 };
    254 
    255 CUDA_TEST_P(WarpAffineNPP, Accuracy)
    256 {
    257     cv::Mat src = readImageType("stereobp/aloe-L.png", type);
    258     ASSERT_FALSE(src.empty());
    259 
    260     cv::Mat M = createTransfomMatrix(src.size(), CV_PI / 4);
    261     int flags = interpolation;
    262     if (inverse)
    263         flags |= cv::WARP_INVERSE_MAP;
    264 
    265     cv::cuda::GpuMat dst;
    266     cv::cuda::warpAffine(loadMat(src), dst, M, src.size(), flags);
    267 
    268     cv::Mat dst_gold;
    269     warpAffineGold(src, M, inverse, src.size(), dst_gold, interpolation, cv::BORDER_CONSTANT, cv::Scalar::all(0));
    270 
    271     EXPECT_MAT_SIMILAR(dst_gold, dst, 2e-2);
    272 }
    273 
    274 INSTANTIATE_TEST_CASE_P(CUDA_Warping, WarpAffineNPP, testing::Combine(
    275     ALL_DEVICES,
    276     testing::Values(MatType(CV_8UC1), MatType(CV_8UC3), MatType(CV_8UC4), MatType(CV_32FC1), MatType(CV_32FC3), MatType(CV_32FC4)),
    277     DIRECT_INVERSE,
    278     testing::Values(Interpolation(cv::INTER_NEAREST), Interpolation(cv::INTER_LINEAR), Interpolation(cv::INTER_CUBIC))));
    279 
    280 #endif // HAVE_CUDA
    281