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 
42 #include "test_precomp.hpp"
43 
44 using namespace cv;
45 using namespace std;
46 
loadImage(string path,Mat & img)47 void loadImage(string path, Mat &img)
48 {
49     img = imread(path, -1);
50     ASSERT_FALSE(img.empty()) << "Could not load input image " << path;
51 }
52 
checkEqual(Mat img0,Mat img1,double threshold,const string & name)53 void checkEqual(Mat img0, Mat img1, double threshold, const string& name)
54 {
55     double max = 1.0;
56     minMaxLoc(abs(img0 - img1), NULL, &max);
57     ASSERT_FALSE(max > threshold) << "max=" << max << " threshold=" << threshold << " method=" << name;
58 }
59 
60 static vector<float> DEFAULT_VECTOR;
loadExposureSeq(String path,vector<Mat> & images,vector<float> & times=DEFAULT_VECTOR)61 void loadExposureSeq(String path, vector<Mat>& images, vector<float>& times = DEFAULT_VECTOR)
62 {
63     ifstream list_file((path + "list.txt").c_str());
64     ASSERT_TRUE(list_file.is_open());
65     string name;
66     float val;
67     while(list_file >> name >> val) {
68         Mat img = imread(path + name);
69         ASSERT_FALSE(img.empty()) << "Could not load input image " << path + name;
70         images.push_back(img);
71         times.push_back(1 / val);
72     }
73     list_file.close();
74 }
75 
loadResponseCSV(String path,Mat & response)76 void loadResponseCSV(String path, Mat& response)
77 {
78     response = Mat(256, 1, CV_32FC3);
79     ifstream resp_file(path.c_str());
80     for(int i = 0; i < 256; i++) {
81         for(int c = 0; c < 3; c++) {
82             resp_file >> response.at<Vec3f>(i)[c];
83             resp_file.ignore(1);
84         }
85     }
86     resp_file.close();
87 }
88 
TEST(Photo_Tonemap,regression)89 TEST(Photo_Tonemap, regression)
90 {
91     string test_path = string(cvtest::TS::ptr()->get_data_path()) + "hdr/tonemap/";
92 
93     Mat img, expected, result;
94     loadImage(test_path + "image.hdr", img);
95     float gamma = 2.2f;
96 
97     Ptr<Tonemap> linear = createTonemap(gamma);
98     linear->process(img, result);
99     loadImage(test_path + "linear.png", expected);
100     result.convertTo(result, CV_8UC3, 255);
101     checkEqual(result, expected, 3, "Simple");
102 
103     Ptr<TonemapDrago> drago = createTonemapDrago(gamma);
104     drago->process(img, result);
105     loadImage(test_path + "drago.png", expected);
106     result.convertTo(result, CV_8UC3, 255);
107     checkEqual(result, expected, 3, "Drago");
108 
109     Ptr<TonemapDurand> durand = createTonemapDurand(gamma);
110     durand->process(img, result);
111     loadImage(test_path + "durand.png", expected);
112     result.convertTo(result, CV_8UC3, 255);
113     checkEqual(result, expected, 3, "Durand");
114 
115     Ptr<TonemapReinhard> reinhard = createTonemapReinhard(gamma);
116     reinhard->process(img, result);
117     loadImage(test_path + "reinhard.png", expected);
118     result.convertTo(result, CV_8UC3, 255);
119     checkEqual(result, expected, 3, "Reinhard");
120 
121     Ptr<TonemapMantiuk> mantiuk = createTonemapMantiuk(gamma);
122     mantiuk->process(img, result);
123     loadImage(test_path + "mantiuk.png", expected);
124     result.convertTo(result, CV_8UC3, 255);
125     checkEqual(result, expected, 3, "Mantiuk");
126 }
127 
TEST(Photo_AlignMTB,regression)128 TEST(Photo_AlignMTB, regression)
129 {
130     const int TESTS_COUNT = 100;
131     string folder = string(cvtest::TS::ptr()->get_data_path()) + "shared/";
132 
133     string file_name = folder + "lena.png";
134     Mat img;
135     loadImage(file_name, img);
136     cvtColor(img, img, COLOR_RGB2GRAY);
137 
138     int max_bits = 5;
139     int max_shift = 32;
140     srand(static_cast<unsigned>(time(0)));
141     int errors = 0;
142 
143     Ptr<AlignMTB> align = createAlignMTB(max_bits);
144 
145     for(int i = 0; i < TESTS_COUNT; i++) {
146         Point shift(rand() % max_shift, rand() % max_shift);
147         Mat res;
148         align->shiftMat(img, res, shift);
149         Point calc = align->calculateShift(img, res);
150         errors += (calc != -shift);
151     }
152     ASSERT_TRUE(errors < 5) << errors << " errors";
153 }
154 
TEST(Photo_MergeMertens,regression)155 TEST(Photo_MergeMertens, regression)
156 {
157     string test_path = string(cvtest::TS::ptr()->get_data_path()) + "hdr/";
158 
159     vector<Mat> images;
160     loadExposureSeq((test_path + "exposures/").c_str() , images);
161 
162     Ptr<MergeMertens> merge = createMergeMertens();
163 
164     Mat result, expected;
165     loadImage(test_path + "merge/mertens.png", expected);
166     merge->process(images, result);
167     result.convertTo(result, CV_8UC3, 255);
168     checkEqual(expected, result, 3, "Mertens");
169 
170     Mat uniform(100, 100, CV_8UC3);
171     uniform = Scalar(0, 255, 0);
172 
173     images.clear();
174     images.push_back(uniform);
175 
176     merge->process(images, result);
177     result.convertTo(result, CV_8UC3, 255);
178     checkEqual(uniform, result, 1e-2f, "Mertens");
179 }
180 
TEST(Photo_MergeDebevec,regression)181 TEST(Photo_MergeDebevec, regression)
182 {
183     string test_path = string(cvtest::TS::ptr()->get_data_path()) + "hdr/";
184 
185     vector<Mat> images;
186     vector<float> times;
187     Mat response;
188     loadExposureSeq(test_path + "exposures/", images, times);
189     loadResponseCSV(test_path + "exposures/response.csv", response);
190 
191     Ptr<MergeDebevec> merge = createMergeDebevec();
192 
193     Mat result, expected;
194     loadImage(test_path + "merge/debevec.hdr", expected);
195     merge->process(images, result, times, response);
196 
197     Ptr<Tonemap> map = createTonemap();
198     map->process(result, result);
199     map->process(expected, expected);
200 
201     checkEqual(expected, result, 1e-2f, "Debevec");
202 }
203 
TEST(Photo_MergeRobertson,regression)204 TEST(Photo_MergeRobertson, regression)
205 {
206     string test_path = string(cvtest::TS::ptr()->get_data_path()) + "hdr/";
207 
208     vector<Mat> images;
209     vector<float> times;
210     loadExposureSeq(test_path + "exposures/", images, times);
211 
212     Ptr<MergeRobertson> merge = createMergeRobertson();
213 
214     Mat result, expected;
215     loadImage(test_path + "merge/robertson.hdr", expected);
216     merge->process(images, result, times);
217     Ptr<Tonemap> map = createTonemap();
218     map->process(result, result);
219     map->process(expected, expected);
220 
221     checkEqual(expected, result, 1e-2f, "MergeRobertson");
222 }
223 
TEST(Photo_CalibrateDebevec,regression)224 TEST(Photo_CalibrateDebevec, regression)
225 {
226     string test_path = string(cvtest::TS::ptr()->get_data_path()) + "hdr/";
227 
228     vector<Mat> images;
229     vector<float> times;
230     Mat response, expected;
231     loadExposureSeq(test_path + "exposures/", images, times);
232     loadResponseCSV(test_path + "calibrate/debevec.csv", expected);
233     Ptr<CalibrateDebevec> calibrate = createCalibrateDebevec();
234 
235     calibrate->process(images, response, times);
236     Mat diff = abs(response - expected);
237     diff = diff.mul(1.0f / response);
238     double max;
239     minMaxLoc(diff, NULL, &max);
240     ASSERT_FALSE(max > 0.1);
241 }
242 
TEST(Photo_CalibrateRobertson,regression)243 TEST(Photo_CalibrateRobertson, regression)
244 {
245     string test_path = string(cvtest::TS::ptr()->get_data_path()) + "hdr/";
246 
247     vector<Mat> images;
248     vector<float> times;
249     Mat response, expected;
250     loadExposureSeq(test_path + "exposures/", images, times);
251     loadResponseCSV(test_path + "calibrate/robertson.csv", expected);
252 
253     Ptr<CalibrateRobertson> calibrate = createCalibrateRobertson();
254     calibrate->process(images, response, times);
255     checkEqual(expected, response, 1e-3f, "CalibrateRobertson");
256 }
257