1 // This file is part of OpenCV project.
2 // It is subject to the license terms in the LICENSE file found in the top-level directory
3 // of this distribution and at http://opencv.org/license.html.
4 #ifndef _RLOF_LOCALFLOW_H_
5 #define _RLOF_LOCALFLOW_H_
6 #include <limits>
7 #include <math.h>
8 #include <float.h>
9 #include <stdio.h>
10 #include "opencv2/imgproc.hpp"
11 #include "opencv2/optflow/rlofflow.hpp"
12 //! Fast median estimation method based on @cite Tibshirani2008. This implementation relates to http://www.stat.cmu.edu/~ryantibs/median/
13 using namespace cv;
14 template<typename T>
quickselect(const Mat & inp,int k)15 T quickselect(const Mat & inp, int k)
16 {
17     unsigned long i;
18     unsigned long ir;
19     unsigned long j;
20     unsigned long l;
21     unsigned long mid;
22     Mat values = inp.clone();
23     T a;
24 
25     l = 0;
26     ir = MAX(values.rows, values.cols) - 1;
27     while(true)
28     {
29         if (ir <= l + 1)
30         {
31             if (ir == l + 1 && values.at<T>(ir) < values.at<T>(l))
32                 std::swap(values.at<T>(l), values.at<T>(ir));
33             return values.at<T>(k);
34         }
35         else
36         {
37             mid = (l + ir) >> 1;
38             std::swap(values.at<T>(mid), values.at<T>(l+1));
39             if (values.at<T>(l) > values.at<T>(ir))
40                 std::swap(values.at<T>(l), values.at<T>(ir));
41             if (values.at<T>(l+1) > values.at<T>(ir))
42                 std::swap(values.at<T>(l+1), values.at<T>(ir));
43             if (values.at<T>(l) > values.at<T>(l+1))
44                 std::swap(values.at<T>(l), values.at<T>(l+1));
45             i = l + 1;
46             j = ir;
47             a = values.at<T>(l+1);
48             while (true)
49             {
50                 do
51                 {
52                     i++;
53                 }
54                 while (values.at<T>(i) < a);
55                 do
56                 {
57                     j--;
58                 }
59                 while (values.at<T>(j) > a);
60                 if (j < i) break;
61                 std::swap(values.at<T>(i), values.at<T>(j));
62             }
63             values.at<T>(l+1) = values.at<T>(j);
64             values.at<T>(j) = a;
65             if (j >= static_cast<unsigned long>(k)) ir = j - 1;
66             if (j <= static_cast<unsigned long>(k)) l = i;
67         }
68     }
69 }
70 
71 namespace cv {
72 namespace optflow {
73 
74 class CImageBuffer
75 {
76 public:
CImageBuffer()77     CImageBuffer()
78         : m_Overwrite(true)
79     {}
setGrayFromRGB(const cv::Mat & inp)80     void setGrayFromRGB(const cv::Mat & inp)
81     {
82         if(m_Overwrite)
83             cv::cvtColor(inp, m_Image, cv::COLOR_BGR2GRAY);
84     }
setImage(const cv::Mat & inp)85     void setImage(const cv::Mat & inp)
86     {
87         if(m_Overwrite)
88             inp.copyTo(m_Image);
89     }
setBlurFromRGB(const cv::Mat & inp)90     void setBlurFromRGB(const cv::Mat & inp)
91     {
92         if(m_Overwrite)
93             cv::GaussianBlur(inp, m_BlurredImage, cv::Size(7,7), -1);
94     }
95 
96     int buildPyramid(cv::Size winSize, int maxLevel, float levelScale[2], bool withBlurredImage = false);
getImage(int level)97     cv::Mat & getImage(int level) {return m_ImagePyramid[level];}
98 
99     std::vector<cv::Mat>     m_ImagePyramid;
100     cv::Mat                  m_BlurredImage;
101     cv::Mat                  m_Image;
102     std::vector<cv::Mat>     m_CrossPyramid;
103     int                      m_maxLevel;
104     bool                     m_Overwrite;
105 };
106 
107 void calcLocalOpticalFlow(
108     const Mat prevImage,
109     const Mat currImage,
110     Ptr<CImageBuffer>  prevPyramids[2],
111     Ptr<CImageBuffer>  currPyramids[2],
112     const std::vector<Point2f> & prevPoints,
113     std::vector<Point2f> & currPoints,
114     const RLOFOpticalFlowParameter & param);
115 
116 }} // namespace
117 #endif
118