optical_flow.cpp
Go to the documentation of this file.
00001 /*************************************************************************
00002         > File Name: optical_flow.cpp
00003         > Author: yincanben
00004         > Mail: yincanben@163.com
00005         > Created Time: Tue 24 Mar 2015 04:22:42 PM CST
00006  ************************************************************************/
00007 
00008 //#include<iostream>
00009 //using namespace std;
00010 #include "optical_flow.h"
00011 OpticalFlow::OpticalFlow(){
00012     num_keypoints_param_= 50 ;
00013     matchscore_thresh_param_ = 10e8 ;
00014 
00015 }
00016 OpticalFlow::~OpticalFlow(){
00017 
00018 }
00019 
00020 void OpticalFlow::process(cv::Mat &input_image){
00021     cv::pyrDown(input_image, input_image) ;
00022 
00023     // Grab a new keyframe whenever we have lost more than half of our tracks
00024     if(key_corners_.size() < size_t(num_keypoints_param_ / 2)){
00025         cv::goodFeaturesToTrack(input_image, key_corners_, num_keypoints_param_, 0.01, 30);
00026         key_image_ = input_image.clone();
00027     }
00028     // Track the features from the keyframe to the current frame
00029     std::vector<cv::Point2f> new_corners;
00030     trackFeatures(key_image_, input_image, key_corners_, new_corners);
00031 
00032     cv::Mat warped_key_image ;
00033     if(new_corners.size() < size_t(num_keypoints_param_/2)){
00034         // If we didn't track enough points, then kill the keyframe
00035         key_corners_.clear();
00036     }else{
00037         // Find the homography between the last frame and the current frame
00038         cv::Mat homography = cv::findHomography(key_corners_, new_corners, CV_RANSAC);
00039 
00040         // Warp the keyframe image to the new image, and find the squared difference
00041         cv::warpPerspective(key_image_, warped_key_image, homography, key_image_.size());
00042         cv::Mat matchScore;
00043         cv::matchTemplate(input_image, warped_key_image, matchScore, CV_TM_SQDIFF);
00044         //ROS_INFO("Match Score: %f", matchScore.at<float>(0,0));
00045 
00046              // If the difference between the warped template and the new frame is too large,
00047              // then kill the keyframe
00048         if(matchScore.at<float>(0,0) > matchscore_thresh_param_)
00049             key_corners_.clear();
00050     }
00051     // Draw the warped keyframe
00052     if(key_corners_.size())
00053         cv::imshow("homography", warped_key_image);
00054 
00055     // Draw the features on the input image
00056     if(key_corners_.size())
00057         drawFeatures(input_image, key_corners_, new_corners);
00058     cv::imshow("tracker (press key for keyframe)", input_image);
00059 
00060     if(cv::waitKey(2) != -1)
00061         key_corners_.clear();
00062 
00063 }
00064 
00065 // ######################################################################
00067 void OpticalFlow::drawFeatures( cv::Mat & image, std::vector<cv::Point2f> const & old_corners, std::vector<cv::Point2f> const & new_corners ){
00068     assert(old_corners.size() == new_corners.size());
00069     for(size_t i=0; i<new_corners.size(); ++i){
00070         cv::rectangle(image, old_corners[i]-cv::Point2f(3,3), old_corners[i]+cv::Point2f(2,2), 255, 5);
00071         cv::rectangle(image, old_corners[i]-cv::Point2f(3,3), old_corners[i]+cv::Point2f(3,3), 0,   1);
00072 
00073         cv::rectangle(image, new_corners[i]-cv::Point2f(3,3), new_corners[i]+cv::Point2f(2,2), 0,   5);
00074         cv::rectangle(image, new_corners[i]-cv::Point2f(3,3), new_corners[i]+cv::Point2f(3,3), 255, 1);
00075 
00076         cv::line(image, old_corners[i], new_corners[i], 0,   5);
00077         cv::line(image, old_corners[i], new_corners[i], 255, 1);
00078     }
00079 }
00080 
00081 // ######################################################################
00083 void OpticalFlow::filterPoints( std::vector<cv::Point2f> & p1, std::vector<cv::Point2f> & p2, std::vector<unsigned char> const & status){
00084     std::vector<cv::Point2f> p1_filt;     p1_filt.reserve(p1.size());
00085     std::vector<cv::Point2f> p2_filt; p2_filt.reserve(p1.size());
00086 
00087     std::vector<cv::Point2f>::iterator p1_it = p1.begin();
00088     std::vector<cv::Point2f>::iterator p2_it = p2.begin();
00089     std::vector<unsigned char>::const_iterator status_it = status.begin();
00090 
00091     while(status_it != status.end()){
00092         if(*status_it > 0){
00093             p1_filt.push_back(*p1_it);
00094             p2_filt.push_back(*p2_it);
00095         }
00096         ++p1_it;
00097         ++p2_it;
00098         ++status_it;
00099     }
00100     p1 = p1_filt;
00101     p2 = p2_filt;
00102 }
00103 
00104 // ######################################################################
00106 
00114 void OpticalFlow::trackFeatures(cv::Mat key_image, cv::Mat curr_image, std::vector<cv::Point2f> & corners, std::vector<cv::Point2f> & new_corners){
00115     cv::Size const searchWindow(15, 15);
00116 
00117     new_corners.resize(corners.size());
00118 
00119     if(corners.size() == 0) return;
00120 
00121     // Perform the forward LK step
00122     std::vector<unsigned char> status(corners.size());
00123     std::vector<float> error(corners.size());
00124     calcOpticalFlowPyrLK(key_image, curr_image, corners, new_corners, status, error, searchWindow, 5);
00125 
00126     // Filter out any untrackable points
00127     filterPoints(corners, new_corners, status);
00128 
00129     if(corners.size() == 0) return;
00130 
00131     // Perform the backwards LK step
00132     std::vector<cv::Point2f> back_corners;
00133     calcOpticalFlowPyrLK(curr_image, key_image, new_corners, back_corners, status, error, searchWindow, 5);
00134 
00135     // Filter out points that either:
00136     // a) Are untrackable by LK (their status byte == 0)
00137     // or
00138     // b) Were tracked by the backward LK step to a position that was too far away from the original point. This indicates
00139     //    that even though LK though it had a good track, the point path was ambiguous.
00140     std::vector<cv::Point2f> filt_corners;
00141     std::vector<cv::Point2f> filt_old_corners;
00142     std::vector<cv::Point2f>::iterator corners_it = corners.begin();
00143     std::vector<cv::Point2f>::iterator new_corners_it = new_corners.begin();
00144     std::vector<cv::Point2f>::iterator back_corners_it = back_corners.begin();
00145     std::vector<unsigned char>::iterator status_it = status.begin();
00146     while(status_it != status.end()){
00147         float const dist = sqrt(pow(new_corners_it->y - back_corners_it->y, 2) + pow(new_corners_it->y - back_corners_it->y, 2));
00148         if(*status_it && dist < 10){
00149             filt_old_corners.push_back(*corners_it);
00150             filt_corners.push_back(*new_corners_it);
00151         }
00152         ++corners_it;
00153         ++new_corners_it;
00154         ++back_corners_it;
00155         ++status_it;
00156     }
00157     new_corners = filt_corners;
00158     corners     = filt_old_corners;
00159 }


micros_dynamic_objects_filter
Author(s):
autogenerated on Thu Jun 6 2019 17:55:18