Home | History | Annotate | Download | only in src
      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.width, 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] = { src.cols, 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] = { src1.cols * cn, 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;
    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] = { src.cols, 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         (void)ubtvWeights;
    451 
    452         typedef void (*func_t)(InputArray _src, OutputArray _dst, int btvKernelSize, const std::vector<float>& btvWeights);
    453         static const func_t funcs[] =
    454         {
    455             0, calcBtvRegularizationImpl<float>, 0, calcBtvRegularizationImpl<Point3f>, 0
    456         };
    457 
    458         const func_t func = funcs[_src.channels()];
    459         CV_Assert(func != 0);
    460         func(_src, _dst, btvKernelSize, btvWeights);
    461     }
    462 
    463     class BTVL1_Base : public cv::superres::SuperResolution
    464     {
    465     public:
    466         BTVL1_Base();
    467 
    468         void process(InputArrayOfArrays src, OutputArray dst, InputArrayOfArrays forwardMotions,
    469                      InputArrayOfArrays backwardMotions, int baseIdx);
    470 
    471         void collectGarbage();
    472 
    473         CV_IMPL_PROPERTY(int, Scale, scale_)
    474         CV_IMPL_PROPERTY(int, Iterations, iterations_)
    475         CV_IMPL_PROPERTY(double, Tau, tau_)
    476         CV_IMPL_PROPERTY(double, Labmda, lambda_)
    477         CV_IMPL_PROPERTY(double, Alpha, alpha_)
    478         CV_IMPL_PROPERTY(int, KernelSize, btvKernelSize_)
    479         CV_IMPL_PROPERTY(int, BlurKernelSize, blurKernelSize_)
    480         CV_IMPL_PROPERTY(double, BlurSigma, blurSigma_)
    481         CV_IMPL_PROPERTY(int, TemporalAreaRadius, temporalAreaRadius_)
    482         CV_IMPL_PROPERTY_S(Ptr<cv::superres::DenseOpticalFlowExt>, OpticalFlow, opticalFlow_)
    483 
    484     protected:
    485         int scale_;
    486         int iterations_;
    487         double tau_;
    488         double lambda_;
    489         double alpha_;
    490         int btvKernelSize_;
    491         int blurKernelSize_;
    492         double blurSigma_;
    493         int temporalAreaRadius_; // not used in some implementations
    494         Ptr<cv::superres::DenseOpticalFlowExt> opticalFlow_;
    495 
    496     private:
    497         bool ocl_process(InputArrayOfArrays src, OutputArray dst, InputArrayOfArrays forwardMotions,
    498                          InputArrayOfArrays backwardMotions, int baseIdx);
    499 
    500         //Ptr<FilterEngine> filter_;
    501         int curBlurKernelSize_;
    502         double curBlurSigma_;
    503         int curSrcType_;
    504 
    505         std::vector<float> btvWeights_;
    506         UMat ubtvWeights_;
    507 
    508         int curBtvKernelSize_;
    509         double curAlpha_;
    510 
    511         // Mat
    512         std::vector<Mat> lowResForwardMotions_;
    513         std::vector<Mat> lowResBackwardMotions_;
    514 
    515         std::vector<Mat> highResForwardMotions_;
    516         std::vector<Mat> highResBackwardMotions_;
    517 
    518         std::vector<Mat> forwardMaps_;
    519         std::vector<Mat> backwardMaps_;
    520 
    521         Mat highRes_;
    522 
    523         Mat diffTerm_, regTerm_;
    524         Mat a_, b_, c_;
    525 
    526 #ifdef HAVE_OPENCL
    527         // UMat
    528         std::vector<UMat> ulowResForwardMotions_;
    529         std::vector<UMat> ulowResBackwardMotions_;
    530 
    531         std::vector<UMat> uhighResForwardMotions_;
    532         std::vector<UMat> uhighResBackwardMotions_;
    533 
    534         std::vector<UMat> uforwardMaps_;
    535         std::vector<UMat> ubackwardMaps_;
    536 
    537         UMat uhighRes_;
    538 
    539         UMat udiffTerm_, uregTerm_;
    540         UMat ua_, ub_, uc_;
    541 #endif
    542     };
    543 
    544     BTVL1_Base::BTVL1_Base()
    545     {
    546         scale_ = 4;
    547         iterations_ = 180;
    548         lambda_ = 0.03;
    549         tau_ = 1.3;
    550         alpha_ = 0.7;
    551         btvKernelSize_ = 7;
    552         blurKernelSize_ = 5;
    553         blurSigma_ = 0.0;
    554         temporalAreaRadius_ = 0;
    555         opticalFlow_ = createOptFlow_Farneback();
    556 
    557         curBlurKernelSize_ = -1;
    558         curBlurSigma_ = -1.0;
    559         curSrcType_ = -1;
    560 
    561         curBtvKernelSize_ = -1;
    562         curAlpha_ = -1.0;
    563     }
    564 
    565 #ifdef HAVE_OPENCL
    566 
    567     bool BTVL1_Base::ocl_process(InputArrayOfArrays _src, OutputArray _dst, InputArrayOfArrays _forwardMotions,
    568                                  InputArrayOfArrays _backwardMotions, int baseIdx)
    569     {
    570         std::vector<UMat> & src = *(std::vector<UMat> *)_src.getObj(),
    571                 & forwardMotions = *(std::vector<UMat> *)_forwardMotions.getObj(),
    572                 & backwardMotions = *(std::vector<UMat> *)_backwardMotions.getObj();
    573 
    574         // update blur filter and btv weights
    575         if (blurKernelSize_ != curBlurKernelSize_ || blurSigma_ != curBlurSigma_ || src[0].type() != curSrcType_)
    576         {
    577             //filter_ = createGaussianFilter(src[0].type(), Size(blurKernelSize_, blurKernelSize_), blurSigma_);
    578             curBlurKernelSize_ = blurKernelSize_;
    579             curBlurSigma_ = blurSigma_;
    580             curSrcType_ = src[0].type();
    581         }
    582 
    583         if (btvWeights_.empty() || btvKernelSize_ != curBtvKernelSize_ || alpha_ != curAlpha_)
    584         {
    585             calcBtvWeights(btvKernelSize_, alpha_, btvWeights_);
    586             Mat(btvWeights_, true).copyTo(ubtvWeights_);
    587 
    588             curBtvKernelSize_ = btvKernelSize_;
    589             curAlpha_ = alpha_;
    590         }
    591 
    592         // calc high res motions
    593         calcRelativeMotions(forwardMotions, backwardMotions, ulowResForwardMotions_, ulowResBackwardMotions_, baseIdx, src[0].size());
    594 
    595         upscaleMotions(ulowResForwardMotions_, uhighResForwardMotions_, scale_);
    596         upscaleMotions(ulowResBackwardMotions_, uhighResBackwardMotions_, scale_);
    597 
    598         uforwardMaps_.resize(uhighResForwardMotions_.size());
    599         ubackwardMaps_.resize(uhighResForwardMotions_.size());
    600         for (size_t i = 0; i < uhighResForwardMotions_.size(); ++i)
    601             buildMotionMaps(uhighResForwardMotions_[i], uhighResBackwardMotions_[i], uforwardMaps_[i], ubackwardMaps_[i]);
    602 
    603         // initial estimation
    604         const Size lowResSize = src[0].size();
    605         const Size highResSize(lowResSize.width * scale_, lowResSize.height * scale_);
    606 
    607         resize(src[baseIdx], uhighRes_, highResSize, 0, 0, INTER_LINEAR); // TODO
    608 
    609         // iterations
    610         udiffTerm_.create(highResSize, uhighRes_.type());
    611         ua_.create(highResSize, uhighRes_.type());
    612         ub_.create(highResSize, uhighRes_.type());
    613         uc_.create(lowResSize, uhighRes_.type());
    614 
    615         for (int i = 0; i < iterations_; ++i)
    616         {
    617             udiffTerm_.setTo(Scalar::all(0));
    618 
    619             for (size_t k = 0; k < src.size(); ++k)
    620             {
    621                 // a = M * Ih
    622                 remap(uhighRes_, ua_, ubackwardMaps_[k], noArray(), INTER_NEAREST);
    623                 // b = HM * Ih
    624                 GaussianBlur(ua_, ub_, Size(blurKernelSize_, blurKernelSize_), blurSigma_);
    625                 // c = DHM * Ih
    626                 resize(ub_, uc_, lowResSize, 0, 0, INTER_NEAREST);
    627 
    628                 diffSign(src[k], uc_, uc_);
    629 
    630                 // a = Dt * diff
    631                 upscale(uc_, ua_, scale_);
    632 
    633                 // b = HtDt * diff
    634                 GaussianBlur(ua_, ub_, Size(blurKernelSize_, blurKernelSize_), blurSigma_);
    635                 // a = MtHtDt * diff
    636                 remap(ub_, ua_, uforwardMaps_[k], noArray(), INTER_NEAREST);
    637 
    638                 add(udiffTerm_, ua_, udiffTerm_);
    639             }
    640 
    641             if (lambda_ > 0)
    642             {
    643                 calcBtvRegularization(uhighRes_, uregTerm_, btvKernelSize_, btvWeights_, ubtvWeights_);
    644                 addWeighted(udiffTerm_, 1.0, uregTerm_, -lambda_, 0.0, udiffTerm_);
    645             }
    646 
    647             addWeighted(uhighRes_, 1.0, udiffTerm_, tau_, 0.0, uhighRes_);
    648         }
    649 
    650         Rect inner(btvKernelSize_, btvKernelSize_, uhighRes_.cols - 2 * btvKernelSize_, uhighRes_.rows - 2 * btvKernelSize_);
    651         uhighRes_(inner).copyTo(_dst);
    652 
    653         return true;
    654     }
    655 
    656 #endif
    657 
    658     void BTVL1_Base::process(InputArrayOfArrays _src, OutputArray _dst, InputArrayOfArrays _forwardMotions,
    659                              InputArrayOfArrays _backwardMotions, int baseIdx)
    660     {
    661         CV_Assert( scale_ > 1 );
    662         CV_Assert( iterations_ > 0 );
    663         CV_Assert( tau_ > 0.0 );
    664         CV_Assert( alpha_ > 0.0 );
    665         CV_Assert( btvKernelSize_ > 0 );
    666         CV_Assert( blurKernelSize_ > 0 );
    667         CV_Assert( blurSigma_ >= 0.0 );
    668 
    669         CV_OCL_RUN(_src.isUMatVector() && _dst.isUMat() && _forwardMotions.isUMatVector() &&
    670                    _backwardMotions.isUMatVector(),
    671                    ocl_process(_src, _dst, _forwardMotions, _backwardMotions, baseIdx))
    672 
    673         std::vector<Mat> & src = *(std::vector<Mat> *)_src.getObj(),
    674                 & forwardMotions = *(std::vector<Mat> *)_forwardMotions.getObj(),
    675                 & backwardMotions = *(std::vector<Mat> *)_backwardMotions.getObj();
    676 
    677         // update blur filter and btv weights
    678         if (blurKernelSize_ != curBlurKernelSize_ || blurSigma_ != curBlurSigma_ || src[0].type() != curSrcType_)
    679         {
    680             //filter_ = createGaussianFilter(src[0].type(), Size(blurKernelSize_, blurKernelSize_), blurSigma_);
    681             curBlurKernelSize_ = blurKernelSize_;
    682             curBlurSigma_ = blurSigma_;
    683             curSrcType_ = src[0].type();
    684         }
    685 
    686         if (btvWeights_.empty() || btvKernelSize_ != curBtvKernelSize_ || alpha_ != curAlpha_)
    687         {
    688             calcBtvWeights(btvKernelSize_, alpha_, btvWeights_);
    689             curBtvKernelSize_ = btvKernelSize_;
    690             curAlpha_ = alpha_;
    691         }
    692 
    693         // calc high res motions
    694         calcRelativeMotions(forwardMotions, backwardMotions, lowResForwardMotions_, lowResBackwardMotions_, baseIdx, src[0].size());
    695 
    696         upscaleMotions(lowResForwardMotions_, highResForwardMotions_, scale_);
    697         upscaleMotions(lowResBackwardMotions_, highResBackwardMotions_, scale_);
    698 
    699         forwardMaps_.resize(highResForwardMotions_.size());
    700         backwardMaps_.resize(highResForwardMotions_.size());
    701         for (size_t i = 0; i < highResForwardMotions_.size(); ++i)
    702             buildMotionMaps(highResForwardMotions_[i], highResBackwardMotions_[i], forwardMaps_[i], backwardMaps_[i]);
    703 
    704         // initial estimation
    705         const Size lowResSize = src[0].size();
    706         const Size highResSize(lowResSize.width * scale_, lowResSize.height * scale_);
    707 
    708         resize(src[baseIdx], highRes_, highResSize, 0, 0, INTER_CUBIC);
    709 
    710         // iterations
    711         diffTerm_.create(highResSize, highRes_.type());
    712         a_.create(highResSize, highRes_.type());
    713         b_.create(highResSize, highRes_.type());
    714         c_.create(lowResSize, highRes_.type());
    715 
    716         for (int i = 0; i < iterations_; ++i)
    717         {
    718             diffTerm_.setTo(Scalar::all(0));
    719 
    720             for (size_t k = 0; k < src.size(); ++k)
    721             {
    722                 // a = M * Ih
    723                 remap(highRes_, a_, backwardMaps_[k], noArray(), INTER_NEAREST);
    724                 // b = HM * Ih
    725                 GaussianBlur(a_, b_, Size(blurKernelSize_, blurKernelSize_), blurSigma_);
    726                 // c = DHM * Ih
    727                 resize(b_, c_, lowResSize, 0, 0, INTER_NEAREST);
    728 
    729                 diffSign(src[k], c_, c_);
    730 
    731                 // a = Dt * diff
    732                 upscale(c_, a_, scale_);
    733                 // b = HtDt * diff
    734                 GaussianBlur(a_, b_, Size(blurKernelSize_, blurKernelSize_), blurSigma_);
    735                 // a = MtHtDt * diff
    736                 remap(b_, a_, forwardMaps_[k], noArray(), INTER_NEAREST);
    737 
    738                 add(diffTerm_, a_, diffTerm_);
    739             }
    740 
    741             if (lambda_ > 0)
    742             {
    743                 calcBtvRegularization(highRes_, regTerm_, btvKernelSize_, btvWeights_, ubtvWeights_);
    744                 addWeighted(diffTerm_, 1.0, regTerm_, -lambda_, 0.0, diffTerm_);
    745             }
    746 
    747             addWeighted(highRes_, 1.0, diffTerm_, tau_, 0.0, highRes_);
    748         }
    749 
    750         Rect inner(btvKernelSize_, btvKernelSize_, highRes_.cols - 2 * btvKernelSize_, highRes_.rows - 2 * btvKernelSize_);
    751         highRes_(inner).copyTo(_dst);
    752     }
    753 
    754     void BTVL1_Base::collectGarbage()
    755     {
    756         // Mat
    757         lowResForwardMotions_.clear();
    758         lowResBackwardMotions_.clear();
    759 
    760         highResForwardMotions_.clear();
    761         highResBackwardMotions_.clear();
    762 
    763         forwardMaps_.clear();
    764         backwardMaps_.clear();
    765 
    766         highRes_.release();
    767 
    768         diffTerm_.release();
    769         regTerm_.release();
    770         a_.release();
    771         b_.release();
    772         c_.release();
    773 
    774 #ifdef HAVE_OPENCL
    775         // UMat
    776         ulowResForwardMotions_.clear();
    777         ulowResBackwardMotions_.clear();
    778 
    779         uhighResForwardMotions_.clear();
    780         uhighResBackwardMotions_.clear();
    781 
    782         uforwardMaps_.clear();
    783         ubackwardMaps_.clear();
    784 
    785         uhighRes_.release();
    786 
    787         udiffTerm_.release();
    788         uregTerm_.release();
    789         ua_.release();
    790         ub_.release();
    791         uc_.release();
    792 #endif
    793     }
    794 
    795 ////////////////////////////////////////////////////////////////////
    796 
    797     class BTVL1 : public BTVL1_Base
    798     {
    799     public:
    800         BTVL1();
    801 
    802         void collectGarbage();
    803 
    804     protected:
    805         void initImpl(Ptr<FrameSource>& frameSource);
    806         bool ocl_initImpl(Ptr<FrameSource>& frameSource);
    807 
    808         void processImpl(Ptr<FrameSource>& frameSource, OutputArray output);
    809         bool ocl_processImpl(Ptr<FrameSource>& frameSource, OutputArray output);
    810 
    811     private:
    812         void readNextFrame(Ptr<FrameSource>& frameSource);
    813         bool ocl_readNextFrame(Ptr<FrameSource>& frameSource);
    814 
    815         void processFrame(int idx);
    816         bool ocl_processFrame(int idx);
    817 
    818         int storePos_;
    819         int procPos_;
    820         int outPos_;
    821 
    822         // Mat
    823         Mat curFrame_;
    824         Mat prevFrame_;
    825 
    826         std::vector<Mat> frames_;
    827         std::vector<Mat> forwardMotions_;
    828         std::vector<Mat> backwardMotions_;
    829         std::vector<Mat> outputs_;
    830 
    831         std::vector<Mat> srcFrames_;
    832         std::vector<Mat> srcForwardMotions_;
    833         std::vector<Mat> srcBackwardMotions_;
    834         Mat finalOutput_;
    835 
    836 #ifdef HAVE_OPENCL
    837         // UMat
    838         UMat ucurFrame_;
    839         UMat uprevFrame_;
    840 
    841         std::vector<UMat> uframes_;
    842         std::vector<UMat> uforwardMotions_;
    843         std::vector<UMat> ubackwardMotions_;
    844         std::vector<UMat> uoutputs_;
    845 
    846         std::vector<UMat> usrcFrames_;
    847         std::vector<UMat> usrcForwardMotions_;
    848         std::vector<UMat> usrcBackwardMotions_;
    849 #endif
    850     };
    851 
    852     BTVL1::BTVL1()
    853     {
    854         temporalAreaRadius_ = 4;
    855     }
    856 
    857     void BTVL1::collectGarbage()
    858     {
    859         // Mat
    860         curFrame_.release();
    861         prevFrame_.release();
    862 
    863         frames_.clear();
    864         forwardMotions_.clear();
    865         backwardMotions_.clear();
    866         outputs_.clear();
    867 
    868         srcFrames_.clear();
    869         srcForwardMotions_.clear();
    870         srcBackwardMotions_.clear();
    871         finalOutput_.release();
    872 
    873 #ifdef HAVE_OPENCL
    874         // UMat
    875         ucurFrame_.release();
    876         uprevFrame_.release();
    877 
    878         uframes_.clear();
    879         uforwardMotions_.clear();
    880         ubackwardMotions_.clear();
    881         uoutputs_.clear();
    882 
    883         usrcFrames_.clear();
    884         usrcForwardMotions_.clear();
    885         usrcBackwardMotions_.clear();
    886 #endif
    887 
    888         SuperResolution::collectGarbage();
    889         BTVL1_Base::collectGarbage();
    890     }
    891 
    892 #ifdef HAVE_OPENCL
    893 
    894     bool BTVL1::ocl_initImpl(Ptr<FrameSource>& frameSource)
    895     {
    896         const int cacheSize = 2 * temporalAreaRadius_ + 1;
    897 
    898         uframes_.resize(cacheSize);
    899         uforwardMotions_.resize(cacheSize);
    900         ubackwardMotions_.resize(cacheSize);
    901         uoutputs_.resize(cacheSize);
    902 
    903         storePos_ = -1;
    904 
    905         for (int t = -temporalAreaRadius_; t <= temporalAreaRadius_; ++t)
    906             readNextFrame(frameSource);
    907 
    908         for (int i = 0; i <= temporalAreaRadius_; ++i)
    909             processFrame(i);
    910 
    911         procPos_ = temporalAreaRadius_;
    912         outPos_ = -1;
    913 
    914         return true;
    915     }
    916 
    917 #endif
    918 
    919     void BTVL1::initImpl(Ptr<FrameSource>& frameSource)
    920     {
    921         const int cacheSize = 2 * temporalAreaRadius_ + 1;
    922 
    923         frames_.resize(cacheSize);
    924         forwardMotions_.resize(cacheSize);
    925         backwardMotions_.resize(cacheSize);
    926         outputs_.resize(cacheSize);
    927 
    928         CV_OCL_RUN(isUmat_,
    929                    ocl_initImpl(frameSource))
    930 
    931         storePos_ = -1;
    932 
    933         for (int t = -temporalAreaRadius_; t <= temporalAreaRadius_; ++t)
    934             readNextFrame(frameSource);
    935 
    936         for (int i = 0; i <= temporalAreaRadius_; ++i)
    937             processFrame(i);
    938 
    939         procPos_ = temporalAreaRadius_;
    940         outPos_ = -1;
    941     }
    942 
    943 #ifdef HAVE_OPENCL
    944 
    945     bool BTVL1::ocl_processImpl(Ptr<FrameSource>& /*frameSource*/, OutputArray _output)
    946     {
    947         const UMat& curOutput = at(outPos_, uoutputs_);
    948         curOutput.convertTo(_output, CV_8U);
    949 
    950         return true;
    951     }
    952 
    953 #endif
    954 
    955     void BTVL1::processImpl(Ptr<FrameSource>& frameSource, OutputArray _output)
    956     {
    957         if (outPos_ >= storePos_)
    958         {
    959             _output.release();
    960             return;
    961         }
    962 
    963         readNextFrame(frameSource);
    964 
    965         if (procPos_ < storePos_)
    966         {
    967             ++procPos_;
    968             processFrame(procPos_);
    969         }
    970         ++outPos_;
    971 
    972         CV_OCL_RUN(isUmat_,
    973                    ocl_processImpl(frameSource, _output))
    974 
    975         const Mat& curOutput = at(outPos_, outputs_);
    976 
    977         if (_output.kind() < _InputArray::OPENGL_BUFFER || _output.isUMat())
    978             curOutput.convertTo(_output, CV_8U);
    979         else
    980         {
    981             curOutput.convertTo(finalOutput_, CV_8U);
    982             arrCopy(finalOutput_, _output);
    983         }
    984     }
    985 
    986 #ifdef HAVE_OPENCL
    987 
    988     bool BTVL1::ocl_readNextFrame(Ptr<FrameSource>& /*frameSource*/)
    989     {
    990         ucurFrame_.convertTo(at(storePos_, uframes_), CV_32F);
    991 
    992         if (storePos_ > 0)
    993         {
    994             opticalFlow_->calc(uprevFrame_, ucurFrame_, at(storePos_ - 1, uforwardMotions_));
    995             opticalFlow_->calc(ucurFrame_, uprevFrame_, at(storePos_, ubackwardMotions_));
    996         }
    997 
    998         ucurFrame_.copyTo(uprevFrame_);
    999         return true;
   1000     }
   1001 
   1002 #endif
   1003 
   1004     void BTVL1::readNextFrame(Ptr<FrameSource>& frameSource)
   1005     {
   1006         frameSource->nextFrame(curFrame_);
   1007         if (curFrame_.empty())
   1008             return;
   1009 
   1010 #ifdef HAVE_OPENCL
   1011         if (isUmat_)
   1012             curFrame_.copyTo(ucurFrame_);
   1013 #endif
   1014         ++storePos_;
   1015 
   1016         CV_OCL_RUN(isUmat_,
   1017                    ocl_readNextFrame(frameSource))
   1018 
   1019         curFrame_.convertTo(at(storePos_, frames_), CV_32F);
   1020 
   1021         if (storePos_ > 0)
   1022         {
   1023             opticalFlow_->calc(prevFrame_, curFrame_, at(storePos_ - 1, forwardMotions_));
   1024             opticalFlow_->calc(curFrame_, prevFrame_, at(storePos_, backwardMotions_));
   1025         }
   1026 
   1027         curFrame_.copyTo(prevFrame_);
   1028     }
   1029 
   1030 #ifdef HAVE_OPENCL
   1031 
   1032     bool BTVL1::ocl_processFrame(int idx)
   1033     {
   1034         const int startIdx = std::max(idx - temporalAreaRadius_, 0);
   1035         const int procIdx = idx;
   1036         const int endIdx = std::min(startIdx + 2 * temporalAreaRadius_, storePos_);
   1037 
   1038         const int count = endIdx - startIdx + 1;
   1039 
   1040         usrcFrames_.resize(count);
   1041         usrcForwardMotions_.resize(count);
   1042         usrcBackwardMotions_.resize(count);
   1043 
   1044         int baseIdx = -1;
   1045 
   1046         for (int i = startIdx, k = 0; i <= endIdx; ++i, ++k)
   1047         {
   1048             if (i == procIdx)
   1049                 baseIdx = k;
   1050 
   1051             usrcFrames_[k] = at(i, uframes_);
   1052 
   1053             if (i < endIdx)
   1054                 usrcForwardMotions_[k] = at(i, uforwardMotions_);
   1055             if (i > startIdx)
   1056                 usrcBackwardMotions_[k] = at(i, ubackwardMotions_);
   1057         }
   1058 
   1059         process(usrcFrames_, at(idx, uoutputs_), usrcForwardMotions_, usrcBackwardMotions_, baseIdx);
   1060 
   1061         return true;
   1062     }
   1063 
   1064 #endif
   1065 
   1066     void BTVL1::processFrame(int idx)
   1067     {
   1068         CV_OCL_RUN(isUmat_,
   1069                    ocl_processFrame(idx))
   1070 
   1071         const int startIdx = std::max(idx - temporalAreaRadius_, 0);
   1072         const int procIdx = idx;
   1073         const int endIdx = std::min(startIdx + 2 * temporalAreaRadius_, storePos_);
   1074 
   1075         const int count = endIdx - startIdx + 1;
   1076 
   1077         srcFrames_.resize(count);
   1078         srcForwardMotions_.resize(count);
   1079         srcBackwardMotions_.resize(count);
   1080 
   1081         int baseIdx = -1;
   1082 
   1083         for (int i = startIdx, k = 0; i <= endIdx; ++i, ++k)
   1084         {
   1085             if (i == procIdx)
   1086                 baseIdx = k;
   1087 
   1088             srcFrames_[k] = at(i, frames_);
   1089 
   1090             if (i < endIdx)
   1091                 srcForwardMotions_[k] = at(i, forwardMotions_);
   1092             if (i > startIdx)
   1093                 srcBackwardMotions_[k] = at(i, backwardMotions_);
   1094         }
   1095 
   1096         process(srcFrames_, at(idx, outputs_), srcForwardMotions_, srcBackwardMotions_, baseIdx);
   1097     }
   1098 }
   1099 
   1100 Ptr<cv::superres::SuperResolution> cv::superres::createSuperResolution_BTVL1()
   1101 {
   1102     return makePtr<BTVL1>();
   1103 }
   1104