diff --git a/modules/optflow/include/opencv2/optflow.hpp b/modules/optflow/include/opencv2/optflow.hpp index 9ddf638d8..e7427d95a 100644 --- a/modules/optflow/include/opencv2/optflow.hpp +++ b/modules/optflow/include/opencv2/optflow.hpp @@ -70,7 +70,7 @@ CV_EXPORTS_W bool writeOpticalFlow( const String& path, InputArray flow ); // DeepFlow implementation, based on: // P. Weinzaepfel, J. Revaud, Z. Harchaoui, and C. Schmid, “DeepFlow: Large Displacement Optical Flow with Deep Matching,” -//CV_EXPORTS_W Ptr createOptFlow_DeepFlow(); +CV_EXPORTS_W Ptr createOptFlow_DeepFlow(); // Additional interface to the SimpleFlow algorithm - calcOpticalFlowSF() CV_EXPORTS_W Ptr createOptFlow_SimpleFlow(); diff --git a/modules/optflow/src/deepflow.cpp b/modules/optflow/src/deepflow.cpp new file mode 100644 index 000000000..52cffef04 --- /dev/null +++ b/modules/optflow/src/deepflow.cpp @@ -0,0 +1,624 @@ +/*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*/ + +#include "precomp.hpp" +#include + +namespace cv +{ +namespace optflow +{ + +class OpticalFlowDeepFlow: public DenseOpticalFlow +{ +public: + OpticalFlowDeepFlow(); + + void calc( InputArray I0, InputArray I1, InputOutputArray flow ); + void collectGarbage(); + +// AlgorithmInfo* info() const; + +protected: + float sigma; // Gaussian smoothing parameter + int minSize; // minimal dimension of an image in the pyramid + float downscaleFactor; // scaling factor in the pyramid + int fixedPointIterations; // during each level of the pyramid + int sorIterations; // iterations of SOR + float alpha; // smoothness assumption weight + float delta; // color constancy weight + float gamma; // gradient constancy weight + float omega; // relaxation factor in SOR + + float zeta; // added to the denomimnator of theta_0 (normaliation of the data term) + float epsilon; // robust penalizer const + int maxLayers; // max amount of layers in the pyramid + +private: + void calcOneLevel( const Mat I0, const Mat I1, Mat W ); + Mat warpImage( const Mat input, const Mat flow ); + void dataTerm( const Mat W, const Mat dW, const Mat Ix, const Mat Iy, const Mat Iz, + const Mat Ixx, const Mat Ixy, const Mat Iyy, const Mat Ixz, const Mat Iyz, + Mat a11, Mat a12, Mat a22, Mat b1, Mat b2 ); + void smoothnessWeights( const Mat W, Mat weightsX, Mat weightsY ); + void smoothnessTerm( const Mat W, const Mat weightsX, const Mat weightsY, Mat b1, Mat b2 ); + void sorSolve( const Mat a11, const Mat a12, const Mat a22, const Mat b1, const Mat b2, + const Mat smoothX, const Mat smoothY, Mat dW ); + std::vector buildPyramid( const Mat& src ); + + int interpolationType; + +}; + +OpticalFlowDeepFlow::OpticalFlowDeepFlow() +{ + // parameters + sigma = 0.6f; + minSize = 25; + downscaleFactor = 0.95f; + fixedPointIterations = 5; + sorIterations = 25; + alpha = 1.0f; + delta = 0.5f; + gamma = 5.0f; + omega = 1.6f; + + //consts + interpolationType = INTER_LINEAR; + zeta = 0.1f; + epsilon = 0.001f; + maxLayers = 200; +} + +std::vector OpticalFlowDeepFlow::buildPyramid( const Mat& src ) +{ + std::vector pyramid; + pyramid.push_back(src); + Mat prev = pyramid[0]; + int i = 0; + while ( i < this->maxLayers ) + { + Mat next; //TODO: filtering at each level? + Size nextSize((int) (prev.cols * downscaleFactor + 0.5f), + (int) (prev.rows * downscaleFactor + 0.5f)); + if( nextSize.height <= minSize || nextSize.width <= minSize) + break; + resize(prev, next, + nextSize, 0, 0, + interpolationType); + pyramid.push_back(next); + prev = next; + } + return pyramid; +} +Mat OpticalFlowDeepFlow::warpImage( const Mat input, const Mat flow ) +{ + // warps the image "backwards" + // if flow = computeFlow( I0, I1 ), then + // I0 = warpImage( I1, flow ) - approx. + + Mat output; + Mat mapX = Mat(flow.size(), CV_32FC1); + Mat mapY = Mat(flow.size(), CV_32FC1); + const float *pFlow; + float *pMapX, *pMapY; + for ( int j = 0; j < flow.rows; ++j ) + { + pFlow = flow.ptr(j); + pMapX = mapX.ptr(j); + pMapY = mapY.ptr(j); + for ( int i = 0; i < flow.cols; ++i ) + { + pMapX[i] = i + pFlow[2 * i]; + pMapY[i] = j + pFlow[2 * i + 1]; + } + } + remap(input, output, mapX, mapY, interpolationType, BORDER_TRANSPARENT); + return output; +} +void OpticalFlowDeepFlow::calc( InputArray _I0, InputArray _I1, InputOutputArray _flow ) +{ + Mat I0temp = _I0.getMat(); + Mat I1temp = _I1.getMat(); + + CV_Assert(I0temp.size() == I1temp.size()); + CV_Assert(I0temp.type() == I1temp.type()); + CV_Assert(I0temp.channels() == 1); + // TODO: currently only grayscale - data term could be computed in color version as well... + + Mat I0, I1; + + I0temp.convertTo(I0, CV_32F); + I1temp.convertTo(I1, CV_32F); + + _flow.create(I0.size(), CV_32FC2); + Mat W = _flow.getMat(); // if any data present - will be discarded + + // pre-smooth images + int kernelLen = (floor(3 * sigma) * 2) + 1; + Size kernelSize(kernelLen, kernelLen); + GaussianBlur(I0, I0, kernelSize, sigma); + GaussianBlur(I1, I1, kernelSize, sigma); + // build down-sized pyramids + std::vector pyramid_I0 = buildPyramid(I0); + std::vector pyramid_I1 = buildPyramid(I1); + int levelCount = pyramid_I0.size(); + + // initialize the first version of flow estimate to zeros + Size smallestSize = pyramid_I0[levelCount - 1].size(); + W = Mat::zeros(smallestSize, CV_32FC2); + + for ( int level = levelCount - 1; level >= 0; --level ) + { //iterate through all levels, beginning with the most coarse + calcOneLevel(pyramid_I0[level], pyramid_I1[level], W); + if ( level > 0 ) //not the last level + { + Mat temp; + Size newSize = pyramid_I0[level - 1].size(); + resize(W, temp, newSize, 0, 0, interpolationType); //resize calculated flow + W = temp * (1.0f / downscaleFactor); //scale values + } + } + W.copyTo(_flow); +} + +void OpticalFlowDeepFlow::calcOneLevel( const Mat I0, const Mat I1, Mat W ) +{ + CV_DbgAssert( I0.size() == I1.size() );CV_DbgAssert( I0.type() == I1.type() );CV_DbgAssert( W.size() == I0.size() ); + + // linear equation systems + Size s = I0.size(); + int t = CV_32F; // data type + Mat a11, a12, a22, b1, b2; + a11.create(s, t); + a12.create(s, t); + a22.create(s, t); + b1.create(s, t); + b2.create(s, t); + // diffusivity coeffs + Mat weightsX, weightsY; + weightsX.create(s, t); + weightsY.create(s, t); + + Mat warpedI1 = warpImage(I1, W); // warped second image + Mat averageFrame = 0.5 * (I0 + warpedI1); // mean value of 2 frames - to compute derivatives on + + //computing derivatives, notation as in Brox's paper + Mat Ix, Iy, Iz, Ixx, Ixy, Iyy, Ixz, Iyz; + int ddepth = -1; //as source image + int kernel_size = 1; + + Sobel(averageFrame, Ix, ddepth, 1, 0, kernel_size, 1, 0.00, BORDER_REPLICATE); + Sobel(averageFrame, Iy, ddepth, 0, 1, kernel_size, 1, 0.00, BORDER_REPLICATE); + Iz.create(I1.size(), I1.type()); + Iz = warpedI1 - I0; + Sobel(Ix, Ixx, ddepth, 1, 0, kernel_size, 1, 0.00, BORDER_REPLICATE); + Sobel(Ix, Ixy, ddepth, 0, 1, kernel_size, 1, 0.00, BORDER_REPLICATE); + Sobel(Iy, Iyy, ddepth, 0, 1, kernel_size, 1, 0.00, BORDER_REPLICATE); + Sobel(Iz, Ixz, ddepth, 1, 0, kernel_size, 1, 0.00, BORDER_REPLICATE); + Sobel(Iz, Iyz, ddepth, 0, 1, kernel_size, 1, 0.00, BORDER_REPLICATE); + + Mat tempW = W.clone(); // flow version to be modified in each iteration + Mat dW = Mat::zeros(W.size(), W.type()); // flow increment + + //fixed-point iterations + for ( int i = 0; i < fixedPointIterations; ++i ) + { + dataTerm(W, dW, Ix, Iy, Iz, Ixx, Ixy, Iyy, Ixz, Iyz, a11, a12, a22, b1, b2); + smoothnessWeights(tempW, weightsX, weightsY); + smoothnessTerm(W, weightsX, weightsY, b1, b2); + sorSolve(a11, a12, a22, b1, b2, weightsX, weightsY, dW); + tempW = W + dW; + } + tempW.copyTo(W); +} +void OpticalFlowDeepFlow::dataTerm( const Mat W, const Mat dW, const Mat Ix, const Mat Iy, + const Mat Iz, const Mat Ixx, const Mat Ixy, const Mat Iyy, const Mat Ixz, + const Mat Iyz, Mat a11, Mat a12, Mat a22, Mat b1, Mat b2 ) +{ + const float zeta_squared = zeta * zeta; // added in normalization factor to be non-zero + const float epsilon_squared = epsilon * epsilon; + + const float *pIx, *pIy, *pIz; + const float *pIxx, *pIxy, *pIyy, *pIxz, *pIyz; + const float *pdU, *pdV; // accessing 2 layers of dW. Succesive columns interleave u and v + float *pa11, *pa12, *pa22, *pb1, *pb2; // linear equation sys. coeffs for each pixel + + float derivNorm; //denominator of the spatial-derivative normalizing factor (theta_0) + float derivNorm2; + float Ik1z, Ik1zx, Ik1zy; // approximations of I^(k+1) values by Taylor expansions + float temp; + for ( int j = 0; j < W.rows; j++ ) //for each row + { + pIx = Ix.ptr(j); + pIy = Iy.ptr(j); + pIz = Iz.ptr(j); + pIxx = Ixx.ptr(j); + pIxy = Ixy.ptr(j); + pIyy = Iyy.ptr(j); + pIxz = Ixz.ptr(j); + pIyz = Iyz.ptr(j); + + pa11 = a11.ptr(j); + pa12 = a12.ptr(j); + pa22 = a22.ptr(j); + pb1 = b1.ptr(j); + pb2 = b2.ptr(j); + + pdU = dW.ptr(j); + pdV = pdU + 1; + for ( int i = 0; i < W.cols; i++ ) //for each pixel in the row + { // TODO: implement masking of points warped out of the image + //color constancy component + derivNorm = (*pIx) * (*pIx) + (*pIy) * (*pIy) + zeta_squared; + Ik1z = *pIz + (*pIx * *pdU) + (*pIy * *pdV); + temp = (0.5*delta/3) / sqrt(Ik1z * Ik1z / derivNorm + epsilon_squared); + *pa11 = *pIx * *pIx * temp / derivNorm; + *pa12 = *pIx * *pIy * temp / derivNorm; + *pa22 = *pIy * *pIy * temp / derivNorm; + *pb1 = -*pIz * *pIx * temp / derivNorm; + *pb2 = -*pIz * *pIy * temp / derivNorm; + + // gradient constancy component + + derivNorm = *pIxx * *pIxx + *pIxy * *pIxy + zeta_squared; + derivNorm2 = *pIyy * *pIyy + *pIxy * *pIxy + zeta_squared; + Ik1zx = *pIxz + *pIxx * *pdU + *pIxy * *pdV; + Ik1zy = *pIyz + *pIxy * *pdU + *pIyy * *pdV; + + temp = (0.5*gamma/3) + / sqrt( + Ik1zx * Ik1zx / derivNorm + Ik1zy * Ik1zy / derivNorm2 + + epsilon_squared); + *pa11 += temp * (*pIxx * *pIxx / derivNorm + *pIxy * *pIxy / derivNorm2); + *pa12 += temp * (*pIxx * *pIxy / derivNorm + *pIxy * *pIyy / derivNorm2); + *pa22 += temp * (*pIxy * *pIxy / derivNorm + *pIyy * *pIyy / derivNorm2); + *pb1 += -temp * (*pIxx * *pIxz / derivNorm + *pIxy * *pIyz / derivNorm2); + *pb2 += -temp * (*pIxy * *pIxz / derivNorm + *pIyy * *pIyz / derivNorm2); + + ++pIx; + ++pIy; + ++pIz; + ++pIxx; + ++pIxy; + ++pIyy; + ++pIxz; + ++pIyz; + pdU += 2; + pdV += 2; + ++pa11; + ++pa12; + ++pa22; + ++pb1; + ++pb2; + + } + } + + + +} +void OpticalFlowDeepFlow::smoothnessWeights( const Mat W, Mat weightsX, Mat weightsY ) +{ + float k[] = { -0.5, 0, 0.5 }; + const float epsilon_squared = epsilon * epsilon; + Mat kernel_h = Mat(1, 3, CV_32FC1, k); + Mat kernel_v = Mat(3, 1, CV_32FC1, k); + Mat Wx, Wy; // partial derivatives of the flow + Mat S = Mat(W.size(), CV_32FC1); // sum of squared derivatives + weightsX = Mat::zeros(W.size(), CV_32FC1); //output - weights of smoothness terms in x and y directions + weightsY = Mat::zeros(W.size(), CV_32FC1); + + filter2D(W, Wx, CV_32FC2, kernel_h); + filter2D(W, Wy, CV_32FC2, kernel_v); + + const float * ux, *uy, *vx, *vy; + float * pS, *pWeight, *temp; + + for ( int j = 0; j < S.rows; ++j ) + { + ux = Wx.ptr(j); + vx = ux + 1; + uy = Wy.ptr(j); + vy = uy + 1; + pS = S.ptr(j); + for ( int i = 0; i < S.cols; ++i ) + { + *pS = alpha / sqrt(*ux * *ux + *vx * *vx + *uy * *uy + *vy * *vy + epsilon_squared); + ux += 2; + vx += 2; + uy += 2; + vy += 2; + ++pS; + } + } + // horizontal weights + for ( int j = 0; j < S.rows; ++j ) + { + pWeight = weightsX.ptr(j); + pS = S.ptr(j); + for ( int i = 0; i < S.cols - 1; ++i ) + { + *pWeight = *pS + *(pS + 1); + ++pS; + ++pWeight; + } + } + //vertical weights + for ( int j = 0; j < S.rows - 1; ++j ) + { + pWeight = weightsY.ptr(j); + pS = S.ptr(j); + temp = S.ptr(j + 1); // next row pointer for easy access + for ( int i = 0; i < S.cols; ++i ) + { + *pWeight = *(pS++) + *(temp++); + ++pWeight; + } + } +} +void OpticalFlowDeepFlow::smoothnessTerm( const Mat W, const Mat weightsX, const Mat weightsY, + Mat b1, Mat b2 ) +{ + float *pB1, *pB2; + const float *pU, *pV, *pWeight; + float iB1, iB2; // increments of b1 and b2 + //horizontal direction - both U and V (b1 and b2) + for ( int j = 0; j < W.rows; j++ ) + { + pB1 = b1.ptr(j); + pB2 = b2.ptr(j); + pU = W.ptr(j); + pV = pU + 1; + pWeight = weightsX.ptr(j); + for ( int i = 0; i < W.cols - 1; i++ ) + { + iB1 = (*(pU + 2) - *pU) * *pWeight; + iB2 = (*(pV + 2) - *pV) * *pWeight; + *pB1 += iB1; + *(pB1 + 1) -= iB1; + *pB2 += iB2; + *(pB2 + 1) -= iB2; + + pB1++; + pB2++; + pU += 2; + pV += 2; + pWeight++; + } + } + const float *pUnext, *pVnext; // temp pointers for next row + float *pB1next, *pB2next; + //vertical direction - both U and V + for ( int j = 0; j < W.rows - 1; j++ ) + { + pB1 = b1.ptr(j); + pB2 = b2.ptr(j); + pU = W.ptr(j); + pV = pU + 1; + pUnext = W.ptr(j + 1); + pVnext = pUnext + 1; + pB1next = b1.ptr(j + 1); + pB2next = b2.ptr(j + 1); + pWeight = weightsY.ptr(j); + for ( int i = 0; i < W.cols; i++ ) + { + iB1 = (*pUnext - *pU) * *pWeight; + iB2 = (*pVnext - *pV) * *pWeight; + *pB1 += iB1; + *pB1next -= iB1; + *pB2 += iB2; + *pB2next -= iB2; + + pB1++; + pB2++; + pU += 2; + pV += 2; + pWeight++; + pUnext += 2; + pVnext += 2; + pB1next++; + pB2next++; + } + } +} +void OpticalFlowDeepFlow::sorSolve( const Mat a11, const Mat a12, const Mat a22, const Mat b1, + const Mat b2, const Mat smoothX, const Mat smoothY, Mat dW ) +{ + CV_Assert(a11.isContinuous()); + CV_Assert(a12.isContinuous()); + CV_Assert(a22.isContinuous()); + CV_Assert(b1.isContinuous()); + CV_Assert(b2.isContinuous()); + CV_Assert(smoothX.isContinuous()); + CV_Assert(smoothY.isContinuous()); + + std::vector dWChannels(2); + split(dW, dWChannels); + + Mat *du = &(dWChannels[0]); + Mat *dv = &(dWChannels[1]); + + CV_Assert(du->isContinuous()); + CV_Assert(dv->isContinuous()); + + const float *pa11, *pa12, *pa22, *pb1, *pb2, *psmoothX, *psmoothY; + float *pdu, *pdv; + psmoothX = smoothX.ptr(0); + psmoothY = smoothY.ptr(0); + pdu = du->ptr(0); + pdv = dv->ptr(0); + + float sigmaU, sigmaV, dPsi, A11, A22, A12, B1, B2, det; + + int cols = dW.cols; + int rows = dW.rows; + + int s = dW.cols; // step between rows + + for ( int iter = 0; iter < sorIterations; ++iter ) + { + pa11 = a11.ptr(0); + pa12 = a12.ptr(0); + pa22 = a22.ptr(0); + pb1 = b1.ptr(0); + pb2 = b2.ptr(0); + for ( int j = 0; j < rows; ++j ) + { + for ( int i = 0; i < cols; ++i ) + { + int o = j * s + i; + if ( i == 0 && j == 0 ) + { + dPsi = psmoothX[o] + psmoothY[o]; + sigmaU = psmoothX[o] * pdu[o + 1] + psmoothY[o] * pdu[o + s]; + sigmaV = psmoothX[o] * pdv[o + 1] + psmoothY[o] * pdv[o + s]; + } else if ( i == cols - 1 && j == 0 ) + { + dPsi = psmoothX[o - 1] + psmoothY[o]; + sigmaU = psmoothX[o - 1] * pdu[o - 1] + + psmoothY[o] * pdu[o + s]; + sigmaV = psmoothX[o - 1] * pdv[o - 1] + + psmoothY[o] * pdv[o + s]; + } else if ( j == 0 ) + { + dPsi = psmoothX[o - 1] + psmoothX[o] + psmoothY[o]; + sigmaU = psmoothX[o - 1] * pdu[o - 1] + + psmoothX[o] * pdu[o + 1] + psmoothY[o] * pdu[o + s]; + sigmaV = psmoothX[o - 1] * pdv[o - 1] + + psmoothX[o] * pdv[o + 1] + psmoothY[o] * pdv[o + s]; + } else if ( i == 0 && j == rows - 1 ) + { + dPsi = psmoothX[o] + psmoothY[o - s]; + sigmaU = psmoothX[o] * pdu[o + 1] + + psmoothY[o - s] * pdu[o - s]; + sigmaV = psmoothX[o] * pdv[o + 1] + + psmoothY[o - s] * pdv[o - s]; + } else if ( i == cols - 1 && j == rows - 1 ) + { + dPsi = psmoothX[o - 1] + psmoothY[o - s]; + sigmaU = psmoothX[o - 1] * pdu[o - 1] + + psmoothY[o - s] * pdu[o - s]; + sigmaV = psmoothX[o - 1] * pdv[o - 1] + + psmoothY[o - s] * pdv[o - s]; + } else if ( j == rows - 1 ) + { + dPsi = psmoothX[o - 1] + psmoothX[o] + psmoothY[o - s]; + sigmaU = psmoothX[o - 1] * pdu[o - 1] + + psmoothX[o] * pdu[o + 1] + + psmoothY[o - s] * pdu[o - s]; + sigmaV = psmoothX[o - 1] * pdv[o - 1] + + psmoothX[o] * pdv[o + 1] + + psmoothY[o - s] * pdv[o - s]; + } else if ( i == 0 ) + { + dPsi = psmoothX[o] + psmoothY[o - s] + psmoothY[o]; + sigmaU = psmoothX[o] * pdu[o + 1] + + psmoothY[o - s] * pdu[o - s] + + psmoothY[o] * pdu[o + s]; + sigmaV = psmoothX[o] * pdv[o + 1] + + psmoothY[o - s] * pdv[o - s] + + psmoothY[o] * pdv[o + s]; + } else if ( i == cols - 1 ) + { + dPsi = psmoothX[o - 1] + psmoothY[o - s] + psmoothY[o]; + sigmaU = psmoothX[o - 1] * pdu[o - 1] + + psmoothY[o - s] * pdu[o - s] + + psmoothY[o] * pdu[o + s]; + sigmaV = psmoothX[o - 1] * pdv[o - 1] + + psmoothY[o - s] * pdv[o - s] + + psmoothY[o] * pdv[o + s]; + } else + { + dPsi = psmoothX[o - 1] + psmoothX[o] + psmoothY[o - s] + + psmoothY[o]; + sigmaU = psmoothX[o - 1] * pdu[o - 1] + + psmoothX[o] * pdu[o + 1] + + psmoothY[o - s] * pdu[o - s] + + psmoothY[o] * pdu[o + s]; + sigmaV = psmoothX[o - 1] * pdv[o - 1] + + psmoothX[o] * pdv[o + 1] + + psmoothY[o - s] * pdv[o - s] + + psmoothY[o] * pdv[o + s]; + } + A22 = *pa11 + dPsi; + A11 = *pa22 + dPsi; + A12 = -*pa12; + det = A11 * A22 - A12 * A12; + A22 /= det; + A11 /= det; + A12 /= det; + B1 = *pb1 + sigmaU; + B2 = *pb2 + sigmaV; + pdu[o] += omega * (A11 * B1 + A12 * B2 - pdu[o]); + pdv[o] += omega * (A12 * B1 + A22 * B2 - pdv[o]); + + ++pa11; ++pa12; ++pa22; ++pb1; ++pb2; + } + } + } + merge(dWChannels, dW); +} +void OpticalFlowDeepFlow::collectGarbage() +{ + +} +// +//CV_INIT_ALGORITHM(OpticalFlowDeepFlow, "DenseOpticalFlow.DeepFlow", +// obj.info()->addParam(obj, "sigma", obj.sigma, false, 0, 0, "Gaussian blur parameter"); +// obj.info()->addParam(obj, "alpha", obj.alpha, false, 0, 0, "Smoothness assumption weight"); +// obj.info()->addParam(obj, "delta", obj.delta, false, 0, 0, "Color constancy weight"); +// obj.info()->addParam(obj, "gamma", obj.gamma, false, 0, 0, "Gradient constancy weight"); +// obj.info()->addParam(obj, "omega", obj.omega, false, 0, 0, "Relaxation factor in SOR"); +// obj.info()->addParam(obj, "minSize", obj.minSize, false, 0, 0, "Min. image size in the pyramid"); +// obj.info()->addParam(obj, "fixedPointIterations", obj.fixedPointIterations, false, 0, 0, "Fixed point iterations"); +// obj.info()->addParam(obj, "sorIterations", obj.sorIterations, false, 0, 0, "SOR iterations"); +// obj.info()->addParam(obj, "downscaleFactor", obj.downscaleFactor, false, 0, 0,"Downscale factor")) + + +Ptr createOptFlow_DeepFlow() +{ + return makePtr(); +} + +}//optflow +}//cv