merged bug fix from r8188 (PyrLKOpticalFlow patch size calculation)
authorVladislav Vinogradov <no@email>
Wed, 25 Apr 2012 09:28:22 +0000 (09:28 +0000)
committerVladislav Vinogradov <no@email>
Wed, 25 Apr 2012 09:28:22 +0000 (09:28 +0000)
modules/gpu/src/pyrlk.cpp
samples/gpu/pyrlk_optical_flow.cpp

index 83fc1f7..2722282 100644 (file)
@@ -53,20 +53,20 @@ void cv::gpu::PyrLKOpticalFlow::dense(const GpuMat&, const GpuMat&, GpuMat&, Gpu
 \r
 #else /* !defined (HAVE_CUDA) */\r
 \r
-namespace cv { namespace gpu { namespace device \r
+namespace cv { namespace gpu { namespace device\r
 {\r
-    namespace pyrlk \r
+    namespace pyrlk\r
     {\r
         void loadConstants(int cn, float minEigThreshold, int2 winSize, int iters);\r
 \r
-        void calcSharrDeriv_gpu(DevMem2Db src, DevMem2D_<short> dx_buf, DevMem2D_<short> dy_buf, DevMem2D_<short> dIdx, DevMem2D_<short> dIdy, int cn, \r
+        void calcSharrDeriv_gpu(DevMem2Db src, DevMem2D_<short> dx_buf, DevMem2D_<short> dy_buf, DevMem2D_<short> dIdx, DevMem2D_<short> dIdy, int cn,\r
             cudaStream_t stream = 0);\r
 \r
         void lkSparse_gpu(DevMem2Db I, DevMem2Db J, DevMem2D_<short> dIdx, DevMem2D_<short> dIdy,\r
-            const float2* prevPts, float2* nextPts, uchar* status, float* err, bool GET_MIN_EIGENVALS, int ptcount, \r
+            const float2* prevPts, float2* nextPts, uchar* status, float* err, bool GET_MIN_EIGENVALS, int ptcount,\r
             int level, dim3 block, dim3 patch, cudaStream_t stream = 0);\r
 \r
-        void lkDense_gpu(DevMem2Db I, DevMem2Db J, DevMem2D_<short> dIdx, DevMem2D_<short> dIdy, \r
+        void lkDense_gpu(DevMem2Db I, DevMem2Db J, DevMem2D_<short> dIdx, DevMem2D_<short> dIdy,\r
             DevMem2Df u, DevMem2Df v, DevMem2Df* err, bool GET_MIN_EIGENVALS, cudaStream_t stream = 0);\r
     }\r
 }}}\r
@@ -91,7 +91,7 @@ void cv::gpu::PyrLKOpticalFlow::buildImagePyramid(const GpuMat& img0, vector<Gpu
     pyr.resize(maxLevel + 1);\r
 \r
     Size sz = img0.size();\r
-    \r
+\r
     for (int level = 0; level <= maxLevel; ++level)\r
     {\r
         GpuMat temp;\r
@@ -124,10 +124,33 @@ void cv::gpu::PyrLKOpticalFlow::buildImagePyramid(const GpuMat& img0, vector<Gpu
     }\r
 }\r
 \r
+namespace\r
+{\r
+    void calcPatchSize(cv::Size winSize, int cn, dim3& block, dim3& patch)\r
+    {\r
+        winSize.width *= cn;\r
+\r
+        if (winSize.width > 32 && winSize.width > 2 * winSize.height)\r
+        {\r
+            block.x = 32;\r
+            block.y = 8;\r
+        }\r
+        else\r
+        {\r
+            block.x = block.y = 16;\r
+        }\r
+\r
+        patch.x = (winSize.width  + block.x - 1) / block.x;\r
+        patch.y = (winSize.height + block.y - 1) / block.y;\r
+\r
+        block.z = patch.z = 1;\r
+    }\r
+}\r
+\r
 void cv::gpu::PyrLKOpticalFlow::sparse(const GpuMat& prevImg, const GpuMat& nextImg, const GpuMat& prevPts, GpuMat& nextPts, GpuMat& status, GpuMat* err)\r
 {\r
     using namespace cv::gpu::device::pyrlk;\r
-        \r
+\r
     if (prevPts.empty())\r
     {\r
         nextPts.release();\r
@@ -136,32 +159,21 @@ void cv::gpu::PyrLKOpticalFlow::sparse(const GpuMat& prevImg, const GpuMat& next
         return;\r
     }\r
 \r
-    derivLambda = std::min(std::max(derivLambda, 0.0), 1.0);    \r
+    derivLambda = std::min(std::max(derivLambda, 0.0), 1.0);\r
 \r
     iters = std::min(std::max(iters, 0), 100);\r
 \r
     const int cn = prevImg.channels();\r
 \r
-    dim3 block;\r
-\r
-    if (winSize.width * cn > 32)\r
-    {\r
-        block.x = 32;\r
-        block.y = 8;\r
-    }\r
-    else\r
-    {\r
-        block.x = block.y = 16;\r
-    }\r
-\r
-    dim3 patch((winSize.width * cn + block.x - 1) / block.x, (winSize.height + block.y - 1) / block.y);\r
+    dim3 block, patch;\r
+    calcPatchSize(winSize, cn, block, patch);\r
 \r
     CV_Assert(derivLambda >= 0);\r
     CV_Assert(maxLevel >= 0 && winSize.width > 2 && winSize.height > 2);\r
     CV_Assert(prevImg.size() == nextImg.size() && prevImg.type() == nextImg.type());\r
     CV_Assert(patch.x > 0 && patch.x < 6 && patch.y > 0 && patch.y < 6);\r
     CV_Assert(prevPts.rows == 1 && prevPts.type() == CV_32FC2);\r
-    \r
+\r
     if (useInitialFlow)\r
         CV_Assert(nextPts.size() == prevPts.size() && nextPts.type() == CV_32FC2);\r
     else\r
@@ -176,19 +188,19 @@ void cv::gpu::PyrLKOpticalFlow::sparse(const GpuMat& prevImg, const GpuMat& next
 \r
     if (err)\r
         ensureSizeIsEnough(1, prevPts.cols, CV_32FC1, *err);\r
-    \r
+\r
     // build the image pyramids.\r
     // we pad each level with +/-winSize.{width|height}\r
     // pixels to simplify the further patch extraction.\r
 \r
     buildImagePyramid(prevImg, prevPyr_, true);\r
     buildImagePyramid(nextImg, nextPyr_, true);\r
-    \r
+\r
     // dI/dx ~ Ix, dI/dy ~ Iy\r
 \r
     ensureSizeIsEnough(prevImg.rows + winSize.height * 2, prevImg.cols + winSize.width * 2, CV_MAKETYPE(CV_16S, cn), dx_buf_);\r
     ensureSizeIsEnough(prevImg.rows + winSize.height * 2, prevImg.cols + winSize.width * 2, CV_MAKETYPE(CV_16S, cn), dy_buf_);\r
-    \r
+\r
     loadConstants(cn, minEigThreshold, make_int2(winSize.width, winSize.height), iters);\r
 \r
     for (int level = maxLevel; level >= 0; level--)\r
@@ -204,8 +216,8 @@ void cv::gpu::PyrLKOpticalFlow::sparse(const GpuMat& prevImg, const GpuMat& next
 \r
         calcSharrDeriv(prevPyr_[level], dIdx, dIdy);\r
 \r
-        lkSparse_gpu(prevPyr_[level], nextPyr_[level], dIdx, dIdy, \r
-            prevPts.ptr<float2>(), nextPts.ptr<float2>(), status.ptr(), level == 0 && err ? err->ptr<float>() : 0, getMinEigenVals, prevPts.cols, \r
+        lkSparse_gpu(prevPyr_[level], nextPyr_[level], dIdx, dIdy,\r
+            prevPts.ptr<float2>(), nextPts.ptr<float2>(), status.ptr(), level == 0 && err ? err->ptr<float>() : 0, getMinEigenVals, prevPts.cols,\r
             level, block, patch);\r
     }\r
 }\r
@@ -214,7 +226,7 @@ void cv::gpu::PyrLKOpticalFlow::dense(const GpuMat& prevImg, const GpuMat& nextI
 {\r
     using namespace cv::gpu::device::pyrlk;\r
 \r
-    derivLambda = std::min(std::max(derivLambda, 0.0), 1.0);    \r
+    derivLambda = std::min(std::max(derivLambda, 0.0), 1.0);\r
 \r
     iters = std::min(std::max(iters, 0), 100);\r
 \r
@@ -222,7 +234,7 @@ void cv::gpu::PyrLKOpticalFlow::dense(const GpuMat& prevImg, const GpuMat& nextI
     CV_Assert(prevImg.size() == nextImg.size() && prevImg.type() == nextImg.type());\r
     CV_Assert(derivLambda >= 0);\r
     CV_Assert(maxLevel >= 0 && winSize.width > 2 && winSize.height > 2);\r
-    \r
+\r
     if (useInitialFlow)\r
     {\r
         CV_Assert(u.size() == prevImg.size() && u.type() == CV_32FC1);\r
@@ -239,7 +251,7 @@ void cv::gpu::PyrLKOpticalFlow::dense(const GpuMat& prevImg, const GpuMat& nextI
 \r
     if (err)\r
         err->create(prevImg.size(), CV_32FC1);\r
-    \r
+\r
     // build the image pyramids.\r
     // we pad each level with +/-winSize.{width|height}\r
     // pixels to simplify the further patch extraction.\r
@@ -248,12 +260,12 @@ void cv::gpu::PyrLKOpticalFlow::dense(const GpuMat& prevImg, const GpuMat& nextI
     buildImagePyramid(nextImg, nextPyr_, true);\r
     buildImagePyramid(u, uPyr_, false);\r
     buildImagePyramid(v, vPyr_, false);\r
-    \r
+\r
     // dI/dx ~ Ix, dI/dy ~ Iy\r
 \r
     ensureSizeIsEnough(prevImg.rows + winSize.height * 2, prevImg.cols + winSize.width * 2, CV_16SC1, dx_buf_);\r
     ensureSizeIsEnough(prevImg.rows + winSize.height * 2, prevImg.cols + winSize.width * 2, CV_16SC1, dy_buf_);\r
-    \r
+\r
     loadConstants(1, minEigThreshold, make_int2(winSize.width, winSize.height), iters);\r
 \r
     DevMem2Df derr = err ? *err : DevMem2Df();\r
@@ -271,7 +283,7 @@ void cv::gpu::PyrLKOpticalFlow::dense(const GpuMat& prevImg, const GpuMat& nextI
 \r
         calcSharrDeriv(prevPyr_[level], dIdx, dIdy);\r
 \r
-        lkDense_gpu(prevPyr_[level], nextPyr_[level], dIdx, dIdy, uPyr_[level], vPyr_[level], \r
+        lkDense_gpu(prevPyr_[level], nextPyr_[level], dIdx, dIdy, uPyr_[level], vPyr_[level],\r
             level == 0 && err ? &derr : 0, getMinEigenVals);\r
 \r
         if (level == 0)\r
index cbc1348..26698ce 100644 (file)
@@ -124,7 +124,7 @@ void getFlowField(const Mat& u, const Mat& v, Mat& flowField)
         {\r
             float d = max(fabsf(ptr_u[j]), fabsf(ptr_v[j]));\r
 \r
-            if (d > maxDisplacement) \r
+            if (d > maxDisplacement)\r
                 maxDisplacement = d;\r
         }\r
     }\r
@@ -152,11 +152,16 @@ void getFlowField(const Mat& u, const Mat& v, Mat& flowField)
 int main(int argc, const char* argv[])\r
 {\r
     const char* keys =\r
-       "{ h  | help           | false | print help message }"\r
-       "{ l  | left           |       | specify left image }"\r
-       "{ r  | right          |       | specify right image }"\r
-       "{ g  | gray           | false | use grayscale sources [PyrLK Sparse] }"\r
-       "{ p  | points         | 4000  | specify points count [GoodFeatureToTrack] }";\r
+        "{ h            | help           | false | print help message }"\r
+        "{ l            | left           |       | specify left image }"\r
+        "{ r            | right          |       | specify right image }"\r
+        "{ gray         | gray           | false | use grayscale sources [PyrLK Sparse] }"\r
+        "{ win_size     | win_size       | 21    | specify windows size [PyrLK] }"\r
+        "{ max_level    | max_level      | 3     | specify max level [PyrLK] }"\r
+        "{ iters        | iters          | 30    | specify iterations count [PyrLK] }"\r
+        "{ deriv_lambda | deriv_lambda   | 0.5   | specify deriv lambda [PyrLK] }"\r
+        "{ points       | points         | 4000  | specify points count [GoodFeatureToTrack] }"\r
+        "{ min_dist     | min_dist       | 0     | specify minimal distance between points [GoodFeatureToTrack] }";\r
 \r
     CommandLineParser cmd(argc, argv, keys);\r
 \r
@@ -178,8 +183,13 @@ int main(int argc, const char* argv[])
     }\r
 \r
     bool useGray = cmd.get<bool>("gray");\r
+    int winSize = cmd.get<int>("win_size");\r
+    int maxLevel = cmd.get<int>("max_level");\r
+    int iters = cmd.get<int>("iters");\r
+    double derivLambda = cmd.get<double>("deriv_lambda");\r
     int points = cmd.get<int>("points");\r
-    \r
+    double minDist = cmd.get<double>("min_dist");\r
+\r
     Mat frame0 = imread(fname0);\r
     Mat frame1 = imread(fname1);\r
 \r
@@ -210,7 +220,7 @@ int main(int argc, const char* argv[])
 \r
     // goodFeaturesToTrack\r
 \r
-    GoodFeaturesToTrackDetector_GPU detector(points, 0.01, 0.0);\r
+    GoodFeaturesToTrackDetector_GPU detector(points, 0.01, minDist);\r
 \r
     GpuMat d_frame0Gray(frame0Gray);\r
     GpuMat d_prevPts;\r
@@ -221,6 +231,12 @@ int main(int argc, const char* argv[])
 \r
     PyrLKOpticalFlow d_pyrLK;\r
 \r
+    d_pyrLK.winSize.width = winSize;\r
+    d_pyrLK.winSize.height = winSize;\r
+    d_pyrLK.maxLevel = maxLevel;\r
+    d_pyrLK.iters = iters;\r
+    d_pyrLK.derivLambda = derivLambda;\r
+\r
     GpuMat d_frame0(frame0);\r
     GpuMat d_frame1(frame1);\r
     GpuMat d_frame1Gray(frame1Gray);\r
@@ -252,13 +268,13 @@ int main(int argc, const char* argv[])
     d_pyrLK.dense(d_frame0Gray, d_frame1Gray, d_u, d_v);\r
 \r
     // Draw flow field\r
-    \r
+\r
     Mat flowField;\r
     getFlowField(Mat(d_u), Mat(d_v), flowField);\r
 \r
     imshow("PyrLK [Dense] Flow Field", flowField);\r
 \r
-    #ifdef HAVE_OPENGL        \r
+    #ifdef HAVE_OPENGL\r
         setOpenGlContext("PyrLK [Dense]");\r
 \r
         GpuMat d_vertex, d_colors;\r