00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 #include <cpl_visual_features/motion/dense_lk.h>
00036 #include <opencv2/imgproc/imgproc.hpp>
00037 
00038 namespace cpl_visual_features
00039 {
00040 
00041 DenseLKFlow::DenseLKFlow(int win_size, int num_levels) :
00042     win_size_(win_size), max_level_(num_levels-1)
00043 {
00044   
00045   cv::getDerivKernels(dy_kernel_, dx_kernel_, 1, 0, CV_SCHARR, true, CV_32F);
00046   cv::flip(dy_kernel_, dy_kernel_, -1);
00047   g_kernel_ = cv::getGaussianKernel(3, 2.0, CV_32F);
00048   optic_g_kernel_ = cv::getGaussianKernel(5, 10.0, CV_32F);
00049   cv::transpose(dy_kernel_, dx_kernel_);
00050 }
00051 
00052 DenseLKFlow::~DenseLKFlow()
00053 {
00054 }
00055 
00056 std::vector<cv::Mat> DenseLKFlow::operator()(cv::Mat& cur_frame,
00057                                              cv::Mat& prev_frame,
00058                                              bool color_in)
00059 {
00060   
00061   if (color_in)
00062   {
00063     cv::Mat tmp_bw(cur_frame.size(), CV_8UC1);
00064     cv::Mat cur_bw(cur_frame.size(), CV_32FC1);
00065     cv::Mat prev_bw(prev_frame.size(), CV_32FC1);
00066     cv::cvtColor(cur_frame, tmp_bw, CV_BGR2GRAY);
00067     tmp_bw.convertTo(cur_bw, CV_32FC1, 1.0/255, 0);
00068     cv::cvtColor(prev_frame, tmp_bw, CV_BGR2GRAY);
00069     tmp_bw.convertTo(prev_bw, CV_32FC1, 1.0/255, 0);
00070     return hierarchy(cur_bw, prev_bw);
00071   }
00072   else
00073   {
00074     return hierarchy(cur_frame, prev_frame);
00075   }
00076 }
00077 
00078 std::vector<cv::Mat> DenseLKFlow::hierarchy(cv::Mat& f2, cv::Mat& f1)
00079 {
00080   const int divisor = std::pow(2,max_level_);
00081   cv::Mat Dx(f2.rows/divisor, f2.cols/divisor, CV_32FC1, cv::Scalar(0.0));
00082   cv::Mat Dy = Dx.clone();
00083   std::vector<cv::Mat> g1s;
00084   std::vector<cv::Mat> g2s;
00085   cv::buildPyramid(f1, g1s, max_level_);
00086   cv::buildPyramid(f2, g2s, max_level_);
00087   std::vector<cv::Mat> flow_outs;
00088 
00089   for (int l = max_level_; l >= 0; --l)
00090   {
00091     if (l != max_level_)
00092     {
00093       Dx = expand(Dx);
00094       Dy = expand(Dy);
00095     }
00096     cv::Mat W = warp(g1s[l], Dx, Dy);
00097     flow_outs = baseLK(g2s[l], W);
00098     Dx = Dx + flow_outs[0];
00099     Dy = Dy + flow_outs[1];
00100     Dx = smooth(Dx);
00101     Dy = smooth(Dy);
00102   }
00103   std::vector<cv::Mat> total_outs;
00104   total_outs.push_back(Dx);
00105   total_outs.push_back(Dy);
00106   return total_outs;
00107 }
00108 
00109 std::vector<cv::Mat> DenseLKFlow::baseLK(cv::Mat& cur_bw, cv::Mat& prev_bw)
00110 {
00111   cv::Mat Ix(cur_bw.size(), CV_32FC1);
00112   cv::Mat Iy(cur_bw.size(), CV_32FC1);
00113   cv::Mat cur_blur(cur_bw.size(), cur_bw.type());
00114   cv::Mat prev_blur(prev_bw.size(), prev_bw.type());
00115   cv::filter2D(cur_bw, cur_blur, CV_32F, g_kernel_);
00116   cv::filter2D(prev_bw, prev_blur, CV_32F, g_kernel_);
00117   cv::Mat It = cur_blur - prev_blur;
00118 
00119   
00120   cv::filter2D(cur_bw, Ix, CV_32F, dx_kernel_);
00121   cv::filter2D(cur_bw, Iy, CV_32F, dy_kernel_);
00122 
00123   int win_radius = win_size_/2;
00124   cv::Mat flow_u(cur_bw.size(), CV_32FC1, cv::Scalar(0.0));
00125   cv::Mat flow_v(cur_bw.size(), CV_32FC1, cv::Scalar(0.0));
00126   for (int r = win_radius; r < Ix.rows-win_radius; ++r)
00127   {
00128     for (int c = win_radius; c < Ix.cols-win_radius; ++c)
00129     {
00130       float sIxx = 0.0;
00131       float sIyy = 0.0;
00132       float sIxy = 0.0;
00133       float sIxt = 0.0;
00134       float sIyt = 0.0;
00135       for (int y = r-win_radius; y <= r+win_radius; ++y)
00136       {
00137         for (int x = c-win_radius; x <= c+win_radius; ++x)
00138         {
00139           sIxx += Ix.at<float>(y,x)*Ix.at<float>(y,x);
00140           sIyy += Iy.at<float>(y,x)*Iy.at<float>(y,x);
00141           sIxy += Ix.at<float>(y,x)*Iy.at<float>(y,x);
00142           sIxt += Ix.at<float>(y,x)*It.at<float>(y,x);
00143           sIyt += Iy.at<float>(y,x)*It.at<float>(y,x);
00144         }
00145       }
00146 
00147       const float det = sIxx*sIyy - sIxy*sIxy;
00148       const float trace = sIxx+sIyy;
00149       cv::Vec2f uv;
00150       const double r_score = trace*trace/det;
00151       if (det == 0.0 || r_score > r_thresh_)
00152       {
00153         uv[0] = 0.0;
00154         uv[1] = 0.0;
00155       }
00156       else
00157       {
00158         uv[0] = (-sIyy*sIxt + sIxy*sIyt)/det;
00159         uv[1] = (sIxy*sIxt - sIxx*sIyt)/det;
00160       }
00161       flow_u.at<float>(r,c) = uv[0];
00162       flow_v.at<float>(r,c) = uv[1];
00163     }
00164   }
00165   std::vector<cv::Mat> outs;
00166   outs.push_back(flow_u);
00167   outs.push_back(flow_v);
00168   return outs;
00169 }
00170 
00171 cv::Mat DenseLKFlow::reduce(cv::Mat& input)
00172 {
00173   cv::Mat output;
00174   cv::pyrDown(input, output);
00175   return output;
00176 }
00177 
00178 cv::Mat DenseLKFlow::expand(cv::Mat& input)
00179 {
00180   cv::Mat output(input.rows*2, input.cols*2, CV_32FC1);
00181   cv::pyrUp(input, output, output.size());
00182   return output;
00183 }
00184 
00185 cv::Mat DenseLKFlow::smooth(cv::Mat& input, int n)
00186 {
00187   cv::Mat sm = input.clone();
00188 #ifdef MEDIAN_FILTER_FLOW
00189   cv::medianBlur(input, sm, 3);
00190 #else // MEDIAN_FILTER_FLOW
00191   for (int l = 0; l < n; ++l)
00192   {
00193     sm = reduce(sm);
00194   }
00195   for (int l = 0; l < n; ++l)
00196   {
00197     sm = expand(sm);
00198   }
00199 #endif // MEDIAN_FILTER_FLOW
00200   return sm;
00201 }
00202 
00203 cv::Mat DenseLKFlow::warp(cv::Mat& i2, cv::Mat& vx, cv::Mat& vy)
00204 {
00205   cv::Mat warpI2(i2.rows, i2.cols, i2.type(), cv::Scalar(0.0));
00206   
00207   cv::Mat map_x(vx.rows, vx.cols, CV_32FC1);
00208   cv::Mat map_y(vy.rows, vy.cols, CV_32FC1);
00209 
00210   for (int y = 0; y < map_x.rows; ++y)
00211   {
00212     for (int x = 0; x < map_x.cols; ++x)
00213     {
00214       map_x.at<float>(y,x) = x + vx.at<float>(y,x);
00215       map_y.at<float>(y,x) = y + vy.at<float>(y,x);
00216     }
00217   }
00218 
00219   
00220   cv::remap(i2, warpI2, map_x, map_y, cv::INTER_LINEAR);
00221 
00222   
00223   
00224   
00225   
00226   
00227   
00228   
00229   
00230   
00231   
00232   return warpI2;
00233 }
00234 
00235 
00236 
00237 
00238 void DenseLKFlow::setWinSize(int win_size)
00239 {
00240   win_size_ = win_size;
00241 }
00242 
00243 void DenseLKFlow::setNumLevels(int num_levels)
00244 {
00245   max_level_ = num_levels-1;
00246 }
00247 }