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