00001
00002
00003
00004
00005
00006
00007
00008
00009
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
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
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
00035 key_corners_.clear();
00036 }else{
00037
00038 cv::Mat homography = cv::findHomography(key_corners_, new_corners, CV_RANSAC);
00039
00040
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
00045
00046
00047
00048 if(matchScore.at<float>(0,0) > matchscore_thresh_param_)
00049 key_corners_.clear();
00050 }
00051
00052 if(key_corners_.size())
00053 cv::imshow("homography", warped_key_image);
00054
00055
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
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
00127 filterPoints(corners, new_corners, status);
00128
00129 if(corners.size() == 0) return;
00130
00131
00132 std::vector<cv::Point2f> back_corners;
00133 calcOpticalFlowPyrLK(curr_image, key_image, new_corners, back_corners, status, error, searchWindow, 5);
00134
00135
00136
00137
00138
00139
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 }