• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "precomp.hpp"
44 #include "opencv2/photo.hpp"
45 #include "opencv2/imgproc.hpp"
46 //#include "opencv2/highgui.hpp"
47 #include "hdr_common.hpp"
48 
49 namespace cv
50 {
51 
52 class CalibrateDebevecImpl : public CalibrateDebevec
53 {
54 public:
CalibrateDebevecImpl(int _samples,float _lambda,bool _random)55     CalibrateDebevecImpl(int _samples, float _lambda, bool _random) :
56         name("CalibrateDebevec"),
57         samples(_samples),
58         lambda(_lambda),
59         random(_random),
60         w(tringleWeights())
61     {
62     }
63 
process(InputArrayOfArrays src,OutputArray dst,InputArray _times)64     void process(InputArrayOfArrays src, OutputArray dst, InputArray _times)
65     {
66         std::vector<Mat> images;
67         src.getMatVector(images);
68         Mat times = _times.getMat();
69 
70         CV_Assert(images.size() == times.total());
71         checkImageDimensions(images);
72         CV_Assert(images[0].depth() == CV_8U);
73 
74         int channels = images[0].channels();
75         int CV_32FCC = CV_MAKETYPE(CV_32F, channels);
76 
77         dst.create(LDR_SIZE, 1, CV_32FCC);
78         Mat result = dst.getMat();
79 
80         std::vector<Point> sample_points;
81         if(random) {
82             for(int i = 0; i < samples; i++) {
83                 sample_points.push_back(Point(rand() % images[0].cols, rand() % images[0].rows));
84             }
85         } else {
86             int x_points = static_cast<int>(sqrt(static_cast<double>(samples) * images[0].cols / images[0].rows));
87             int y_points = samples / x_points;
88             int step_x = images[0].cols / x_points;
89             int step_y = images[0].rows / y_points;
90 
91             for(int i = 0, x = step_x / 2; i < x_points; i++, x += step_x) {
92                 for(int j = 0, y = step_y / 2; j < y_points; j++, y += step_y) {
93                     if( 0 <= x && x < images[0].cols &&
94                         0 <= y && y < images[0].rows )
95                         sample_points.push_back(Point(x, y));
96                 }
97             }
98         }
99 
100         std::vector<Mat> result_split(channels);
101         for(int channel = 0; channel < channels; channel++) {
102             Mat A = Mat::zeros((int)sample_points.size() * (int)images.size() + LDR_SIZE + 1, LDR_SIZE + (int)sample_points.size(), CV_32F);
103             Mat B = Mat::zeros(A.rows, 1, CV_32F);
104 
105             int eq = 0;
106             for(size_t i = 0; i < sample_points.size(); i++) {
107                 for(size_t j = 0; j < images.size(); j++) {
108 
109                     int val = images[j].ptr()[3*(sample_points[i].y * images[j].cols + sample_points[i].x) + channel];
110                     A.at<float>(eq, val) = w.at<float>(val);
111                     A.at<float>(eq, LDR_SIZE + (int)i) = -w.at<float>(val);
112                     B.at<float>(eq, 0) = w.at<float>(val) * log(times.at<float>((int)j));
113                     eq++;
114                 }
115             }
116             A.at<float>(eq, LDR_SIZE / 2) = 1;
117             eq++;
118 
119             for(int i = 0; i < 254; i++) {
120                 A.at<float>(eq, i) = lambda * w.at<float>(i + 1);
121                 A.at<float>(eq, i + 1) = -2 * lambda * w.at<float>(i + 1);
122                 A.at<float>(eq, i + 2) = lambda * w.at<float>(i + 1);
123                 eq++;
124             }
125             Mat solution;
126             solve(A, B, solution, DECOMP_SVD);
127             solution.rowRange(0, LDR_SIZE).copyTo(result_split[channel]);
128         }
129         merge(result_split, result);
130         exp(result, result);
131     }
132 
getSamples() const133     int getSamples() const { return samples; }
setSamples(int val)134     void setSamples(int val) { samples = val; }
135 
getLambda() const136     float getLambda() const { return lambda; }
setLambda(float val)137     void setLambda(float val) { lambda = val; }
138 
getRandom() const139     bool getRandom() const { return random; }
setRandom(bool val)140     void setRandom(bool val) { random = val; }
141 
write(FileStorage & fs) const142     void write(FileStorage& fs) const
143     {
144         fs << "name" << name
145            << "samples" << samples
146            << "lambda" << lambda
147            << "random" << static_cast<int>(random);
148     }
149 
read(const FileNode & fn)150     void read(const FileNode& fn)
151     {
152         FileNode n = fn["name"];
153         CV_Assert(n.isString() && String(n) == name);
154         samples = fn["samples"];
155         lambda = fn["lambda"];
156         int random_val = fn["random"];
157         random = (random_val != 0);
158     }
159 
160 protected:
161     String name;
162     int samples;
163     float lambda;
164     bool random;
165     Mat w;
166 };
167 
createCalibrateDebevec(int samples,float lambda,bool random)168 Ptr<CalibrateDebevec> createCalibrateDebevec(int samples, float lambda, bool random)
169 {
170     return makePtr<CalibrateDebevecImpl>(samples, lambda, random);
171 }
172 
173 class CalibrateRobertsonImpl : public CalibrateRobertson
174 {
175 public:
CalibrateRobertsonImpl(int _max_iter,float _threshold)176     CalibrateRobertsonImpl(int _max_iter, float _threshold) :
177         name("CalibrateRobertson"),
178         max_iter(_max_iter),
179         threshold(_threshold),
180         weight(RobertsonWeights())
181     {
182     }
183 
process(InputArrayOfArrays src,OutputArray dst,InputArray _times)184     void process(InputArrayOfArrays src, OutputArray dst, InputArray _times)
185     {
186         std::vector<Mat> images;
187         src.getMatVector(images);
188         Mat times = _times.getMat();
189 
190         CV_Assert(images.size() == times.total());
191         checkImageDimensions(images);
192         CV_Assert(images[0].depth() == CV_8U);
193 
194         int channels = images[0].channels();
195         int CV_32FCC = CV_MAKETYPE(CV_32F, channels);
196 
197         dst.create(LDR_SIZE, 1, CV_32FCC);
198         Mat response = dst.getMat();
199         response = linearResponse(3) / (LDR_SIZE / 2.0f);
200 
201         Mat card = Mat::zeros(LDR_SIZE, 1, CV_32FCC);
202         for(size_t i = 0; i < images.size(); i++) {
203            uchar *ptr = images[i].ptr();
204            for(size_t pos = 0; pos < images[i].total(); pos++) {
205                for(int c = 0; c < channels; c++, ptr++) {
206                    card.at<Vec3f>(*ptr)[c] += 1;
207                }
208            }
209         }
210         card = 1.0 / card;
211 
212         Ptr<MergeRobertson> merge = createMergeRobertson();
213         for(int iter = 0; iter < max_iter; iter++) {
214 
215             radiance = Mat::zeros(images[0].size(), CV_32FCC);
216             merge->process(images, radiance, times, response);
217 
218             Mat new_response = Mat::zeros(LDR_SIZE, 1, CV_32FC3);
219             for(size_t i = 0; i < images.size(); i++) {
220                 uchar *ptr = images[i].ptr();
221                 float* rad_ptr = radiance.ptr<float>();
222                 for(size_t pos = 0; pos < images[i].total(); pos++) {
223                     for(int c = 0; c < channels; c++, ptr++, rad_ptr++) {
224                         new_response.at<Vec3f>(*ptr)[c] += times.at<float>((int)i) * *rad_ptr;
225                     }
226                 }
227             }
228             new_response = new_response.mul(card);
229             for(int c = 0; c < 3; c++) {
230                 float middle = new_response.at<Vec3f>(LDR_SIZE / 2)[c];
231                 for(int i = 0; i < LDR_SIZE; i++) {
232                     new_response.at<Vec3f>(i)[c] /= middle;
233                 }
234             }
235             float diff = static_cast<float>(sum(sum(abs(new_response - response)))[0] / channels);
236             new_response.copyTo(response);
237             if(diff < threshold) {
238                 break;
239             }
240         }
241     }
242 
getMaxIter() const243     int getMaxIter() const { return max_iter; }
setMaxIter(int val)244     void setMaxIter(int val) { max_iter = val; }
245 
getThreshold() const246     float getThreshold() const { return threshold; }
setThreshold(float val)247     void setThreshold(float val) { threshold = val; }
248 
getRadiance() const249     Mat getRadiance() const { return radiance; }
250 
write(FileStorage & fs) const251     void write(FileStorage& fs) const
252     {
253         fs << "name" << name
254            << "max_iter" << max_iter
255            << "threshold" << threshold;
256     }
257 
read(const FileNode & fn)258     void read(const FileNode& fn)
259     {
260         FileNode n = fn["name"];
261         CV_Assert(n.isString() && String(n) == name);
262         max_iter = fn["max_iter"];
263         threshold = fn["threshold"];
264     }
265 
266 protected:
267     String name;
268     int max_iter;
269     float threshold;
270     Mat weight, radiance;
271 };
272 
createCalibrateRobertson(int max_iter,float threshold)273 Ptr<CalibrateRobertson> createCalibrateRobertson(int max_iter, float threshold)
274 {
275     return makePtr<CalibrateRobertsonImpl>(max_iter, threshold);
276 }
277 
278 }
279