diff --git a/include/tracking.hpp b/include/tracking.hpp index f80004c..8aa4498 100644 --- a/include/tracking.hpp +++ b/include/tracking.hpp @@ -3,7 +3,7 @@ #include #include -#include "opencv2/core/core.hpp" +#include "opencv2/opencv.hpp" class Tracker { public: @@ -11,3 +11,12 @@ class Tracker { virtual bool Init(const cv::Mat &frame, const cv::Rect &roi) = 0; virtual cv::Rect Track(const cv::Mat &frame) = 0; }; +class MedianFlowTracker : public Tracker { +public: + virtual bool Init(const cv::Mat &frame, const cv::Rect &roi); + virtual cv::Rect Track(const cv::Mat &frame); + +protected: + cv::Rect position_; + cv::Mat frame_; +}; \ No newline at end of file diff --git a/samples/tracking_demo.cpp b/samples/tracking_demo.cpp new file mode 100644 index 0000000..0d532e1 --- /dev/null +++ b/samples/tracking_demo.cpp @@ -0,0 +1,56 @@ +#include +#include + +#include "opencv2/core.hpp" +#include "opencv2/opencv.hpp" +#include "tracking.hpp" + +using namespace std; +using namespace cv; + +const char* kAbout = + "This is an empty application that can be treated as a template for your " + "own doing-something-cool applications."; + +const char* kOptions = + "{ v video | | video to process }" + "{ h ? help usage | | print help message }"; + +int main(int argc, const char** argv) { + // Parse command line arguments. + CommandLineParser parser(argc, argv, kOptions); + parser.about(kAbout); + + // If help option is given, print help message and exit. + if (parser.get("help")) { + parser.printMessage(); + return 0; + } + + // Do something cool. + VideoCapture cap; + if (parser.has("video")) + cap = VideoCapture(parser.get("video")); + else + cap = VideoCapture(0); + + if (!cap.isOpened()) + { + cout << "Failed to open video capture." << endl; + return 1; + } + + for (;;) + { + Mat frame; + cap >> frame; + MedianFlowTracker track; + track.Init(frame,Rect(25,25,50,50)); + track.Track(frame); + rectangle(frame, track.Track(frame), CV_RGB(255, 0, 255)); + if (frame.empty()) break; + imshow("x", frame); + if (cv::waitKey(30) >= 0) break; + } + return 0; +} diff --git a/src/tracking.cpp b/src/tracking.cpp index 26cbe06..2720d93 100644 --- a/src/tracking.cpp +++ b/src/tracking.cpp @@ -1,13 +1,69 @@ #include "tracking.hpp" #include +#include using std::string; using std::shared_ptr; using namespace cv; +using namespace std; +int compX( Point a, Point b) +{ + return a.x - b.x; +} +int compY(Point a, Point b) +{ + return a.y - b.y; +} -shared_ptr Tracker::CreateTracker(const string &name) { +shared_ptr Tracker::CreateTracker(const string &name) +{ + if (name == "median_flow") + { + return std::make_shared(); + } std::cerr << "Failed to create tracker with name '" << name << "'" << std::endl; return nullptr; } + +bool MedianFlowTracker::Init(const Mat & frame, const Rect & roi) +{ + Mat frame_ = frame; + Rect position_ = roi; + return true; +} + +Rect MedianFlowTracker::Track(const Mat & frame) +{ + vector corners; + vector corners_out; + vector Shift; + vector status; + vector err; + goodFeaturesToTrack(frame, corners, 100, 0.3, 7); + calcOpticalFlowPyrLK(frame_, frame, corners, corners_out, status, err); + int erased = 0; + + for (int i = 0; i < status.size(); i++) + if (!status[i]) + { + corners_out.erase(corners_out.begin() + i - erased); + corners.erase(corners.begin() + i - erased); + erased++; + } + + for(int i = 0; i < corners.size(); i++) + { + Shift[i].x = corners[i].x - corners_out[i].x; + Shift[i].y = corners[i].y - corners_out[i].y; + } + sort(Shift.begin(), Shift.end(), compX); + sort(Shift.begin(), Shift.end(), compY); + + + position_.x += Shift[Shift.size() / 2].x; + position_.y += Shift[Shift.size() / 2].y; + + return position_; +}