optical_flow.cpp 30.1 KB
Newer Older
wester committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                           License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of the copyright holders may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

wester committed
43 44 45 46 47 48 49 50 51 52 53 54 55 56
#if defined(__arm__) && defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)
// While compiling CV_INIT_ALGORITHM(Farneback_GPU, ...) below, GCC emits a bogus
// -Warray-bounds warning in GpuMat::~GpuMat. Also, for some reason, suppressing
// it inside precomp.hpp doesn't work (probably because it's precompiled).
// Thus, we include this before it's included by precomp.hpp.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Warray-bounds"
#include "opencv2/core/gpumat.hpp"
#pragma GCC diagnostic pop

// Even more strangely, this suppression doesn't work when cross-compiling.
// For that, there's another suppression at the bottom of the file.
#endif

wester committed
57 58
#include "precomp.hpp"

wester committed
59
using namespace std;
wester committed
60
using namespace cv;
wester committed
61
using namespace cv::gpu;
wester committed
62 63 64 65 66 67 68 69
using namespace cv::superres;
using namespace cv::superres::detail;

///////////////////////////////////////////////////////////////////
// CpuOpticalFlow

namespace
{
wester committed
70
    class CpuOpticalFlow : public DenseOpticalFlowExt
wester committed
71 72 73 74 75 76 77 78
    {
    public:
        explicit CpuOpticalFlow(int work_type);

        void calc(InputArray frame0, InputArray frame1, OutputArray flow1, OutputArray flow2);
        void collectGarbage();

    protected:
wester committed
79
        virtual void impl(const Mat& input0, const Mat& input1, OutputArray dst) = 0;
wester committed
80 81 82 83 84 85 86 87

    private:
        int work_type_;
        Mat buf_[6];
        Mat flow_;
        Mat flows_[2];
    };

wester committed
88
    CpuOpticalFlow::CpuOpticalFlow(int work_type) : work_type_(work_type)
wester committed
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
    {
    }

    void CpuOpticalFlow::calc(InputArray _frame0, InputArray _frame1, OutputArray _flow1, OutputArray _flow2)
    {
        Mat frame0 = arrGetMat(_frame0, buf_[0]);
        Mat frame1 = arrGetMat(_frame1, buf_[1]);

        CV_Assert( frame1.type() == frame0.type() );
        CV_Assert( frame1.size() == frame0.size() );

        Mat input0 = convertToType(frame0, work_type_, buf_[2], buf_[3]);
        Mat input1 = convertToType(frame1, work_type_, buf_[4], buf_[5]);

        if (!_flow2.needed() && _flow1.kind() < _InputArray::OPENGL_BUFFER)
        {
            impl(input0, input1, _flow1);
            return;
        }

        impl(input0, input1, flow_);

        if (!_flow2.needed())
wester committed
112
        {
wester committed
113
            arrCopy(flow_, _flow1);
wester committed
114
        }
wester committed
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
        else
        {
            split(flow_, flows_);

            arrCopy(flows_[0], _flow1);
            arrCopy(flows_[1], _flow2);
        }
    }

    void CpuOpticalFlow::collectGarbage()
    {
        for (int i = 0; i < 6; ++i)
            buf_[i].release();
        flow_.release();
        flows_[0].release();
        flows_[1].release();
    }
}

///////////////////////////////////////////////////////////////////
// Farneback

namespace
{
wester committed
139
    class Farneback : public CpuOpticalFlow
wester committed
140 141
    {
    public:
wester committed
142
        AlgorithmInfo* info() const;
wester committed
143

wester committed
144
        Farneback();
wester committed
145 146

    protected:
wester committed
147
        void impl(const Mat& input0, const Mat& input1, OutputArray dst);
wester committed
148 149 150 151 152 153 154 155 156 157 158

    private:
        double pyrScale_;
        int numLevels_;
        int winSize_;
        int numIters_;
        int polyN_;
        double polySigma_;
        int flags_;
    };

wester committed
159 160 161 162 163 164 165 166 167
    CV_INIT_ALGORITHM(Farneback, "DenseOpticalFlowExt.Farneback",
                      obj.info()->addParam(obj, "pyrScale", obj.pyrScale_);
                      obj.info()->addParam(obj, "numLevels", obj.numLevels_);
                      obj.info()->addParam(obj, "winSize", obj.winSize_);
                      obj.info()->addParam(obj, "numIters", obj.numIters_);
                      obj.info()->addParam(obj, "polyN", obj.polyN_);
                      obj.info()->addParam(obj, "polySigma", obj.polySigma_);
                      obj.info()->addParam(obj, "flags", obj.flags_))

wester committed
168 169 170 171 172 173 174 175 176 177 178
    Farneback::Farneback() : CpuOpticalFlow(CV_8UC1)
    {
        pyrScale_ = 0.5;
        numLevels_ = 5;
        winSize_ = 13;
        numIters_ = 10;
        polyN_ = 5;
        polySigma_ = 1.1;
        flags_ = 0;
    }

wester committed
179
    void Farneback::impl(const Mat& input0, const Mat& input1, OutputArray dst)
wester committed
180
    {
wester committed
181
        calcOpticalFlowFarneback(input0, input1, dst, pyrScale_, numLevels_, winSize_, numIters_, polyN_, polySigma_, flags_);
wester committed
182 183 184
    }
}

wester committed
185
Ptr<DenseOpticalFlowExt> cv::superres::createOptFlow_Farneback()
wester committed
186
{
wester committed
187
    return new Farneback;
wester committed
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
}

///////////////////////////////////////////////////////////////////
// Simple

namespace
{
    class Simple : public CpuOpticalFlow
    {
    public:
        AlgorithmInfo* info() const;

        Simple();

    protected:
wester committed
203
        void impl(const Mat& input0, const Mat& input1, OutputArray dst);
wester committed
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252

    private:
        int layers_;
        int averagingBlockSize_;
        int maxFlow_;
        double sigmaDist_;
        double sigmaColor_;
        int postProcessWindow_;
        double sigmaDistFix_;
        double sigmaColorFix_;
        double occThr_;
        int upscaleAveragingRadius_;
        double upscaleSigmaDist_;
        double upscaleSigmaColor_;
        double speedUpThr_;
    };

    CV_INIT_ALGORITHM(Simple, "DenseOpticalFlowExt.Simple",
                      obj.info()->addParam(obj, "layers", obj.layers_);
                      obj.info()->addParam(obj, "averagingBlockSize", obj.averagingBlockSize_);
                      obj.info()->addParam(obj, "maxFlow", obj.maxFlow_);
                      obj.info()->addParam(obj, "sigmaDist", obj.sigmaDist_);
                      obj.info()->addParam(obj, "sigmaColor", obj.sigmaColor_);
                      obj.info()->addParam(obj, "postProcessWindow", obj.postProcessWindow_);
                      obj.info()->addParam(obj, "sigmaDistFix", obj.sigmaDistFix_);
                      obj.info()->addParam(obj, "sigmaColorFix", obj.sigmaColorFix_);
                      obj.info()->addParam(obj, "occThr", obj.occThr_);
                      obj.info()->addParam(obj, "upscaleAveragingRadius", obj.upscaleAveragingRadius_);
                      obj.info()->addParam(obj, "upscaleSigmaDist", obj.upscaleSigmaDist_);
                      obj.info()->addParam(obj, "upscaleSigmaColor", obj.upscaleSigmaColor_);
                      obj.info()->addParam(obj, "speedUpThr", obj.speedUpThr_))

    Simple::Simple() : CpuOpticalFlow(CV_8UC3)
    {
        layers_ = 3;
        averagingBlockSize_ = 2;
        maxFlow_ = 4;
        sigmaDist_ = 4.1;
        sigmaColor_ = 25.5;
        postProcessWindow_ = 18;
        sigmaDistFix_ = 55.0;
        sigmaColorFix_ = 25.5;
        occThr_ = 0.35;
        upscaleAveragingRadius_ = 18;
        upscaleSigmaDist_ = 55.0;
        upscaleSigmaColor_ = 25.5;
        speedUpThr_ = 10;
    }

wester committed
253
    void Simple::impl(const Mat& _input0, const Mat& _input1, OutputArray dst)
wester committed
254
    {
wester committed
255 256 257
        Mat input0 = _input0;
        Mat input1 = _input1;
        calcOpticalFlowSF(input0, input1, dst.getMatRef(),
wester committed
258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275
                          layers_,
                          averagingBlockSize_,
                          maxFlow_,
                          sigmaDist_,
                          sigmaColor_,
                          postProcessWindow_,
                          sigmaDistFix_,
                          sigmaColorFix_,
                          occThr_,
                          upscaleAveragingRadius_,
                          upscaleSigmaDist_,
                          upscaleSigmaColor_,
                          speedUpThr_);
    }
}

Ptr<DenseOpticalFlowExt> cv::superres::createOptFlow_Simple()
{
wester committed
276 277
    return new Simple;
}
wester committed
278 279 280 281 282 283

///////////////////////////////////////////////////////////////////
// DualTVL1

namespace
{
wester committed
284
    class DualTVL1 : public CpuOpticalFlow
wester committed
285 286
    {
    public:
wester committed
287 288
        AlgorithmInfo* info() const;

wester committed
289 290
        DualTVL1();

wester committed
291
        void collectGarbage();
wester committed
292 293

    protected:
wester committed
294
        void impl(const Mat& input0, const Mat& input1, OutputArray dst);
wester committed
295 296

    private:
wester committed
297 298 299 300 301 302 303 304 305 306
        double tau_;
        double lambda_;
        double theta_;
        int nscales_;
        int warps_;
        double epsilon_;
        int iterations_;
        bool useInitialFlow_;

        Ptr<DenseOpticalFlow> alg_;
wester committed
307 308
    };

wester committed
309 310 311 312 313 314 315 316 317 318
    CV_INIT_ALGORITHM(DualTVL1, "DenseOpticalFlowExt.DualTVL1",
                      obj.info()->addParam(obj, "tau", obj.tau_);
                      obj.info()->addParam(obj, "lambda", obj.lambda_);
                      obj.info()->addParam(obj, "theta", obj.theta_);
                      obj.info()->addParam(obj, "nscales", obj.nscales_);
                      obj.info()->addParam(obj, "warps", obj.warps_);
                      obj.info()->addParam(obj, "epsilon", obj.epsilon_);
                      obj.info()->addParam(obj, "iterations", obj.iterations_);
                      obj.info()->addParam(obj, "useInitialFlow", obj.useInitialFlow_))

wester committed
319 320 321
    DualTVL1::DualTVL1() : CpuOpticalFlow(CV_8UC1)
    {
        alg_ = cv::createOptFlow_DualTVL1();
wester committed
322 323 324 325 326 327 328 329
        tau_ = alg_->getDouble("tau");
        lambda_ = alg_->getDouble("lambda");
        theta_ = alg_->getDouble("theta");
        nscales_ = alg_->getInt("nscales");
        warps_ = alg_->getInt("warps");
        epsilon_ = alg_->getDouble("epsilon");
        iterations_ = alg_->getInt("iterations");
        useInitialFlow_ = alg_->getBool("useInitialFlow");
wester committed
330 331
    }

wester committed
332
    void DualTVL1::impl(const Mat& input0, const Mat& input1, OutputArray dst)
wester committed
333
    {
wester committed
334 335 336 337 338 339 340 341
        alg_->set("tau", tau_);
        alg_->set("lambda", lambda_);
        alg_->set("theta", theta_);
        alg_->set("nscales", nscales_);
        alg_->set("warps", warps_);
        alg_->set("epsilon", epsilon_);
        alg_->set("iterations", iterations_);
        alg_->set("useInitialFlow", useInitialFlow_);
wester committed
342

wester committed
343
        alg_->calc(input0, input1, dst);
wester committed
344 345 346 347 348 349 350 351 352
    }

    void DualTVL1::collectGarbage()
    {
        alg_->collectGarbage();
        CpuOpticalFlow::collectGarbage();
    }
}

wester committed
353
Ptr<DenseOpticalFlowExt> cv::superres::createOptFlow_DualTVL1()
wester committed
354
{
wester committed
355
    return new DualTVL1;
wester committed
356 357 358 359 360
}

///////////////////////////////////////////////////////////////////
// GpuOpticalFlow

wester committed
361
#if !defined(HAVE_OPENCV_GPU) || defined(DYNAMIC_CUDA_SUPPORT)
wester committed
362

wester committed
363
Ptr<DenseOpticalFlowExt> cv::superres::createOptFlow_Farneback_GPU()
wester committed
364
{
wester committed
365 366
    CV_Error(CV_StsNotImplemented, "The called functionality is disabled for current build or platform");
    return Ptr<DenseOpticalFlowExt>();
wester committed
367 368
}

wester committed
369
Ptr<DenseOpticalFlowExt> cv::superres::createOptFlow_DualTVL1_GPU()
wester committed
370
{
wester committed
371 372
    CV_Error(CV_StsNotImplemented, "The called functionality is disabled for current build or platform");
    return Ptr<DenseOpticalFlowExt>();
wester committed
373 374
}

wester committed
375
Ptr<DenseOpticalFlowExt> cv::superres::createOptFlow_Brox_GPU()
wester committed
376
{
wester committed
377 378
    CV_Error(CV_StsNotImplemented, "The called functionality is disabled for current build or platform");
    return Ptr<DenseOpticalFlowExt>();
wester committed
379 380
}

wester committed
381
Ptr<DenseOpticalFlowExt> cv::superres::createOptFlow_PyrLK_GPU()
wester committed
382
{
wester committed
383 384
    CV_Error(CV_StsNotImplemented, "The called functionality is disabled for current build or platform");
    return Ptr<DenseOpticalFlowExt>();
wester committed
385 386
}

wester committed
387
#else // HAVE_OPENCV_GPU
wester committed
388 389 390

namespace
{
wester committed
391
    class GpuOpticalFlow : public DenseOpticalFlowExt
wester committed
392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422
    {
    public:
        explicit GpuOpticalFlow(int work_type);

        void calc(InputArray frame0, InputArray frame1, OutputArray flow1, OutputArray flow2);
        void collectGarbage();

    protected:
        virtual void impl(const GpuMat& input0, const GpuMat& input1, GpuMat& dst1, GpuMat& dst2) = 0;

    private:
        int work_type_;
        GpuMat buf_[6];
        GpuMat u_, v_, flow_;
    };

    GpuOpticalFlow::GpuOpticalFlow(int work_type) : work_type_(work_type)
    {
    }

    void GpuOpticalFlow::calc(InputArray _frame0, InputArray _frame1, OutputArray _flow1, OutputArray _flow2)
    {
        GpuMat frame0 = arrGetGpuMat(_frame0, buf_[0]);
        GpuMat frame1 = arrGetGpuMat(_frame1, buf_[1]);

        CV_Assert( frame1.type() == frame0.type() );
        CV_Assert( frame1.size() == frame0.size() );

        GpuMat input0 = convertToType(frame0, work_type_, buf_[2], buf_[3]);
        GpuMat input1 = convertToType(frame1, work_type_, buf_[4], buf_[5]);

wester committed
423
        if (_flow2.needed() && _flow1.kind() == _InputArray::GPU_MAT && _flow2.kind() == _InputArray::GPU_MAT)
wester committed
424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454
        {
            impl(input0, input1, _flow1.getGpuMatRef(), _flow2.getGpuMatRef());
            return;
        }

        impl(input0, input1, u_, v_);

        if (_flow2.needed())
        {
            arrCopy(u_, _flow1);
            arrCopy(v_, _flow2);
        }
        else
        {
            GpuMat src[] = {u_, v_};
            merge(src, 2, flow_);
            arrCopy(flow_, _flow1);
        }
    }

    void GpuOpticalFlow::collectGarbage()
    {
        for (int i = 0; i < 6; ++i)
            buf_[i].release();
        u_.release();
        v_.release();
        flow_.release();
    }
}

///////////////////////////////////////////////////////////////////
wester committed
455
// Brox_GPU
wester committed
456 457 458

namespace
{
wester committed
459
    class Brox_GPU : public GpuOpticalFlow
wester committed
460 461
    {
    public:
wester committed
462 463 464
        AlgorithmInfo* info() const;

        Brox_GPU();
wester committed
465

wester committed
466
        void collectGarbage();
wester committed
467 468 469 470 471 472 473 474 475 476 477 478

    protected:
        void impl(const GpuMat& input0, const GpuMat& input1, GpuMat& dst1, GpuMat& dst2);

    private:
        double alpha_;
        double gamma_;
        double scaleFactor_;
        int innerIterations_;
        int outerIterations_;
        int solverIterations_;

wester committed
479
        BroxOpticalFlow alg_;
wester committed
480 481
    };

wester committed
482 483 484 485 486 487 488
    CV_INIT_ALGORITHM(Brox_GPU, "DenseOpticalFlowExt.Brox_GPU",
                      obj.info()->addParam(obj, "alpha", obj.alpha_, false, 0, 0, "Flow smoothness");
                      obj.info()->addParam(obj, "gamma", obj.gamma_, false, 0, 0, "Gradient constancy importance");
                      obj.info()->addParam(obj, "scaleFactor", obj.scaleFactor_, false, 0, 0, "Pyramid scale factor");
                      obj.info()->addParam(obj, "innerIterations", obj.innerIterations_, false, 0, 0, "Number of lagged non-linearity iterations (inner loop)");
                      obj.info()->addParam(obj, "outerIterations", obj.outerIterations_, false, 0, 0, "Number of warping iterations (number of pyramid levels)");
                      obj.info()->addParam(obj, "solverIterations", obj.solverIterations_, false, 0, 0, "Number of linear system solver iterations"))
wester committed
489

wester committed
490
    Brox_GPU::Brox_GPU() : GpuOpticalFlow(CV_32FC1), alg_(0.197f, 50.0f, 0.8f, 10, 77, 10)
wester committed
491
    {
wester committed
492 493 494 495 496 497
        alpha_ = alg_.alpha;
        gamma_ = alg_.gamma;
        scaleFactor_ = alg_.scale_factor;
        innerIterations_ = alg_.inner_iterations;
        outerIterations_ = alg_.outer_iterations;
        solverIterations_ = alg_.solver_iterations;
wester committed
498 499
    }

wester committed
500
    void Brox_GPU::impl(const GpuMat& input0, const GpuMat& input1, GpuMat& dst1, GpuMat& dst2)
wester committed
501
    {
wester committed
502 503 504 505 506 507
        alg_.alpha = static_cast<float>(alpha_);
        alg_.gamma = static_cast<float>(gamma_);
        alg_.scale_factor = static_cast<float>(scaleFactor_);
        alg_.inner_iterations = innerIterations_;
        alg_.outer_iterations = outerIterations_;
        alg_.solver_iterations = solverIterations_;
wester committed
508

wester committed
509
        alg_(input0, input1, dst1, dst2);
wester committed
510 511
    }

wester committed
512
    void Brox_GPU::collectGarbage()
wester committed
513
    {
wester committed
514
        alg_.buf.release();
wester committed
515 516 517 518
        GpuOpticalFlow::collectGarbage();
    }
}

wester committed
519
Ptr<DenseOpticalFlowExt> cv::superres::createOptFlow_Brox_GPU()
wester committed
520
{
wester committed
521
    return new Brox_GPU;
wester committed
522 523 524
}

///////////////////////////////////////////////////////////////////
wester committed
525
// PyrLK_GPU
wester committed
526 527 528

namespace
{
wester committed
529
    class PyrLK_GPU : public GpuOpticalFlow
wester committed
530 531
    {
    public:
wester committed
532
        AlgorithmInfo* info() const;
wester committed
533

wester committed
534 535 536
        PyrLK_GPU();

        void collectGarbage();
wester committed
537 538 539 540 541 542 543 544 545

    protected:
        void impl(const GpuMat& input0, const GpuMat& input1, GpuMat& dst1, GpuMat& dst2);

    private:
        int winSize_;
        int maxLevel_;
        int iterations_;

wester committed
546
        PyrLKOpticalFlow alg_;
wester committed
547 548
    };

wester committed
549 550 551 552
    CV_INIT_ALGORITHM(PyrLK_GPU, "DenseOpticalFlowExt.PyrLK_GPU",
                      obj.info()->addParam(obj, "winSize", obj.winSize_);
                      obj.info()->addParam(obj, "maxLevel", obj.maxLevel_);
                      obj.info()->addParam(obj, "iterations", obj.iterations_))
wester committed
553

wester committed
554
    PyrLK_GPU::PyrLK_GPU() : GpuOpticalFlow(CV_8UC1)
wester committed
555
    {
wester committed
556 557 558
        winSize_ = alg_.winSize.width;
        maxLevel_ = alg_.maxLevel;
        iterations_ = alg_.iters;
wester committed
559 560
    }

wester committed
561
    void PyrLK_GPU::impl(const GpuMat& input0, const GpuMat& input1, GpuMat& dst1, GpuMat& dst2)
wester committed
562
    {
wester committed
563 564 565 566
        alg_.winSize.width = winSize_;
        alg_.winSize.height = winSize_;
        alg_.maxLevel = maxLevel_;
        alg_.iters = iterations_;
wester committed
567

wester committed
568
        alg_.dense(input0, input1, dst1, dst2);
wester committed
569 570
    }

wester committed
571
    void PyrLK_GPU::collectGarbage()
wester committed
572
    {
wester committed
573
        alg_.releaseMemory();
wester committed
574 575 576 577
        GpuOpticalFlow::collectGarbage();
    }
}

wester committed
578
Ptr<DenseOpticalFlowExt> cv::superres::createOptFlow_PyrLK_GPU()
wester committed
579
{
wester committed
580
    return new PyrLK_GPU;
wester committed
581 582 583
}

///////////////////////////////////////////////////////////////////
wester committed
584
// Farneback_GPU
wester committed
585 586 587

namespace
{
wester committed
588
    class Farneback_GPU : public GpuOpticalFlow
wester committed
589 590
    {
    public:
wester committed
591
        AlgorithmInfo* info() const;
wester committed
592

wester committed
593 594 595
        Farneback_GPU();

        void collectGarbage();
wester committed
596 597 598 599 600 601 602 603 604 605 606 607 608

    protected:
        void impl(const GpuMat& input0, const GpuMat& input1, GpuMat& dst1, GpuMat& dst2);

    private:
        double pyrScale_;
        int numLevels_;
        int winSize_;
        int numIters_;
        int polyN_;
        double polySigma_;
        int flags_;

wester committed
609
        FarnebackOpticalFlow alg_;
wester committed
610 611
    };

wester committed
612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632
    CV_INIT_ALGORITHM(Farneback_GPU, "DenseOpticalFlowExt.Farneback_GPU",
                      obj.info()->addParam(obj, "pyrScale", obj.pyrScale_);
                      obj.info()->addParam(obj, "numLevels", obj.numLevels_);
                      obj.info()->addParam(obj, "winSize", obj.winSize_);
                      obj.info()->addParam(obj, "numIters", obj.numIters_);
                      obj.info()->addParam(obj, "polyN", obj.polyN_);
                      obj.info()->addParam(obj, "polySigma", obj.polySigma_);
                      obj.info()->addParam(obj, "flags", obj.flags_))

    Farneback_GPU::Farneback_GPU() : GpuOpticalFlow(CV_8UC1)
    {
        pyrScale_ = alg_.pyrScale;
        numLevels_ = alg_.numLevels;
        winSize_ = alg_.winSize;
        numIters_ = alg_.numIters;
        polyN_ = alg_.polyN;
        polySigma_ = alg_.polySigma;
        flags_ = alg_.flags;
    }

    void Farneback_GPU::impl(const GpuMat& input0, const GpuMat& input1, GpuMat& dst1, GpuMat& dst2)
wester committed
633
    {
wester committed
634 635 636 637 638 639 640
        alg_.pyrScale = pyrScale_;
        alg_.numLevels = numLevels_;
        alg_.winSize = winSize_;
        alg_.numIters = numIters_;
        alg_.polyN = polyN_;
        alg_.polySigma = polySigma_;
        alg_.flags = flags_;
wester committed
641

wester committed
642
        alg_(input0, input1, dst1, dst2);
wester committed
643 644
    }

wester committed
645
    void Farneback_GPU::collectGarbage()
wester committed
646
    {
wester committed
647 648
        alg_.releaseMemory();
        GpuOpticalFlow::collectGarbage();
wester committed
649
    }
wester committed
650
}
wester committed
651

wester committed
652 653 654 655 656 657 658 659 660 661 662
Ptr<DenseOpticalFlowExt> cv::superres::createOptFlow_Farneback_GPU()
{
    return new Farneback_GPU;
}

///////////////////////////////////////////////////////////////////
// DualTVL1_GPU

namespace
{
    class DualTVL1_GPU : public GpuOpticalFlow
wester committed
663
    {
wester committed
664 665 666 667
    public:
        AlgorithmInfo* info() const;

        DualTVL1_GPU();
wester committed
668

wester committed
669
        void collectGarbage();
wester committed
670

wester committed
671 672 673 674 675 676 677 678 679 680 681 682 683 684 685
    protected:
        void impl(const GpuMat& input0, const GpuMat& input1, GpuMat& dst1, GpuMat& dst2);

    private:
        double tau_;
        double lambda_;
        double theta_;
        int nscales_;
        int warps_;
        double epsilon_;
        int iterations_;
        bool useInitialFlow_;

        OpticalFlowDual_TVL1_GPU alg_;
    };
wester committed
686

wester committed
687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720
    CV_INIT_ALGORITHM(DualTVL1_GPU, "DenseOpticalFlowExt.DualTVL1_GPU",
                      obj.info()->addParam(obj, "tau", obj.tau_);
                      obj.info()->addParam(obj, "lambda", obj.lambda_);
                      obj.info()->addParam(obj, "theta", obj.theta_);
                      obj.info()->addParam(obj, "nscales", obj.nscales_);
                      obj.info()->addParam(obj, "warps", obj.warps_);
                      obj.info()->addParam(obj, "epsilon", obj.epsilon_);
                      obj.info()->addParam(obj, "iterations", obj.iterations_);
                      obj.info()->addParam(obj, "useInitialFlow", obj.useInitialFlow_))

    DualTVL1_GPU::DualTVL1_GPU() : GpuOpticalFlow(CV_8UC1)
    {
        tau_ = alg_.tau;
        lambda_ = alg_.lambda;
        theta_ = alg_.theta;
        nscales_ = alg_.nscales;
        warps_ = alg_.warps;
        epsilon_ = alg_.epsilon;
        iterations_ = alg_.iterations;
        useInitialFlow_ = alg_.useInitialFlow;
    }

    void DualTVL1_GPU::impl(const GpuMat& input0, const GpuMat& input1, GpuMat& dst1, GpuMat& dst2)
    {
        alg_.tau = tau_;
        alg_.lambda = lambda_;
        alg_.theta = theta_;
        alg_.nscales = nscales_;
        alg_.warps = warps_;
        alg_.epsilon = epsilon_;
        alg_.iterations = iterations_;
        alg_.useInitialFlow = useInitialFlow_;

        alg_(input0, input1, dst1, dst2);
wester committed
721 722
    }

wester committed
723
    void DualTVL1_GPU::collectGarbage()
wester committed
724
    {
wester committed
725
        alg_.collectGarbage();
wester committed
726 727 728 729
        GpuOpticalFlow::collectGarbage();
    }
}

wester committed
730
Ptr<DenseOpticalFlowExt> cv::superres::createOptFlow_DualTVL1_GPU()
wester committed
731
{
wester committed
732
    return new DualTVL1_GPU;
wester committed
733 734
}

wester committed
735 736
#endif // HAVE_OPENCV_GPU
#ifdef HAVE_OPENCV_OCL
wester committed
737 738 739

namespace
{
wester committed
740
    class oclOpticalFlow : public DenseOpticalFlowExt
wester committed
741 742
    {
    public:
wester committed
743 744
        explicit oclOpticalFlow(int work_type);

wester committed
745 746 747
        void calc(InputArray frame0, InputArray frame1, OutputArray flow1, OutputArray flow2);
        void collectGarbage();

wester committed
748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801
    protected:
        virtual void impl(const cv::ocl::oclMat& input0, const cv::ocl::oclMat& input1, cv::ocl::oclMat& dst1, cv::ocl::oclMat& dst2) = 0;

    private:
        int work_type_;
        cv::ocl::oclMat buf_[6];
        cv::ocl::oclMat u_, v_, flow_;
    };

    oclOpticalFlow::oclOpticalFlow(int work_type) : work_type_(work_type)
    {
    }

    void oclOpticalFlow::calc(InputArray frame0, InputArray frame1, OutputArray flow1, OutputArray flow2)
    {
        ocl::oclMat& _frame0 = ocl::getOclMatRef(frame0);
        ocl::oclMat& _frame1 = ocl::getOclMatRef(frame1);
        ocl::oclMat& _flow1  = ocl::getOclMatRef(flow1);
        ocl::oclMat& _flow2  = ocl::getOclMatRef(flow2);

        CV_Assert( _frame1.type() == _frame0.type() );
        CV_Assert( _frame1.size() == _frame0.size() );

        cv::ocl::oclMat input0_ = convertToType(_frame0, work_type_, buf_[2], buf_[3]);
        cv::ocl::oclMat input1_ = convertToType(_frame1, work_type_, buf_[4], buf_[5]);

        impl(input0_, input1_, u_, v_);//go to tvl1 algorithm

        u_.copyTo(_flow1);
        v_.copyTo(_flow2);
    }

    void oclOpticalFlow::collectGarbage()
    {
        for (int i = 0; i < 6; ++i)
            buf_[i].release();
        u_.release();
        v_.release();
        flow_.release();
    }
}
///////////////////////////////////////////////////////////////////
// PyrLK_OCL

namespace
{
    class PyrLK_OCL : public oclOpticalFlow
    {
    public:
        AlgorithmInfo* info() const;

        PyrLK_OCL();

        void collectGarbage();
wester committed
802 803

    protected:
wester committed
804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863
        void impl(const ocl::oclMat& input0, const ocl::oclMat& input1, ocl::oclMat& dst1, ocl::oclMat& dst2);

    private:
        int winSize_;
        int maxLevel_;
        int iterations_;

        ocl::PyrLKOpticalFlow alg_;
    };

    CV_INIT_ALGORITHM(PyrLK_OCL, "DenseOpticalFlowExt.PyrLK_OCL",
        obj.info()->addParam(obj, "winSize", obj.winSize_);
    obj.info()->addParam(obj, "maxLevel", obj.maxLevel_);
    obj.info()->addParam(obj, "iterations", obj.iterations_))

    PyrLK_OCL::PyrLK_OCL() : oclOpticalFlow(CV_8UC1)
    {
        winSize_ = alg_.winSize.width;
        maxLevel_ = alg_.maxLevel;
        iterations_ = alg_.iters;
    }

    void PyrLK_OCL::impl(const cv::ocl::oclMat& input0, const cv::ocl::oclMat& input1, cv::ocl::oclMat& dst1, cv::ocl::oclMat& dst2)
    {
        alg_.winSize.width = winSize_;
        alg_.winSize.height = winSize_;
        alg_.maxLevel = maxLevel_;
        alg_.iters = iterations_;

        alg_.dense(input0, input1, dst1, dst2);
    }

    void PyrLK_OCL::collectGarbage()
    {
        alg_.releaseMemory();
        oclOpticalFlow::collectGarbage();
    }
}

Ptr<DenseOpticalFlowExt> cv::superres::createOptFlow_PyrLK_OCL()
{
    return new PyrLK_OCL;
}

///////////////////////////////////////////////////////////////////
// DualTVL1_OCL

namespace
{
    class DualTVL1_OCL : public oclOpticalFlow
    {
    public:
        AlgorithmInfo* info() const;

        DualTVL1_OCL();

        void collectGarbage();

    protected:
        void impl(const cv::ocl::oclMat& input0, const cv::ocl::oclMat& input1, cv::ocl::oclMat& dst1, cv::ocl::oclMat& dst2);
wester committed
864 865 866 867 868 869 870 871 872 873 874

    private:
        double tau_;
        double lambda_;
        double theta_;
        int nscales_;
        int warps_;
        double epsilon_;
        int iterations_;
        bool useInitialFlow_;

wester committed
875
        ocl::OpticalFlowDual_TVL1_OCL alg_;
wester committed
876 877
    };

wester committed
878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900
    CV_INIT_ALGORITHM(DualTVL1_OCL, "DenseOpticalFlowExt.DualTVL1_OCL",
    obj.info()->addParam(obj, "tau", obj.tau_);
    obj.info()->addParam(obj, "lambda", obj.lambda_);
    obj.info()->addParam(obj, "theta", obj.theta_);
    obj.info()->addParam(obj, "nscales", obj.nscales_);
    obj.info()->addParam(obj, "warps", obj.warps_);
    obj.info()->addParam(obj, "epsilon", obj.epsilon_);
    obj.info()->addParam(obj, "iterations", obj.iterations_);
    obj.info()->addParam(obj, "useInitialFlow", obj.useInitialFlow_))

    DualTVL1_OCL::DualTVL1_OCL() : oclOpticalFlow(CV_8UC1)
    {
        tau_ = alg_.tau;
        lambda_ = alg_.lambda;
        theta_ = alg_.theta;
        nscales_ = alg_.nscales;
        warps_ = alg_.warps;
        epsilon_ = alg_.epsilon;
        iterations_ = alg_.iterations;
        useInitialFlow_ = alg_.useInitialFlow;
    }

    void DualTVL1_OCL::impl(const cv::ocl::oclMat& input0, const cv::ocl::oclMat& input1, cv::ocl::oclMat& dst1, cv::ocl::oclMat& dst2)
wester committed
901
    {
wester committed
902 903 904 905 906 907 908 909 910 911
        alg_.tau = tau_;
        alg_.lambda = lambda_;
        alg_.theta = theta_;
        alg_.nscales = nscales_;
        alg_.warps = warps_;
        alg_.epsilon = epsilon_;
        alg_.iterations = iterations_;
        alg_.useInitialFlow = useInitialFlow_;

        alg_(input0, input1, dst1, dst2);
wester committed
912 913 914

    }

wester committed
915
    void DualTVL1_OCL::collectGarbage()
wester committed
916
    {
wester committed
917 918
        alg_.collectGarbage();
        oclOpticalFlow::collectGarbage();
wester committed
919
    }
wester committed
920 921 922 923 924 925
}

Ptr<DenseOpticalFlowExt> cv::superres::createOptFlow_DualTVL1_OCL()
{
    return new DualTVL1_OCL;
}
wester committed
926

wester committed
927 928 929 930 931 932
///////////////////////////////////////////////////////////////////
// FarneBack

namespace
{
    class FarneBack_OCL : public oclOpticalFlow
wester committed
933
    {
wester committed
934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954
    public:
        AlgorithmInfo* info() const;

        FarneBack_OCL();

        void collectGarbage();

    protected:
        void impl(const cv::ocl::oclMat& input0, const cv::ocl::oclMat& input1, cv::ocl::oclMat& dst1, cv::ocl::oclMat& dst2);

    private:
        double pyrScale_;
        int numLevels_;
        int winSize_;
        int numIters_;
        int polyN_;
        double polySigma_;
        int flags_;

        ocl::FarnebackOpticalFlow alg_;
    };
wester committed
955

wester committed
956 957 958 959 960 961 962 963
    CV_INIT_ALGORITHM(FarneBack_OCL, "DenseOpticalFlowExt.FarneBack_OCL",
        obj.info()->addParam(obj, "pyrScale", obj.pyrScale_);
    obj.info()->addParam(obj, "numLevels", obj.numLevels_);
    obj.info()->addParam(obj, "winSize", obj.winSize_);
    obj.info()->addParam(obj, "numIters", obj.numIters_);
    obj.info()->addParam(obj, "polyN", obj.polyN_);
    obj.info()->addParam(obj, "polySigma", obj.polySigma_);
    obj.info()->addParam(obj, "flags", obj.flags_))
wester committed
964

wester committed
965 966 967 968 969 970 971 972 973 974
    FarneBack_OCL::FarneBack_OCL() : oclOpticalFlow(CV_8UC1)
    {
        pyrScale_ = alg_.pyrScale;
        numLevels_ = alg_.numLevels;
        winSize_ = alg_.winSize;
        numIters_ = alg_.numIters;
        polyN_ = alg_.polyN;
        polySigma_ = alg_.polySigma;
        flags_ = alg_.flags;
    }
wester committed
975

wester committed
976 977 978 979 980 981 982 983 984 985 986
    void FarneBack_OCL::impl(const cv::ocl::oclMat& input0, const cv::ocl::oclMat& input1, cv::ocl::oclMat& dst1, cv::ocl::oclMat& dst2)
    {
        alg_.pyrScale = pyrScale_;
        alg_.numLevels = numLevels_;
        alg_.winSize = winSize_;
        alg_.numIters = numIters_;
        alg_.polyN = polyN_;
        alg_.polySigma = polySigma_;
        alg_.flags = flags_;

        alg_(input0, input1, dst1, dst2);
wester committed
987 988
    }

wester committed
989
    void FarneBack_OCL::collectGarbage()
wester committed
990
    {
wester committed
991 992
        alg_.releaseMemory();
        oclOpticalFlow::collectGarbage();
wester committed
993 994 995
    }
}

wester committed
996
Ptr<DenseOpticalFlowExt> cv::superres::createOptFlow_Farneback_OCL()
wester committed
997
{
wester committed
998
    return new FarneBack_OCL;
wester committed
999 1000
}

wester committed
1001 1002 1003 1004 1005 1006 1007
#endif

// Even though this looks as if it covers nothing, it actually suppress a warning in
// CV_INIT_ALGORITHM(Farneback_GPU, ...). See the top comment for more explanation.
#if defined(__arm__) && defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)
# pragma GCC diagnostic ignored "-Warray-bounds"
#endif