test_hdr.cpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  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) 2013, OpenCV Foundation, all rights reserved.
  14. // Third party copyrights are property of their respective owners.
  15. //
  16. // Redistribution and use in source and binary forms, with or without modification,
  17. // are permitted provided that the following conditions are met:
  18. //
  19. // * Redistribution's of source code must retain the above copyright notice,
  20. // this list of conditions and the following disclaimer.
  21. //
  22. // * Redistribution's in binary form must reproduce the above copyright notice,
  23. // this list of conditions and the following disclaimer in the documentation
  24. // and/or other materials provided with the distribution.
  25. //
  26. // * The name of the copyright holders may not be used to endorse or promote products
  27. // derived from this software without specific prior written permission.
  28. //
  29. // This software is provided by the copyright holders and contributors "as is" and
  30. // any express or implied warranties, including, but not limited to, the implied
  31. // warranties of merchantability and fitness for a particular purpose are disclaimed.
  32. // In no event shall the Intel Corporation or contributors be liable for any direct,
  33. // indirect, incidental, special, exemplary, or consequential damages
  34. // (including, but not limited to, procurement of substitute goods or services;
  35. // loss of use, data, or profits; or business interruption) however caused
  36. // and on any theory of liability, whether in contract, strict liability,
  37. // or tort (including negligence or otherwise) arising in any way out of
  38. // the use of this software, even if advised of the possibility of such damage.
  39. //
  40. //M*/
  41. #include "test_precomp.hpp"
  42. namespace opencv_test { namespace {
  43. void loadImage(string path, Mat &img)
  44. {
  45. img = imread(path, -1);
  46. ASSERT_FALSE(img.empty()) << "Could not load input image " << path;
  47. }
  48. void checkEqual(Mat img0, Mat img1, double threshold, const string& name)
  49. {
  50. double max = 1.0;
  51. minMaxLoc(abs(img0 - img1), NULL, &max);
  52. ASSERT_FALSE(max > threshold) << "max=" << max << " threshold=" << threshold << " method=" << name;
  53. }
  54. static vector<float> DEFAULT_VECTOR;
  55. void loadExposureSeq(String path, vector<Mat>& images, vector<float>& times = DEFAULT_VECTOR)
  56. {
  57. std::ifstream list_file((path + "list.txt").c_str());
  58. ASSERT_TRUE(list_file.is_open());
  59. string name;
  60. float val;
  61. while(list_file >> name >> val) {
  62. Mat img = imread(path + name);
  63. ASSERT_FALSE(img.empty()) << "Could not load input image " << path + name;
  64. images.push_back(img);
  65. times.push_back(1 / val);
  66. }
  67. list_file.close();
  68. }
  69. void loadResponseCSV(String path, Mat& response)
  70. {
  71. response = Mat(256, 1, CV_32FC3);
  72. std::ifstream resp_file(path.c_str());
  73. for(int i = 0; i < 256; i++) {
  74. for(int c = 0; c < 3; c++) {
  75. resp_file >> response.at<Vec3f>(i)[c];
  76. resp_file.ignore(1);
  77. }
  78. }
  79. resp_file.close();
  80. }
  81. TEST(Photo_Tonemap, regression)
  82. {
  83. string test_path = string(cvtest::TS::ptr()->get_data_path()) + "hdr/tonemap/";
  84. Mat img, expected, result;
  85. loadImage(test_path + "image.hdr", img);
  86. float gamma = 2.2f;
  87. Ptr<Tonemap> linear = createTonemap(gamma);
  88. linear->process(img, result);
  89. loadImage(test_path + "linear.png", expected);
  90. result.convertTo(result, CV_8UC3, 255);
  91. checkEqual(result, expected, 3, "Simple");
  92. Ptr<TonemapDrago> drago = createTonemapDrago(gamma);
  93. drago->process(img, result);
  94. loadImage(test_path + "drago.png", expected);
  95. result.convertTo(result, CV_8UC3, 255);
  96. checkEqual(result, expected, 3, "Drago");
  97. Ptr<TonemapReinhard> reinhard = createTonemapReinhard(gamma);
  98. reinhard->process(img, result);
  99. loadImage(test_path + "reinhard.png", expected);
  100. result.convertTo(result, CV_8UC3, 255);
  101. checkEqual(result, expected, 3, "Reinhard");
  102. Ptr<TonemapMantiuk> mantiuk = createTonemapMantiuk(gamma);
  103. mantiuk->process(img, result);
  104. loadImage(test_path + "mantiuk.png", expected);
  105. result.convertTo(result, CV_8UC3, 255);
  106. checkEqual(result, expected, 3, "Mantiuk");
  107. }
  108. TEST(Photo_AlignMTB, regression)
  109. {
  110. const int TESTS_COUNT = 100;
  111. string folder = string(cvtest::TS::ptr()->get_data_path()) + "shared/";
  112. string file_name = folder + "lena.png";
  113. Mat img;
  114. loadImage(file_name, img);
  115. cvtColor(img, img, COLOR_RGB2GRAY);
  116. int max_bits = 5;
  117. int max_shift = 32;
  118. srand(static_cast<unsigned>(time(0)));
  119. int errors = 0;
  120. Ptr<AlignMTB> align = createAlignMTB(max_bits);
  121. RNG rng = theRNG();
  122. for(int i = 0; i < TESTS_COUNT; i++) {
  123. Point shift(rng.uniform(0, max_shift), rng.uniform(0, max_shift));
  124. Mat res;
  125. align->shiftMat(img, res, shift);
  126. Point calc = align->calculateShift(img, res);
  127. errors += (calc != -shift);
  128. }
  129. ASSERT_TRUE(errors < 5) << errors << " errors";
  130. }
  131. TEST(Photo_MergeMertens, regression)
  132. {
  133. string test_path = string(cvtest::TS::ptr()->get_data_path()) + "hdr/";
  134. vector<Mat> images;
  135. loadExposureSeq((test_path + "exposures/").c_str() , images);
  136. Ptr<MergeMertens> merge = createMergeMertens();
  137. Mat result, expected;
  138. loadImage(test_path + "merge/mertens.png", expected);
  139. merge->process(images, result);
  140. result.convertTo(result, CV_8UC3, 255);
  141. checkEqual(expected, result, 3, "Mertens");
  142. Mat uniform(100, 100, CV_8UC3);
  143. uniform = Scalar(0, 255, 0);
  144. images.clear();
  145. images.push_back(uniform);
  146. merge->process(images, result);
  147. result.convertTo(result, CV_8UC3, 255);
  148. checkEqual(uniform, result, 1e-2f, "Mertens");
  149. }
  150. TEST(Photo_MergeDebevec, regression)
  151. {
  152. string test_path = string(cvtest::TS::ptr()->get_data_path()) + "hdr/";
  153. vector<Mat> images;
  154. vector<float> times;
  155. Mat response;
  156. loadExposureSeq(test_path + "exposures/", images, times);
  157. loadResponseCSV(test_path + "exposures/response.csv", response);
  158. Ptr<MergeDebevec> merge = createMergeDebevec();
  159. Mat result, expected;
  160. loadImage(test_path + "merge/debevec.hdr", expected);
  161. merge->process(images, result, times, response);
  162. Ptr<Tonemap> map = createTonemap();
  163. map->process(result, result);
  164. map->process(expected, expected);
  165. checkEqual(expected, result, 1e-2f, "Debevec");
  166. }
  167. TEST(Photo_MergeRobertson, regression)
  168. {
  169. string test_path = string(cvtest::TS::ptr()->get_data_path()) + "hdr/";
  170. vector<Mat> images;
  171. vector<float> times;
  172. loadExposureSeq(test_path + "exposures/", images, times);
  173. Ptr<MergeRobertson> merge = createMergeRobertson();
  174. Mat result, expected;
  175. loadImage(test_path + "merge/robertson.hdr", expected);
  176. merge->process(images, result, times);
  177. const float eps = 6.f;
  178. checkEqual(expected, result, eps, "MergeRobertson");
  179. }
  180. TEST(Photo_CalibrateDebevec, regression)
  181. {
  182. string test_path = string(cvtest::TS::ptr()->get_data_path()) + "hdr/";
  183. vector<Mat> images;
  184. vector<float> times;
  185. Mat response, expected;
  186. loadExposureSeq(test_path + "exposures/", images, times);
  187. loadResponseCSV(test_path + "calibrate/debevec.csv", expected);
  188. Ptr<CalibrateDebevec> calibrate = createCalibrateDebevec();
  189. calibrate->process(images, response, times);
  190. Mat diff = abs(response - expected);
  191. diff = diff.mul(1.0f / response);
  192. double max;
  193. minMaxLoc(diff, NULL, &max);
  194. #if defined(__arm__) || defined(__aarch64__)
  195. ASSERT_LT(max, 0.131);
  196. #else
  197. ASSERT_LT(max, 0.1);
  198. #endif
  199. }
  200. TEST(Photo_CalibrateRobertson, regression)
  201. {
  202. string test_path = string(cvtest::TS::ptr()->get_data_path()) + "hdr/";
  203. vector<Mat> images;
  204. vector<float> times;
  205. Mat response, expected;
  206. loadExposureSeq(test_path + "exposures/", images, times);
  207. loadResponseCSV(test_path + "calibrate/robertson.csv", expected);
  208. Ptr<CalibrateRobertson> calibrate = createCalibrateRobertson();
  209. calibrate->process(images, response, times);
  210. checkEqual(expected, response, 1e-1f, "CalibrateRobertson");
  211. }
  212. TEST(Photo_CalibrateRobertson, bug_18180)
  213. {
  214. vector<Mat> images;
  215. vector<cv::String> fn;
  216. string test_path = cvtest::TS::ptr()->get_data_path() + "hdr/exposures/bug_18180/";
  217. for(int i = 1; i <= 4; ++i)
  218. images.push_back(imread(test_path + std::to_string(i) + ".jpg"));
  219. vector<float> times {15.0f, 2.5f, 0.25f, 0.33f};
  220. Mat response, expected;
  221. Ptr<CalibrateRobertson> calibrate = createCalibrateRobertson(2, 0.01f);
  222. calibrate->process(images, response, times);
  223. Mat response_no_nans = response.clone();
  224. patchNaNs(response_no_nans);
  225. // since there should be no NaNs, original response vs. response with NaNs patched should be identical
  226. EXPECT_EQ(0.0, cv::norm(response, response_no_nans, NORM_L2));
  227. }
  228. }} // namespace