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 #include "opencv2/ts/ocl_test.hpp" 45 46 #if BUILD_WITH_VIDEO_INPUT_SUPPORT 47 48 class AllignedFrameSource : public cv::superres::FrameSource 49 { 50 public: 51 AllignedFrameSource(const cv::Ptr<cv::superres::FrameSource>& base, int scale); 52 53 void nextFrame(cv::OutputArray frame); 54 void reset(); 55 56 private: 57 cv::Ptr<cv::superres::FrameSource> base_; 58 59 cv::Mat origFrame_; 60 int scale_; 61 }; 62 63 AllignedFrameSource::AllignedFrameSource(const cv::Ptr<cv::superres::FrameSource>& base, int scale) : 64 base_(base), scale_(scale) 65 { 66 CV_Assert( base_ ); 67 } 68 69 void AllignedFrameSource::nextFrame(cv::OutputArray frame) 70 { 71 base_->nextFrame(origFrame_); 72 73 if (origFrame_.rows % scale_ == 0 && origFrame_.cols % scale_ == 0) 74 cv::superres::arrCopy(origFrame_, frame); 75 else 76 { 77 cv::Rect ROI(0, 0, (origFrame_.cols / scale_) * scale_, (origFrame_.rows / scale_) * scale_); 78 cv::superres::arrCopy(origFrame_(ROI), frame); 79 } 80 } 81 82 void AllignedFrameSource::reset() 83 { 84 base_->reset(); 85 } 86 87 class DegradeFrameSource : public cv::superres::FrameSource 88 { 89 public: 90 DegradeFrameSource(const cv::Ptr<cv::superres::FrameSource>& base, int scale); 91 92 void nextFrame(cv::OutputArray frame); 93 void reset(); 94 95 private: 96 cv::Ptr<cv::superres::FrameSource> base_; 97 98 cv::Mat origFrame_; 99 cv::Mat blurred_; 100 cv::Mat deg_; 101 double iscale_; 102 }; 103 104 DegradeFrameSource::DegradeFrameSource(const cv::Ptr<cv::superres::FrameSource>& base, int scale) : 105 base_(base), iscale_(1.0 / scale) 106 { 107 CV_Assert( base_ ); 108 } 109 110 static void addGaussNoise(cv::OutputArray _image, double sigma) 111 { 112 int type = _image.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); 113 cv::Mat noise(_image.size(), CV_32FC(cn)); 114 cvtest::TS::ptr()->get_rng().fill(noise, cv::RNG::NORMAL, 0.0, sigma); 115 116 cv::addWeighted(_image, 1.0, noise, 1.0, 0.0, _image, depth); 117 } 118 119 static void addSpikeNoise(cv::OutputArray _image, int frequency) 120 { 121 cv::Mat_<uchar> mask(_image.size(), 0); 122 123 for (int y = 0; y < mask.rows; ++y) 124 for (int x = 0; x < mask.cols; ++x) 125 if (cvtest::TS::ptr()->get_rng().uniform(0, frequency) < 1) 126 mask(y, x) = 255; 127 128 _image.setTo(cv::Scalar::all(255), mask); 129 } 130 131 void DegradeFrameSource::nextFrame(cv::OutputArray frame) 132 { 133 base_->nextFrame(origFrame_); 134 135 cv::GaussianBlur(origFrame_, blurred_, cv::Size(5, 5), 0); 136 cv::resize(blurred_, deg_, cv::Size(), iscale_, iscale_, cv::INTER_NEAREST); 137 138 addGaussNoise(deg_, 10.0); 139 addSpikeNoise(deg_, 500); 140 141 cv::superres::arrCopy(deg_, frame); 142 } 143 144 void DegradeFrameSource::reset() 145 { 146 base_->reset(); 147 } 148 149 double MSSIM(cv::InputArray _i1, cv::InputArray _i2) 150 { 151 const double C1 = 6.5025; 152 const double C2 = 58.5225; 153 154 const int depth = CV_32F; 155 156 cv::Mat I1, I2; 157 _i1.getMat().convertTo(I1, depth); 158 _i2.getMat().convertTo(I2, depth); 159 160 cv::Mat I2_2 = I2.mul(I2); // I2^2 161 cv::Mat I1_2 = I1.mul(I1); // I1^2 162 cv::Mat I1_I2 = I1.mul(I2); // I1 * I2 163 164 cv::Mat mu1, mu2; 165 cv::GaussianBlur(I1, mu1, cv::Size(11, 11), 1.5); 166 cv::GaussianBlur(I2, mu2, cv::Size(11, 11), 1.5); 167 168 cv::Mat mu1_2 = mu1.mul(mu1); 169 cv::Mat mu2_2 = mu2.mul(mu2); 170 cv::Mat mu1_mu2 = mu1.mul(mu2); 171 172 cv::Mat sigma1_2, sigma2_2, sigma12; 173 174 cv::GaussianBlur(I1_2, sigma1_2, cv::Size(11, 11), 1.5); 175 sigma1_2 -= mu1_2; 176 177 cv::GaussianBlur(I2_2, sigma2_2, cv::Size(11, 11), 1.5); 178 sigma2_2 -= mu2_2; 179 180 cv::GaussianBlur(I1_I2, sigma12, cv::Size(11, 11), 1.5); 181 sigma12 -= mu1_mu2; 182 183 cv::Mat t1, t2; 184 cv::Mat numerator; 185 cv::Mat denominator; 186 187 // t3 = ((2*mu1_mu2 + C1).*(2*sigma12 + C2)) 188 t1 = 2 * mu1_mu2 + C1; 189 t2 = 2 * sigma12 + C2; 190 numerator = t1.mul(t2); 191 192 // t1 =((mu1_2 + mu2_2 + C1).*(sigma1_2 + sigma2_2 + C2)) 193 t1 = mu1_2 + mu2_2 + C1; 194 t2 = sigma1_2 + sigma2_2 + C2; 195 denominator = t1.mul(t2); 196 197 // ssim_map = numerator./denominator; 198 cv::Mat ssim_map; 199 cv::divide(numerator, denominator, ssim_map); 200 201 // mssim = average of ssim map 202 cv::Scalar mssim = cv::mean(ssim_map); 203 204 if (_i1.channels() == 1) 205 return mssim[0]; 206 207 return (mssim[0] + mssim[1] + mssim[3]) / 3; 208 } 209 210 class SuperResolution : public testing::Test 211 { 212 public: 213 template <typename T> 214 void RunTest(cv::Ptr<cv::superres::SuperResolution> superRes); 215 }; 216 217 template <typename T> 218 void SuperResolution::RunTest(cv::Ptr<cv::superres::SuperResolution> superRes) 219 { 220 const std::string inputVideoName = cvtest::TS::ptr()->get_data_path() + "car.avi"; 221 const int scale = 2; 222 const int iterations = 100; 223 const int temporalAreaRadius = 2; 224 225 ASSERT_FALSE( superRes.empty() ); 226 227 const int btvKernelSize = superRes->getKernelSize(); 228 229 superRes->setScale(scale); 230 superRes->setIterations(iterations); 231 superRes->setTemporalAreaRadius(temporalAreaRadius); 232 233 cv::Ptr<cv::superres::FrameSource> goldSource(new AllignedFrameSource(cv::superres::createFrameSource_Video(inputVideoName), scale)); 234 cv::Ptr<cv::superres::FrameSource> lowResSource(new DegradeFrameSource( 235 cv::makePtr<AllignedFrameSource>(cv::superres::createFrameSource_Video(inputVideoName), scale), scale)); 236 237 // skip first frame 238 cv::Mat frame; 239 240 lowResSource->nextFrame(frame); 241 goldSource->nextFrame(frame); 242 243 cv::Rect inner(btvKernelSize, btvKernelSize, frame.cols - 2 * btvKernelSize, frame.rows - 2 * btvKernelSize); 244 245 superRes->setInput(lowResSource); 246 247 double srAvgMSSIM = 0.0; 248 const int count = 10; 249 250 cv::Mat goldFrame; 251 T superResFrame; 252 for (int i = 0; i < count; ++i) 253 { 254 goldSource->nextFrame(goldFrame); 255 ASSERT_FALSE( goldFrame.empty() ); 256 257 superRes->nextFrame(superResFrame); 258 ASSERT_FALSE( superResFrame.empty() ); 259 260 const double srMSSIM = MSSIM(goldFrame(inner), superResFrame); 261 262 srAvgMSSIM += srMSSIM; 263 } 264 265 srAvgMSSIM /= count; 266 267 EXPECT_GE( srAvgMSSIM, 0.5 ); 268 } 269 270 TEST_F(SuperResolution, BTVL1) 271 { 272 RunTest<cv::Mat>(cv::superres::createSuperResolution_BTVL1()); 273 } 274 275 #if defined(HAVE_CUDA) && defined(HAVE_OPENCV_CUDAARITHM) && defined(HAVE_OPENCV_CUDAWARPING) && defined(HAVE_OPENCV_CUDAFILTERS) 276 277 TEST_F(SuperResolution, BTVL1_CUDA) 278 { 279 RunTest<cv::Mat>(cv::superres::createSuperResolution_BTVL1_CUDA()); 280 } 281 282 #endif 283 284 #ifdef HAVE_OPENCL 285 286 namespace cvtest { 287 namespace ocl { 288 289 OCL_TEST_F(SuperResolution, BTVL1) 290 { 291 RunTest<cv::UMat>(cv::superres::createSuperResolution_BTVL1()); 292 } 293 294 } } // namespace cvtest::ocl 295 296 #endif 297 298 #endif // BUILD_WITH_VIDEO_INPUT_SUPPORT 299