Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/superres/src/btv_l1.cpp
16344 views
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
// S. Farsiu , D. Robinson, M. Elad, P. Milanfar. Fast and robust multiframe super resolution.
44
// Dennis Mitzel, Thomas Pock, Thomas Schoenemann, Daniel Cremers. Video Super Resolution using Duality Based TV-L1 Optical Flow.
45
46
#include "precomp.hpp"
47
#include "opencl_kernels_superres.hpp"
48
49
using namespace cv;
50
using namespace cv::superres;
51
using namespace cv::superres::detail;
52
53
namespace
54
{
55
#ifdef HAVE_OPENCL
56
57
bool ocl_calcRelativeMotions(InputArrayOfArrays _forwardMotions, InputArrayOfArrays _backwardMotions,
58
OutputArrayOfArrays _relForwardMotions, OutputArrayOfArrays _relBackwardMotions,
59
int baseIdx, const Size & size)
60
{
61
std::vector<UMat> & forwardMotions = *(std::vector<UMat> *)_forwardMotions.getObj(),
62
& backwardMotions = *(std::vector<UMat> *)_backwardMotions.getObj(),
63
& relForwardMotions = *(std::vector<UMat> *)_relForwardMotions.getObj(),
64
& relBackwardMotions = *(std::vector<UMat> *)_relBackwardMotions.getObj();
65
66
const int count = static_cast<int>(forwardMotions.size());
67
68
relForwardMotions.resize(count);
69
relForwardMotions[baseIdx].create(size, CV_32FC2);
70
relForwardMotions[baseIdx].setTo(Scalar::all(0));
71
72
relBackwardMotions.resize(count);
73
relBackwardMotions[baseIdx].create(size, CV_32FC2);
74
relBackwardMotions[baseIdx].setTo(Scalar::all(0));
75
76
for (int i = baseIdx - 1; i >= 0; --i)
77
{
78
add(relForwardMotions[i + 1], forwardMotions[i], relForwardMotions[i]);
79
add(relBackwardMotions[i + 1], backwardMotions[i + 1], relBackwardMotions[i]);
80
}
81
82
for (int i = baseIdx + 1; i < count; ++i)
83
{
84
add(relForwardMotions[i - 1], backwardMotions[i], relForwardMotions[i]);
85
add(relBackwardMotions[i - 1], forwardMotions[i - 1], relBackwardMotions[i]);
86
}
87
88
return true;
89
}
90
91
#endif
92
93
void calcRelativeMotions(InputArrayOfArrays _forwardMotions, InputArrayOfArrays _backwardMotions,
94
OutputArrayOfArrays _relForwardMotions, OutputArrayOfArrays _relBackwardMotions,
95
int baseIdx, const Size & size)
96
{
97
CV_OCL_RUN(_forwardMotions.isUMatVector() && _backwardMotions.isUMatVector() &&
98
_relForwardMotions.isUMatVector() && _relBackwardMotions.isUMatVector(),
99
ocl_calcRelativeMotions(_forwardMotions, _backwardMotions, _relForwardMotions,
100
_relBackwardMotions, baseIdx, size))
101
102
std::vector<Mat> & forwardMotions = *(std::vector<Mat> *)_forwardMotions.getObj(),
103
& backwardMotions = *(std::vector<Mat> *)_backwardMotions.getObj(),
104
& relForwardMotions = *(std::vector<Mat> *)_relForwardMotions.getObj(),
105
& relBackwardMotions = *(std::vector<Mat> *)_relBackwardMotions.getObj();
106
107
const int count = static_cast<int>(forwardMotions.size());
108
109
relForwardMotions.resize(count);
110
relForwardMotions[baseIdx].create(size, CV_32FC2);
111
relForwardMotions[baseIdx].setTo(Scalar::all(0));
112
113
relBackwardMotions.resize(count);
114
relBackwardMotions[baseIdx].create(size, CV_32FC2);
115
relBackwardMotions[baseIdx].setTo(Scalar::all(0));
116
117
for (int i = baseIdx - 1; i >= 0; --i)
118
{
119
add(relForwardMotions[i + 1], forwardMotions[i], relForwardMotions[i]);
120
add(relBackwardMotions[i + 1], backwardMotions[i + 1], relBackwardMotions[i]);
121
}
122
123
for (int i = baseIdx + 1; i < count; ++i)
124
{
125
add(relForwardMotions[i - 1], backwardMotions[i], relForwardMotions[i]);
126
add(relBackwardMotions[i - 1], forwardMotions[i - 1], relBackwardMotions[i]);
127
}
128
}
129
#ifdef HAVE_OPENCL
130
131
bool ocl_upscaleMotions(InputArrayOfArrays _lowResMotions, OutputArrayOfArrays _highResMotions, int scale)
132
{
133
std::vector<UMat> & lowResMotions = *(std::vector<UMat> *)_lowResMotions.getObj(),
134
& highResMotions = *(std::vector<UMat> *)_highResMotions.getObj();
135
136
highResMotions.resize(lowResMotions.size());
137
138
for (size_t i = 0; i < lowResMotions.size(); ++i)
139
{
140
resize(lowResMotions[i], highResMotions[i], Size(), scale, scale, INTER_LINEAR); // TODO
141
multiply(highResMotions[i], Scalar::all(scale), highResMotions[i]);
142
}
143
144
return true;
145
}
146
147
#endif
148
149
void upscaleMotions(InputArrayOfArrays _lowResMotions, OutputArrayOfArrays _highResMotions, int scale)
150
{
151
CV_OCL_RUN(_lowResMotions.isUMatVector() && _highResMotions.isUMatVector(),
152
ocl_upscaleMotions(_lowResMotions, _highResMotions, scale))
153
154
std::vector<Mat> & lowResMotions = *(std::vector<Mat> *)_lowResMotions.getObj(),
155
& highResMotions = *(std::vector<Mat> *)_highResMotions.getObj();
156
157
highResMotions.resize(lowResMotions.size());
158
159
for (size_t i = 0; i < lowResMotions.size(); ++i)
160
{
161
resize(lowResMotions[i], highResMotions[i], Size(), scale, scale, INTER_CUBIC);
162
multiply(highResMotions[i], Scalar::all(scale), highResMotions[i]);
163
}
164
}
165
166
#ifdef HAVE_OPENCL
167
168
bool ocl_buildMotionMaps(InputArray _forwardMotion, InputArray _backwardMotion,
169
OutputArray _forwardMap, OutputArray _backwardMap)
170
{
171
ocl::Kernel k("buildMotionMaps", ocl::superres::superres_btvl1_oclsrc);
172
if (k.empty())
173
return false;
174
175
UMat forwardMotion = _forwardMotion.getUMat(), backwardMotion = _backwardMotion.getUMat();
176
Size size = forwardMotion.size();
177
178
_forwardMap.create(size, CV_32FC2);
179
_backwardMap.create(size, CV_32FC2);
180
181
UMat forwardMap = _forwardMap.getUMat(), backwardMap = _backwardMap.getUMat();
182
183
k.args(ocl::KernelArg::ReadOnlyNoSize(forwardMotion),
184
ocl::KernelArg::ReadOnlyNoSize(backwardMotion),
185
ocl::KernelArg::WriteOnlyNoSize(forwardMap),
186
ocl::KernelArg::WriteOnly(backwardMap));
187
188
size_t globalsize[2] = { (size_t)size.width, (size_t)size.height };
189
return k.run(2, globalsize, NULL, false);
190
}
191
192
#endif
193
194
void buildMotionMaps(InputArray _forwardMotion, InputArray _backwardMotion,
195
OutputArray _forwardMap, OutputArray _backwardMap)
196
{
197
CV_OCL_RUN(_forwardMap.isUMat() && _backwardMap.isUMat(),
198
ocl_buildMotionMaps(_forwardMotion, _backwardMotion, _forwardMap,
199
_backwardMap));
200
201
Mat forwardMotion = _forwardMotion.getMat(), backwardMotion = _backwardMotion.getMat();
202
203
_forwardMap.create(forwardMotion.size(), CV_32FC2);
204
_backwardMap.create(forwardMotion.size(), CV_32FC2);
205
206
Mat forwardMap = _forwardMap.getMat(), backwardMap = _backwardMap.getMat();
207
208
for (int y = 0; y < forwardMotion.rows; ++y)
209
{
210
const Point2f* forwardMotionRow = forwardMotion.ptr<Point2f>(y);
211
const Point2f* backwardMotionRow = backwardMotion.ptr<Point2f>(y);
212
Point2f* forwardMapRow = forwardMap.ptr<Point2f>(y);
213
Point2f* backwardMapRow = backwardMap.ptr<Point2f>(y);
214
215
for (int x = 0; x < forwardMotion.cols; ++x)
216
{
217
Point2f base(static_cast<float>(x), static_cast<float>(y));
218
219
forwardMapRow[x] = base + backwardMotionRow[x];
220
backwardMapRow[x] = base + forwardMotionRow[x];
221
}
222
}
223
}
224
225
template <typename T>
226
void upscaleImpl(InputArray _src, OutputArray _dst, int scale)
227
{
228
Mat src = _src.getMat();
229
_dst.create(src.rows * scale, src.cols * scale, src.type());
230
_dst.setTo(Scalar::all(0));
231
Mat dst = _dst.getMat();
232
233
for (int y = 0, Y = 0; y < src.rows; ++y, Y += scale)
234
{
235
const T * const srcRow = src.ptr<T>(y);
236
T * const dstRow = dst.ptr<T>(Y);
237
238
for (int x = 0, X = 0; x < src.cols; ++x, X += scale)
239
dstRow[X] = srcRow[x];
240
}
241
}
242
243
#ifdef HAVE_OPENCL
244
245
static bool ocl_upscale(InputArray _src, OutputArray _dst, int scale)
246
{
247
int type = _src.type(), cn = CV_MAT_CN(type);
248
ocl::Kernel k("upscale", ocl::superres::superres_btvl1_oclsrc,
249
format("-D cn=%d", cn));
250
if (k.empty())
251
return false;
252
253
UMat src = _src.getUMat();
254
_dst.create(src.rows * scale, src.cols * scale, type);
255
_dst.setTo(Scalar::all(0));
256
UMat dst = _dst.getUMat();
257
258
k.args(ocl::KernelArg::ReadOnly(src),
259
ocl::KernelArg::ReadWriteNoSize(dst), scale);
260
261
size_t globalsize[2] = { (size_t)src.cols, (size_t)src.rows };
262
return k.run(2, globalsize, NULL, false);
263
}
264
265
#endif
266
267
typedef struct _Point4f { float ar[4]; } Point4f;
268
269
void upscale(InputArray _src, OutputArray _dst, int scale)
270
{
271
int cn = _src.channels();
272
CV_Assert( cn == 1 || cn == 3 || cn == 4 );
273
274
CV_OCL_RUN(_dst.isUMat(),
275
ocl_upscale(_src, _dst, scale))
276
277
typedef void (*func_t)(InputArray src, OutputArray dst, int scale);
278
static const func_t funcs[] =
279
{
280
0, upscaleImpl<float>, 0, upscaleImpl<Point3f>, upscaleImpl<Point4f>
281
};
282
283
const func_t func = funcs[cn];
284
CV_Assert(func != 0);
285
func(_src, _dst, scale);
286
}
287
288
inline float diffSign(float a, float b)
289
{
290
return a > b ? 1.0f : a < b ? -1.0f : 0.0f;
291
}
292
293
Point3f diffSign(Point3f a, Point3f b)
294
{
295
return Point3f(
296
a.x > b.x ? 1.0f : a.x < b.x ? -1.0f : 0.0f,
297
a.y > b.y ? 1.0f : a.y < b.y ? -1.0f : 0.0f,
298
a.z > b.z ? 1.0f : a.z < b.z ? -1.0f : 0.0f
299
);
300
}
301
302
#ifdef HAVE_OPENCL
303
304
static bool ocl_diffSign(InputArray _src1, OutputArray _src2, OutputArray _dst)
305
{
306
ocl::Kernel k("diffSign", ocl::superres::superres_btvl1_oclsrc);
307
if (k.empty())
308
return false;
309
310
UMat src1 = _src1.getUMat(), src2 = _src2.getUMat();
311
_dst.create(src1.size(), src1.type());
312
UMat dst = _dst.getUMat();
313
314
int cn = src1.channels();
315
k.args(ocl::KernelArg::ReadOnlyNoSize(src1),
316
ocl::KernelArg::ReadOnlyNoSize(src2),
317
ocl::KernelArg::WriteOnly(dst, cn));
318
319
size_t globalsize[2] = { (size_t)src1.cols * cn, (size_t)src1.rows };
320
return k.run(2, globalsize, NULL, false);
321
}
322
323
#endif
324
325
void diffSign(InputArray _src1, OutputArray _src2, OutputArray _dst)
326
{
327
CV_OCL_RUN(_dst.isUMat(),
328
ocl_diffSign(_src1, _src2, _dst))
329
330
Mat src1 = _src1.getMat(), src2 = _src2.getMat();
331
_dst.create(src1.size(), src1.type());
332
Mat dst = _dst.getMat();
333
334
const int count = src1.cols * src1.channels();
335
336
for (int y = 0; y < src1.rows; ++y)
337
{
338
const float * const src1Ptr = src1.ptr<float>(y);
339
const float * const src2Ptr = src2.ptr<float>(y);
340
float* dstPtr = dst.ptr<float>(y);
341
342
for (int x = 0; x < count; ++x)
343
dstPtr[x] = diffSign(src1Ptr[x], src2Ptr[x]);
344
}
345
}
346
347
void calcBtvWeights(int btvKernelSize, double alpha, std::vector<float>& btvWeights)
348
{
349
const size_t size = btvKernelSize * btvKernelSize;
350
351
btvWeights.resize(size);
352
353
const int ksize = (btvKernelSize - 1) / 2;
354
const float alpha_f = static_cast<float>(alpha);
355
356
for (int m = 0, ind = 0; m <= ksize; ++m)
357
{
358
for (int l = ksize; l + m >= 0; --l, ++ind)
359
btvWeights[ind] = pow(alpha_f, std::abs(m) + std::abs(l));
360
}
361
}
362
363
template <typename T>
364
struct BtvRegularizationBody : ParallelLoopBody
365
{
366
void operator ()(const Range& range) const CV_OVERRIDE;
367
368
Mat src;
369
mutable Mat dst;
370
int ksize;
371
const float* btvWeights;
372
};
373
374
template <typename T>
375
void BtvRegularizationBody<T>::operator ()(const Range& range) const
376
{
377
for (int i = range.start; i < range.end; ++i)
378
{
379
const T * const srcRow = src.ptr<T>(i);
380
T * const dstRow = dst.ptr<T>(i);
381
382
for(int j = ksize; j < src.cols - ksize; ++j)
383
{
384
const T srcVal = srcRow[j];
385
386
for (int m = 0, ind = 0; m <= ksize; ++m)
387
{
388
const T* srcRow2 = src.ptr<T>(i - m);
389
const T* srcRow3 = src.ptr<T>(i + m);
390
391
for (int l = ksize; l + m >= 0; --l, ++ind)
392
dstRow[j] += btvWeights[ind] * (diffSign(srcVal, srcRow3[j + l])
393
- diffSign(srcRow2[j - l], srcVal));
394
}
395
}
396
}
397
}
398
399
template <typename T>
400
void calcBtvRegularizationImpl(InputArray _src, OutputArray _dst, int btvKernelSize, const std::vector<float>& btvWeights)
401
{
402
Mat src = _src.getMat();
403
_dst.create(src.size(), src.type());
404
_dst.setTo(Scalar::all(0));
405
Mat dst = _dst.getMat();
406
407
const int ksize = (btvKernelSize - 1) / 2;
408
409
BtvRegularizationBody<T> body;
410
411
body.src = src;
412
body.dst = dst;
413
body.ksize = ksize;
414
body.btvWeights = &btvWeights[0];
415
416
parallel_for_(Range(ksize, src.rows - ksize), body);
417
}
418
419
#ifdef HAVE_OPENCL
420
421
static bool ocl_calcBtvRegularization(InputArray _src, OutputArray _dst, int btvKernelSize, const UMat & ubtvWeights)
422
{
423
int cn = _src.channels();
424
ocl::Kernel k("calcBtvRegularization", ocl::superres::superres_btvl1_oclsrc,
425
format("-D cn=%d", cn));
426
if (k.empty())
427
return false;
428
429
UMat src = _src.getUMat();
430
_dst.create(src.size(), src.type());
431
_dst.setTo(Scalar::all(0));
432
UMat dst = _dst.getUMat();
433
434
const int ksize = (btvKernelSize - 1) / 2;
435
436
k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnly(dst),
437
ksize, ocl::KernelArg::PtrReadOnly(ubtvWeights));
438
439
size_t globalsize[2] = { (size_t)src.cols, (size_t)src.rows };
440
return k.run(2, globalsize, NULL, false);
441
}
442
443
#endif
444
445
void calcBtvRegularization(InputArray _src, OutputArray _dst, int btvKernelSize,
446
const std::vector<float>& btvWeights, const UMat & ubtvWeights)
447
{
448
CV_OCL_RUN(_dst.isUMat(),
449
ocl_calcBtvRegularization(_src, _dst, btvKernelSize, ubtvWeights))
450
CV_UNUSED(ubtvWeights);
451
if (_src.channels() == 1)
452
{
453
calcBtvRegularizationImpl<float>(_src, _dst, btvKernelSize, btvWeights);
454
}
455
else if (_src.channels() == 3)
456
{
457
calcBtvRegularizationImpl<Point3f>(_src, _dst, btvKernelSize, btvWeights);
458
}
459
else
460
{
461
CV_Error(Error::StsBadArg, "Unsupported number of channels in _src");
462
}
463
}
464
465
class BTVL1_Base : public cv::superres::SuperResolution
466
{
467
public:
468
BTVL1_Base();
469
470
void process(InputArrayOfArrays src, OutputArray dst, InputArrayOfArrays forwardMotions,
471
InputArrayOfArrays backwardMotions, int baseIdx);
472
473
void collectGarbage() CV_OVERRIDE;
474
475
inline int getScale() const CV_OVERRIDE { return scale_; }
476
inline void setScale(int val) CV_OVERRIDE { scale_ = val; }
477
inline int getIterations() const CV_OVERRIDE { return iterations_; }
478
inline void setIterations(int val) CV_OVERRIDE { iterations_ = val; }
479
inline double getTau() const CV_OVERRIDE { return tau_; }
480
inline void setTau(double val) CV_OVERRIDE { tau_ = val; }
481
inline double getLabmda() const CV_OVERRIDE { return lambda_; }
482
inline void setLabmda(double val) CV_OVERRIDE { lambda_ = val; }
483
inline double getAlpha() const CV_OVERRIDE { return alpha_; }
484
inline void setAlpha(double val) CV_OVERRIDE { alpha_ = val; }
485
inline int getKernelSize() const CV_OVERRIDE { return btvKernelSize_; }
486
inline void setKernelSize(int val) CV_OVERRIDE { btvKernelSize_ = val; }
487
inline int getBlurKernelSize() const CV_OVERRIDE { return blurKernelSize_; }
488
inline void setBlurKernelSize(int val) CV_OVERRIDE { blurKernelSize_ = val; }
489
inline double getBlurSigma() const CV_OVERRIDE { return blurSigma_; }
490
inline void setBlurSigma(double val) CV_OVERRIDE { blurSigma_ = val; }
491
inline int getTemporalAreaRadius() const CV_OVERRIDE { return temporalAreaRadius_; }
492
inline void setTemporalAreaRadius(int val) CV_OVERRIDE { temporalAreaRadius_ = val; }
493
inline Ptr<cv::superres::DenseOpticalFlowExt> getOpticalFlow() const CV_OVERRIDE { return opticalFlow_; }
494
inline void setOpticalFlow(const Ptr<cv::superres::DenseOpticalFlowExt>& val) CV_OVERRIDE { opticalFlow_ = val; }
495
496
protected:
497
int scale_;
498
int iterations_;
499
double tau_;
500
double lambda_;
501
double alpha_;
502
int btvKernelSize_;
503
int blurKernelSize_;
504
double blurSigma_;
505
int temporalAreaRadius_; // not used in some implementations
506
Ptr<cv::superres::DenseOpticalFlowExt> opticalFlow_;
507
508
private:
509
bool ocl_process(InputArrayOfArrays src, OutputArray dst, InputArrayOfArrays forwardMotions,
510
InputArrayOfArrays backwardMotions, int baseIdx);
511
512
//Ptr<FilterEngine> filter_;
513
int curBlurKernelSize_;
514
double curBlurSigma_;
515
int curSrcType_;
516
517
std::vector<float> btvWeights_;
518
UMat ubtvWeights_;
519
520
int curBtvKernelSize_;
521
double curAlpha_;
522
523
// Mat
524
std::vector<Mat> lowResForwardMotions_;
525
std::vector<Mat> lowResBackwardMotions_;
526
527
std::vector<Mat> highResForwardMotions_;
528
std::vector<Mat> highResBackwardMotions_;
529
530
std::vector<Mat> forwardMaps_;
531
std::vector<Mat> backwardMaps_;
532
533
Mat highRes_;
534
535
Mat diffTerm_, regTerm_;
536
Mat a_, b_, c_;
537
538
#ifdef HAVE_OPENCL
539
// UMat
540
std::vector<UMat> ulowResForwardMotions_;
541
std::vector<UMat> ulowResBackwardMotions_;
542
543
std::vector<UMat> uhighResForwardMotions_;
544
std::vector<UMat> uhighResBackwardMotions_;
545
546
std::vector<UMat> uforwardMaps_;
547
std::vector<UMat> ubackwardMaps_;
548
549
UMat uhighRes_;
550
551
UMat udiffTerm_, uregTerm_;
552
UMat ua_, ub_, uc_;
553
#endif
554
};
555
556
BTVL1_Base::BTVL1_Base()
557
{
558
scale_ = 4;
559
iterations_ = 180;
560
lambda_ = 0.03;
561
tau_ = 1.3;
562
alpha_ = 0.7;
563
btvKernelSize_ = 7;
564
blurKernelSize_ = 5;
565
blurSigma_ = 0.0;
566
temporalAreaRadius_ = 0;
567
opticalFlow_ = createOptFlow_Farneback();
568
569
curBlurKernelSize_ = -1;
570
curBlurSigma_ = -1.0;
571
curSrcType_ = -1;
572
573
curBtvKernelSize_ = -1;
574
curAlpha_ = -1.0;
575
}
576
577
#ifdef HAVE_OPENCL
578
579
bool BTVL1_Base::ocl_process(InputArrayOfArrays _src, OutputArray _dst, InputArrayOfArrays _forwardMotions,
580
InputArrayOfArrays _backwardMotions, int baseIdx)
581
{
582
std::vector<UMat> & src = *(std::vector<UMat> *)_src.getObj(),
583
& forwardMotions = *(std::vector<UMat> *)_forwardMotions.getObj(),
584
& backwardMotions = *(std::vector<UMat> *)_backwardMotions.getObj();
585
586
// update blur filter and btv weights
587
if (blurKernelSize_ != curBlurKernelSize_ || blurSigma_ != curBlurSigma_ || src[0].type() != curSrcType_)
588
{
589
//filter_ = createGaussianFilter(src[0].type(), Size(blurKernelSize_, blurKernelSize_), blurSigma_);
590
curBlurKernelSize_ = blurKernelSize_;
591
curBlurSigma_ = blurSigma_;
592
curSrcType_ = src[0].type();
593
}
594
595
if (btvWeights_.empty() || btvKernelSize_ != curBtvKernelSize_ || alpha_ != curAlpha_)
596
{
597
calcBtvWeights(btvKernelSize_, alpha_, btvWeights_);
598
Mat(btvWeights_, true).copyTo(ubtvWeights_);
599
600
curBtvKernelSize_ = btvKernelSize_;
601
curAlpha_ = alpha_;
602
}
603
604
// calc high res motions
605
calcRelativeMotions(forwardMotions, backwardMotions, ulowResForwardMotions_, ulowResBackwardMotions_, baseIdx, src[0].size());
606
607
upscaleMotions(ulowResForwardMotions_, uhighResForwardMotions_, scale_);
608
upscaleMotions(ulowResBackwardMotions_, uhighResBackwardMotions_, scale_);
609
610
uforwardMaps_.resize(uhighResForwardMotions_.size());
611
ubackwardMaps_.resize(uhighResForwardMotions_.size());
612
for (size_t i = 0; i < uhighResForwardMotions_.size(); ++i)
613
buildMotionMaps(uhighResForwardMotions_[i], uhighResBackwardMotions_[i], uforwardMaps_[i], ubackwardMaps_[i]);
614
615
// initial estimation
616
const Size lowResSize = src[0].size();
617
const Size highResSize(lowResSize.width * scale_, lowResSize.height * scale_);
618
619
resize(src[baseIdx], uhighRes_, highResSize, 0, 0, INTER_LINEAR); // TODO
620
621
// iterations
622
udiffTerm_.create(highResSize, uhighRes_.type());
623
ua_.create(highResSize, uhighRes_.type());
624
ub_.create(highResSize, uhighRes_.type());
625
uc_.create(lowResSize, uhighRes_.type());
626
627
for (int i = 0; i < iterations_; ++i)
628
{
629
udiffTerm_.setTo(Scalar::all(0));
630
631
for (size_t k = 0; k < src.size(); ++k)
632
{
633
// a = M * Ih
634
remap(uhighRes_, ua_, ubackwardMaps_[k], noArray(), INTER_NEAREST);
635
// b = HM * Ih
636
GaussianBlur(ua_, ub_, Size(blurKernelSize_, blurKernelSize_), blurSigma_);
637
// c = DHM * Ih
638
resize(ub_, uc_, lowResSize, 0, 0, INTER_NEAREST);
639
640
diffSign(src[k], uc_, uc_);
641
642
// a = Dt * diff
643
upscale(uc_, ua_, scale_);
644
645
// b = HtDt * diff
646
GaussianBlur(ua_, ub_, Size(blurKernelSize_, blurKernelSize_), blurSigma_);
647
// a = MtHtDt * diff
648
remap(ub_, ua_, uforwardMaps_[k], noArray(), INTER_NEAREST);
649
650
add(udiffTerm_, ua_, udiffTerm_);
651
}
652
653
if (lambda_ > 0)
654
{
655
calcBtvRegularization(uhighRes_, uregTerm_, btvKernelSize_, btvWeights_, ubtvWeights_);
656
addWeighted(udiffTerm_, 1.0, uregTerm_, -lambda_, 0.0, udiffTerm_);
657
}
658
659
addWeighted(uhighRes_, 1.0, udiffTerm_, tau_, 0.0, uhighRes_);
660
}
661
662
Rect inner(btvKernelSize_, btvKernelSize_, uhighRes_.cols - 2 * btvKernelSize_, uhighRes_.rows - 2 * btvKernelSize_);
663
uhighRes_(inner).copyTo(_dst);
664
665
return true;
666
}
667
668
#endif
669
670
void BTVL1_Base::process(InputArrayOfArrays _src, OutputArray _dst, InputArrayOfArrays _forwardMotions,
671
InputArrayOfArrays _backwardMotions, int baseIdx)
672
{
673
CV_INSTRUMENT_REGION();
674
675
CV_Assert( scale_ > 1 );
676
CV_Assert( iterations_ > 0 );
677
CV_Assert( tau_ > 0.0 );
678
CV_Assert( alpha_ > 0.0 );
679
CV_Assert( btvKernelSize_ > 0 );
680
CV_Assert( blurKernelSize_ > 0 );
681
CV_Assert( blurSigma_ >= 0.0 );
682
683
CV_OCL_RUN(_src.isUMatVector() && _dst.isUMat() && _forwardMotions.isUMatVector() &&
684
_backwardMotions.isUMatVector(),
685
ocl_process(_src, _dst, _forwardMotions, _backwardMotions, baseIdx))
686
687
std::vector<Mat> & src = *(std::vector<Mat> *)_src.getObj(),
688
& forwardMotions = *(std::vector<Mat> *)_forwardMotions.getObj(),
689
& backwardMotions = *(std::vector<Mat> *)_backwardMotions.getObj();
690
691
// update blur filter and btv weights
692
if (blurKernelSize_ != curBlurKernelSize_ || blurSigma_ != curBlurSigma_ || src[0].type() != curSrcType_)
693
{
694
//filter_ = createGaussianFilter(src[0].type(), Size(blurKernelSize_, blurKernelSize_), blurSigma_);
695
curBlurKernelSize_ = blurKernelSize_;
696
curBlurSigma_ = blurSigma_;
697
curSrcType_ = src[0].type();
698
}
699
700
if (btvWeights_.empty() || btvKernelSize_ != curBtvKernelSize_ || alpha_ != curAlpha_)
701
{
702
calcBtvWeights(btvKernelSize_, alpha_, btvWeights_);
703
curBtvKernelSize_ = btvKernelSize_;
704
curAlpha_ = alpha_;
705
}
706
707
// calc high res motions
708
calcRelativeMotions(forwardMotions, backwardMotions, lowResForwardMotions_, lowResBackwardMotions_, baseIdx, src[0].size());
709
710
upscaleMotions(lowResForwardMotions_, highResForwardMotions_, scale_);
711
upscaleMotions(lowResBackwardMotions_, highResBackwardMotions_, scale_);
712
713
forwardMaps_.resize(highResForwardMotions_.size());
714
backwardMaps_.resize(highResForwardMotions_.size());
715
for (size_t i = 0; i < highResForwardMotions_.size(); ++i)
716
buildMotionMaps(highResForwardMotions_[i], highResBackwardMotions_[i], forwardMaps_[i], backwardMaps_[i]);
717
718
// initial estimation
719
const Size lowResSize = src[0].size();
720
const Size highResSize(lowResSize.width * scale_, lowResSize.height * scale_);
721
722
resize(src[baseIdx], highRes_, highResSize, 0, 0, INTER_CUBIC);
723
724
// iterations
725
diffTerm_.create(highResSize, highRes_.type());
726
a_.create(highResSize, highRes_.type());
727
b_.create(highResSize, highRes_.type());
728
c_.create(lowResSize, highRes_.type());
729
730
for (int i = 0; i < iterations_; ++i)
731
{
732
diffTerm_.setTo(Scalar::all(0));
733
734
for (size_t k = 0; k < src.size(); ++k)
735
{
736
// a = M * Ih
737
remap(highRes_, a_, backwardMaps_[k], noArray(), INTER_NEAREST);
738
// b = HM * Ih
739
GaussianBlur(a_, b_, Size(blurKernelSize_, blurKernelSize_), blurSigma_);
740
// c = DHM * Ih
741
resize(b_, c_, lowResSize, 0, 0, INTER_NEAREST);
742
743
diffSign(src[k], c_, c_);
744
745
// a = Dt * diff
746
upscale(c_, a_, scale_);
747
// b = HtDt * diff
748
GaussianBlur(a_, b_, Size(blurKernelSize_, blurKernelSize_), blurSigma_);
749
// a = MtHtDt * diff
750
remap(b_, a_, forwardMaps_[k], noArray(), INTER_NEAREST);
751
752
add(diffTerm_, a_, diffTerm_);
753
}
754
755
if (lambda_ > 0)
756
{
757
calcBtvRegularization(highRes_, regTerm_, btvKernelSize_, btvWeights_, ubtvWeights_);
758
addWeighted(diffTerm_, 1.0, regTerm_, -lambda_, 0.0, diffTerm_);
759
}
760
761
addWeighted(highRes_, 1.0, diffTerm_, tau_, 0.0, highRes_);
762
}
763
764
Rect inner(btvKernelSize_, btvKernelSize_, highRes_.cols - 2 * btvKernelSize_, highRes_.rows - 2 * btvKernelSize_);
765
highRes_(inner).copyTo(_dst);
766
}
767
768
void BTVL1_Base::collectGarbage()
769
{
770
// Mat
771
lowResForwardMotions_.clear();
772
lowResBackwardMotions_.clear();
773
774
highResForwardMotions_.clear();
775
highResBackwardMotions_.clear();
776
777
forwardMaps_.clear();
778
backwardMaps_.clear();
779
780
highRes_.release();
781
782
diffTerm_.release();
783
regTerm_.release();
784
a_.release();
785
b_.release();
786
c_.release();
787
788
#ifdef HAVE_OPENCL
789
// UMat
790
ulowResForwardMotions_.clear();
791
ulowResBackwardMotions_.clear();
792
793
uhighResForwardMotions_.clear();
794
uhighResBackwardMotions_.clear();
795
796
uforwardMaps_.clear();
797
ubackwardMaps_.clear();
798
799
uhighRes_.release();
800
801
udiffTerm_.release();
802
uregTerm_.release();
803
ua_.release();
804
ub_.release();
805
uc_.release();
806
#endif
807
}
808
809
////////////////////////////////////////////////////////////////////
810
811
class BTVL1 CV_FINAL : public BTVL1_Base
812
{
813
public:
814
BTVL1();
815
816
void collectGarbage() CV_OVERRIDE;
817
818
protected:
819
void initImpl(Ptr<FrameSource>& frameSource) CV_OVERRIDE;
820
bool ocl_initImpl(Ptr<FrameSource>& frameSource);
821
822
void processImpl(Ptr<FrameSource>& frameSource, OutputArray output) CV_OVERRIDE;
823
bool ocl_processImpl(Ptr<FrameSource>& frameSource, OutputArray output);
824
825
private:
826
void readNextFrame(Ptr<FrameSource>& frameSource);
827
bool ocl_readNextFrame(Ptr<FrameSource>& frameSource);
828
829
void processFrame(int idx);
830
bool ocl_processFrame(int idx);
831
832
int storePos_;
833
int procPos_;
834
int outPos_;
835
836
// Mat
837
Mat curFrame_;
838
Mat prevFrame_;
839
840
std::vector<Mat> frames_;
841
std::vector<Mat> forwardMotions_;
842
std::vector<Mat> backwardMotions_;
843
std::vector<Mat> outputs_;
844
845
std::vector<Mat> srcFrames_;
846
std::vector<Mat> srcForwardMotions_;
847
std::vector<Mat> srcBackwardMotions_;
848
Mat finalOutput_;
849
850
#ifdef HAVE_OPENCL
851
// UMat
852
UMat ucurFrame_;
853
UMat uprevFrame_;
854
855
std::vector<UMat> uframes_;
856
std::vector<UMat> uforwardMotions_;
857
std::vector<UMat> ubackwardMotions_;
858
std::vector<UMat> uoutputs_;
859
860
std::vector<UMat> usrcFrames_;
861
std::vector<UMat> usrcForwardMotions_;
862
std::vector<UMat> usrcBackwardMotions_;
863
#endif
864
};
865
866
BTVL1::BTVL1()
867
{
868
temporalAreaRadius_ = 4;
869
procPos_ = 0;
870
outPos_ = 0;
871
storePos_ = 0;
872
}
873
874
void BTVL1::collectGarbage()
875
{
876
// Mat
877
curFrame_.release();
878
prevFrame_.release();
879
880
frames_.clear();
881
forwardMotions_.clear();
882
backwardMotions_.clear();
883
outputs_.clear();
884
885
srcFrames_.clear();
886
srcForwardMotions_.clear();
887
srcBackwardMotions_.clear();
888
finalOutput_.release();
889
890
#ifdef HAVE_OPENCL
891
// UMat
892
ucurFrame_.release();
893
uprevFrame_.release();
894
895
uframes_.clear();
896
uforwardMotions_.clear();
897
ubackwardMotions_.clear();
898
uoutputs_.clear();
899
900
usrcFrames_.clear();
901
usrcForwardMotions_.clear();
902
usrcBackwardMotions_.clear();
903
#endif
904
905
SuperResolution::collectGarbage();
906
BTVL1_Base::collectGarbage();
907
}
908
909
#ifdef HAVE_OPENCL
910
911
bool BTVL1::ocl_initImpl(Ptr<FrameSource>& frameSource)
912
{
913
const int cacheSize = 2 * temporalAreaRadius_ + 1;
914
915
uframes_.resize(cacheSize);
916
uforwardMotions_.resize(cacheSize);
917
ubackwardMotions_.resize(cacheSize);
918
uoutputs_.resize(cacheSize);
919
920
storePos_ = -1;
921
922
for (int t = -temporalAreaRadius_; t <= temporalAreaRadius_; ++t)
923
readNextFrame(frameSource);
924
925
for (int i = 0; i <= temporalAreaRadius_; ++i)
926
processFrame(i);
927
928
procPos_ = temporalAreaRadius_;
929
outPos_ = -1;
930
931
return true;
932
}
933
934
#endif
935
936
void BTVL1::initImpl(Ptr<FrameSource>& frameSource)
937
{
938
const int cacheSize = 2 * temporalAreaRadius_ + 1;
939
940
frames_.resize(cacheSize);
941
forwardMotions_.resize(cacheSize);
942
backwardMotions_.resize(cacheSize);
943
outputs_.resize(cacheSize);
944
945
CV_OCL_RUN(isUmat_,
946
ocl_initImpl(frameSource))
947
948
storePos_ = -1;
949
950
for (int t = -temporalAreaRadius_; t <= temporalAreaRadius_; ++t)
951
readNextFrame(frameSource);
952
953
for (int i = 0; i <= temporalAreaRadius_; ++i)
954
processFrame(i);
955
956
procPos_ = temporalAreaRadius_;
957
outPos_ = -1;
958
}
959
960
#ifdef HAVE_OPENCL
961
962
bool BTVL1::ocl_processImpl(Ptr<FrameSource>& /*frameSource*/, OutputArray _output)
963
{
964
const UMat& curOutput = at(outPos_, uoutputs_);
965
curOutput.convertTo(_output, CV_8U);
966
967
return true;
968
}
969
970
#endif
971
972
void BTVL1::processImpl(Ptr<FrameSource>& frameSource, OutputArray _output)
973
{
974
CV_INSTRUMENT_REGION();
975
976
if (outPos_ >= storePos_)
977
{
978
_output.release();
979
return;
980
}
981
982
readNextFrame(frameSource);
983
984
if (procPos_ < storePos_)
985
{
986
++procPos_;
987
processFrame(procPos_);
988
}
989
++outPos_;
990
991
CV_OCL_RUN(isUmat_,
992
ocl_processImpl(frameSource, _output))
993
994
const Mat& curOutput = at(outPos_, outputs_);
995
996
if (_output.kind() < _InputArray::OPENGL_BUFFER || _output.isUMat())
997
curOutput.convertTo(_output, CV_8U);
998
else
999
{
1000
curOutput.convertTo(finalOutput_, CV_8U);
1001
arrCopy(finalOutput_, _output);
1002
}
1003
}
1004
1005
#ifdef HAVE_OPENCL
1006
1007
bool BTVL1::ocl_readNextFrame(Ptr<FrameSource>& /*frameSource*/)
1008
{
1009
ucurFrame_.convertTo(at(storePos_, uframes_), CV_32F);
1010
1011
if (storePos_ > 0)
1012
{
1013
opticalFlow_->calc(uprevFrame_, ucurFrame_, at(storePos_ - 1, uforwardMotions_));
1014
opticalFlow_->calc(ucurFrame_, uprevFrame_, at(storePos_, ubackwardMotions_));
1015
}
1016
1017
ucurFrame_.copyTo(uprevFrame_);
1018
return true;
1019
}
1020
1021
#endif
1022
1023
void BTVL1::readNextFrame(Ptr<FrameSource>& frameSource)
1024
{
1025
CV_INSTRUMENT_REGION();
1026
1027
frameSource->nextFrame(curFrame_);
1028
if (curFrame_.empty())
1029
return;
1030
1031
#ifdef HAVE_OPENCL
1032
if (isUmat_)
1033
curFrame_.copyTo(ucurFrame_);
1034
#endif
1035
++storePos_;
1036
1037
CV_OCL_RUN(isUmat_,
1038
ocl_readNextFrame(frameSource))
1039
1040
curFrame_.convertTo(at(storePos_, frames_), CV_32F);
1041
1042
if (storePos_ > 0)
1043
{
1044
opticalFlow_->calc(prevFrame_, curFrame_, at(storePos_ - 1, forwardMotions_));
1045
opticalFlow_->calc(curFrame_, prevFrame_, at(storePos_, backwardMotions_));
1046
}
1047
1048
curFrame_.copyTo(prevFrame_);
1049
}
1050
1051
#ifdef HAVE_OPENCL
1052
1053
bool BTVL1::ocl_processFrame(int idx)
1054
{
1055
const int startIdx = std::max(idx - temporalAreaRadius_, 0);
1056
const int procIdx = idx;
1057
const int endIdx = std::min(startIdx + 2 * temporalAreaRadius_, storePos_);
1058
1059
const int count = endIdx - startIdx + 1;
1060
1061
usrcFrames_.resize(count);
1062
usrcForwardMotions_.resize(count);
1063
usrcBackwardMotions_.resize(count);
1064
1065
int baseIdx = -1;
1066
1067
for (int i = startIdx, k = 0; i <= endIdx; ++i, ++k)
1068
{
1069
if (i == procIdx)
1070
baseIdx = k;
1071
1072
usrcFrames_[k] = at(i, uframes_);
1073
1074
if (i < endIdx)
1075
usrcForwardMotions_[k] = at(i, uforwardMotions_);
1076
if (i > startIdx)
1077
usrcBackwardMotions_[k] = at(i, ubackwardMotions_);
1078
}
1079
1080
process(usrcFrames_, at(idx, uoutputs_), usrcForwardMotions_, usrcBackwardMotions_, baseIdx);
1081
1082
return true;
1083
}
1084
1085
#endif
1086
1087
void BTVL1::processFrame(int idx)
1088
{
1089
CV_INSTRUMENT_REGION();
1090
1091
CV_OCL_RUN(isUmat_,
1092
ocl_processFrame(idx))
1093
1094
const int startIdx = std::max(idx - temporalAreaRadius_, 0);
1095
const int procIdx = idx;
1096
const int endIdx = std::min(startIdx + 2 * temporalAreaRadius_, storePos_);
1097
1098
const int count = endIdx - startIdx + 1;
1099
1100
srcFrames_.resize(count);
1101
srcForwardMotions_.resize(count);
1102
srcBackwardMotions_.resize(count);
1103
1104
int baseIdx = -1;
1105
1106
for (int i = startIdx, k = 0; i <= endIdx; ++i, ++k)
1107
{
1108
if (i == procIdx)
1109
baseIdx = k;
1110
1111
srcFrames_[k] = at(i, frames_);
1112
1113
if (i < endIdx)
1114
srcForwardMotions_[k] = at(i, forwardMotions_);
1115
if (i > startIdx)
1116
srcBackwardMotions_[k] = at(i, backwardMotions_);
1117
}
1118
1119
process(srcFrames_, at(idx, outputs_), srcForwardMotions_, srcBackwardMotions_, baseIdx);
1120
}
1121
}
1122
1123
Ptr<cv::superres::SuperResolution> cv::superres::createSuperResolution_BTVL1()
1124
{
1125
return makePtr<BTVL1>();
1126
}
1127
1128