~paparazzi-uav/paparazzi/v5.0-manual

« back to all changes in this revision

Viewing changes to sw/ext/opencv_bebop/opencv/modules/photo/src/merge.cpp

  • Committer: Paparazzi buildbot
  • Date: 2016-05-18 15:00:29 UTC
  • Revision ID: felix.ruess+docbot@gmail.com-20160518150029-e8lgzi5kvb4p7un9
Manual import commit 4b8bbb730080dac23cf816b98908dacfabe2a8ec from v5.0 branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 "precomp.hpp"
 
43
#include "opencv2/photo.hpp"
 
44
#include "opencv2/imgproc.hpp"
 
45
#include "hdr_common.hpp"
 
46
 
 
47
namespace cv
 
48
{
 
49
 
 
50
class MergeDebevecImpl : public MergeDebevec
 
51
{
 
52
public:
 
53
    MergeDebevecImpl() :
 
54
        name("MergeDebevec"),
 
55
        weights(tringleWeights())
 
56
    {
 
57
    }
 
58
 
 
59
    void process(InputArrayOfArrays src, OutputArray dst, InputArray _times, InputArray input_response)
 
60
    {
 
61
        std::vector<Mat> images;
 
62
        src.getMatVector(images);
 
63
        Mat times = _times.getMat();
 
64
 
 
65
        CV_Assert(images.size() == times.total());
 
66
        checkImageDimensions(images);
 
67
        CV_Assert(images[0].depth() == CV_8U);
 
68
 
 
69
        int channels = images[0].channels();
 
70
        Size size = images[0].size();
 
71
        int CV_32FCC = CV_MAKETYPE(CV_32F, channels);
 
72
 
 
73
        dst.create(images[0].size(), CV_32FCC);
 
74
        Mat result = dst.getMat();
 
75
 
 
76
        Mat response = input_response.getMat();
 
77
 
 
78
        if(response.empty()) {
 
79
            response = linearResponse(channels);
 
80
            response.at<Vec3f>(0) = response.at<Vec3f>(1);
 
81
        }
 
82
 
 
83
        Mat log_response;
 
84
        log(response, log_response);
 
85
        CV_Assert(log_response.rows == LDR_SIZE && log_response.cols == 1 &&
 
86
                  log_response.channels() == channels);
 
87
 
 
88
        Mat exp_values(times);
 
89
        log(exp_values, exp_values);
 
90
 
 
91
        result = Mat::zeros(size, CV_32FCC);
 
92
        std::vector<Mat> result_split;
 
93
        split(result, result_split);
 
94
        Mat weight_sum = Mat::zeros(size, CV_32F);
 
95
 
 
96
        for(size_t i = 0; i < images.size(); i++) {
 
97
            std::vector<Mat> splitted;
 
98
            split(images[i], splitted);
 
99
 
 
100
            Mat w = Mat::zeros(size, CV_32F);
 
101
            for(int c = 0; c < channels; c++) {
 
102
                LUT(splitted[c], weights, splitted[c]);
 
103
                w += splitted[c];
 
104
            }
 
105
            w /= channels;
 
106
 
 
107
            Mat response_img;
 
108
            LUT(images[i], log_response, response_img);
 
109
            split(response_img, splitted);
 
110
            for(int c = 0; c < channels; c++) {
 
111
                result_split[c] += w.mul(splitted[c] - exp_values.at<float>((int)i));
 
112
            }
 
113
            weight_sum += w;
 
114
        }
 
115
        weight_sum = 1.0f / weight_sum;
 
116
        for(int c = 0; c < channels; c++) {
 
117
            result_split[c] = result_split[c].mul(weight_sum);
 
118
        }
 
119
        merge(result_split, result);
 
120
        exp(result, result);
 
121
    }
 
122
 
 
123
    void process(InputArrayOfArrays src, OutputArray dst, InputArray times)
 
124
    {
 
125
        process(src, dst, times, Mat());
 
126
    }
 
127
 
 
128
protected:
 
129
    String name;
 
130
    Mat weights;
 
131
};
 
132
 
 
133
Ptr<MergeDebevec> createMergeDebevec()
 
134
{
 
135
    return makePtr<MergeDebevecImpl>();
 
136
}
 
137
 
 
138
class MergeMertensImpl : public MergeMertens
 
139
{
 
140
public:
 
141
    MergeMertensImpl(float _wcon, float _wsat, float _wexp) :
 
142
        name("MergeMertens"),
 
143
        wcon(_wcon),
 
144
        wsat(_wsat),
 
145
        wexp(_wexp)
 
146
    {
 
147
    }
 
148
 
 
149
    void process(InputArrayOfArrays src, OutputArrayOfArrays dst, InputArray, InputArray)
 
150
    {
 
151
        process(src, dst);
 
152
    }
 
153
 
 
154
    void process(InputArrayOfArrays src, OutputArray dst)
 
155
    {
 
156
        std::vector<Mat> images;
 
157
        src.getMatVector(images);
 
158
        checkImageDimensions(images);
 
159
 
 
160
        int channels = images[0].channels();
 
161
        CV_Assert(channels == 1 || channels == 3);
 
162
        Size size = images[0].size();
 
163
        int CV_32FCC = CV_MAKETYPE(CV_32F, channels);
 
164
 
 
165
        std::vector<Mat> weights(images.size());
 
166
        Mat weight_sum = Mat::zeros(size, CV_32F);
 
167
 
 
168
        for(size_t i = 0; i < images.size(); i++) {
 
169
            Mat img, gray, contrast, saturation, wellexp;
 
170
            std::vector<Mat> splitted(channels);
 
171
 
 
172
            images[i].convertTo(img, CV_32F, 1.0f/255.0f);
 
173
            if(channels == 3) {
 
174
                cvtColor(img, gray, COLOR_RGB2GRAY);
 
175
            } else {
 
176
                img.copyTo(gray);
 
177
            }
 
178
            split(img, splitted);
 
179
 
 
180
            Laplacian(gray, contrast, CV_32F);
 
181
            contrast = abs(contrast);
 
182
 
 
183
            Mat mean = Mat::zeros(size, CV_32F);
 
184
            for(int c = 0; c < channels; c++) {
 
185
                mean += splitted[c];
 
186
            }
 
187
            mean /= channels;
 
188
 
 
189
            saturation = Mat::zeros(size, CV_32F);
 
190
            for(int c = 0; c < channels;  c++) {
 
191
                Mat deviation = splitted[c] - mean;
 
192
                pow(deviation, 2.0f, deviation);
 
193
                saturation += deviation;
 
194
            }
 
195
            sqrt(saturation, saturation);
 
196
 
 
197
            wellexp = Mat::ones(size, CV_32F);
 
198
            for(int c = 0; c < channels; c++) {
 
199
                Mat expo = splitted[c] - 0.5f;
 
200
                pow(expo, 2.0f, expo);
 
201
                expo = -expo / 0.08f;
 
202
                exp(expo, expo);
 
203
                wellexp = wellexp.mul(expo);
 
204
            }
 
205
 
 
206
            pow(contrast, wcon, contrast);
 
207
            pow(saturation, wsat, saturation);
 
208
            pow(wellexp, wexp, wellexp);
 
209
 
 
210
            weights[i] = contrast;
 
211
            if(channels == 3) {
 
212
                weights[i] = weights[i].mul(saturation);
 
213
            }
 
214
            weights[i] = weights[i].mul(wellexp) + 1e-12f;
 
215
            weight_sum += weights[i];
 
216
        }
 
217
        int maxlevel = static_cast<int>(logf(static_cast<float>(min(size.width, size.height))) / logf(2.0f));
 
218
        std::vector<Mat> res_pyr(maxlevel + 1);
 
219
 
 
220
        for(size_t i = 0; i < images.size(); i++) {
 
221
            weights[i] /= weight_sum;
 
222
            Mat img;
 
223
            images[i].convertTo(img, CV_32F, 1.0f/255.0f);
 
224
 
 
225
            std::vector<Mat> img_pyr, weight_pyr;
 
226
            buildPyramid(img, img_pyr, maxlevel);
 
227
            buildPyramid(weights[i], weight_pyr, maxlevel);
 
228
 
 
229
            for(int lvl = 0; lvl < maxlevel; lvl++) {
 
230
                Mat up;
 
231
                pyrUp(img_pyr[lvl + 1], up, img_pyr[lvl].size());
 
232
                img_pyr[lvl] -= up;
 
233
            }
 
234
            for(int lvl = 0; lvl <= maxlevel; lvl++) {
 
235
                std::vector<Mat> splitted(channels);
 
236
                split(img_pyr[lvl], splitted);
 
237
                for(int c = 0; c < channels; c++) {
 
238
                    splitted[c] = splitted[c].mul(weight_pyr[lvl]);
 
239
                }
 
240
                merge(splitted, img_pyr[lvl]);
 
241
                if(res_pyr[lvl].empty()) {
 
242
                    res_pyr[lvl] = img_pyr[lvl];
 
243
                } else {
 
244
                    res_pyr[lvl] += img_pyr[lvl];
 
245
                }
 
246
            }
 
247
        }
 
248
        for(int lvl = maxlevel; lvl > 0; lvl--) {
 
249
            Mat up;
 
250
            pyrUp(res_pyr[lvl], up, res_pyr[lvl - 1].size());
 
251
            res_pyr[lvl - 1] += up;
 
252
        }
 
253
        dst.create(size, CV_32FCC);
 
254
        res_pyr[0].copyTo(dst.getMat());
 
255
    }
 
256
 
 
257
    float getContrastWeight() const { return wcon; }
 
258
    void setContrastWeight(float val) { wcon = val; }
 
259
 
 
260
    float getSaturationWeight() const { return wsat; }
 
261
    void setSaturationWeight(float val) { wsat = val; }
 
262
 
 
263
    float getExposureWeight() const { return wexp; }
 
264
    void setExposureWeight(float val) { wexp = val; }
 
265
 
 
266
    void write(FileStorage& fs) const
 
267
    {
 
268
        fs << "name" << name
 
269
           << "contrast_weight" << wcon
 
270
           << "saturation_weight" << wsat
 
271
           << "exposure_weight" << wexp;
 
272
    }
 
273
 
 
274
    void read(const FileNode& fn)
 
275
    {
 
276
        FileNode n = fn["name"];
 
277
        CV_Assert(n.isString() && String(n) == name);
 
278
        wcon = fn["contrast_weight"];
 
279
        wsat = fn["saturation_weight"];
 
280
        wexp = fn["exposure_weight"];
 
281
    }
 
282
 
 
283
protected:
 
284
    String name;
 
285
    float wcon, wsat, wexp;
 
286
};
 
287
 
 
288
Ptr<MergeMertens> createMergeMertens(float wcon, float wsat, float wexp)
 
289
{
 
290
    return makePtr<MergeMertensImpl>(wcon, wsat, wexp);
 
291
}
 
292
 
 
293
class MergeRobertsonImpl : public MergeRobertson
 
294
{
 
295
public:
 
296
    MergeRobertsonImpl() :
 
297
        name("MergeRobertson"),
 
298
        weight(RobertsonWeights())
 
299
    {
 
300
    }
 
301
 
 
302
    void process(InputArrayOfArrays src, OutputArray dst, InputArray _times, InputArray input_response)
 
303
    {
 
304
        std::vector<Mat> images;
 
305
        src.getMatVector(images);
 
306
        Mat times = _times.getMat();
 
307
 
 
308
        CV_Assert(images.size() == times.total());
 
309
        checkImageDimensions(images);
 
310
        CV_Assert(images[0].depth() == CV_8U);
 
311
 
 
312
        int channels = images[0].channels();
 
313
        int CV_32FCC = CV_MAKETYPE(CV_32F, channels);
 
314
 
 
315
        dst.create(images[0].size(), CV_32FCC);
 
316
        Mat result = dst.getMat();
 
317
 
 
318
        Mat response = input_response.getMat();
 
319
        if(response.empty()) {
 
320
            float middle = LDR_SIZE / 2.0f;
 
321
            response = linearResponse(channels) / middle;
 
322
        }
 
323
        CV_Assert(response.rows == LDR_SIZE && response.cols == 1 &&
 
324
                  response.channels() == channels);
 
325
 
 
326
        result = Mat::zeros(images[0].size(), CV_32FCC);
 
327
        Mat wsum = Mat::zeros(images[0].size(), CV_32FCC);
 
328
        for(size_t i = 0; i < images.size(); i++) {
 
329
            Mat im, w;
 
330
            LUT(images[i], weight, w);
 
331
            LUT(images[i], response, im);
 
332
 
 
333
            result += times.at<float>((int)i) * w.mul(im);
 
334
            wsum += times.at<float>((int)i) * times.at<float>((int)i) * w;
 
335
        }
 
336
        result = result.mul(1 / wsum);
 
337
    }
 
338
 
 
339
    void process(InputArrayOfArrays src, OutputArray dst, InputArray times)
 
340
    {
 
341
        process(src, dst, times, Mat());
 
342
    }
 
343
 
 
344
protected:
 
345
    String name;
 
346
    Mat weight;
 
347
};
 
348
 
 
349
Ptr<MergeRobertson> createMergeRobertson()
 
350
{
 
351
    return makePtr<MergeRobertsonImpl>();
 
352
}
 
353
 
 
354
}