From 0f22f32735468c0bf0791be4b44febe474648700 Mon Sep 17 00:00:00 2001 From: ivanvikhrev Date: Mon, 8 Oct 2018 21:51:43 +0300 Subject: [PATCH 1/2] raw --- include/tracking.hpp | 12 +++++ samples/tracking_demo.cpp | 104 ++++++++++++++++++++++++++++++++++++++ src/tracking.cpp | 88 ++++++++++++++++++++++++++++++-- 3 files changed, 200 insertions(+), 4 deletions(-) create mode 100644 samples/tracking_demo.cpp diff --git a/include/tracking.hpp b/include/tracking.hpp index f80004c..86e1ab4 100644 --- a/include/tracking.hpp +++ b/include/tracking.hpp @@ -4,6 +4,7 @@ #include #include "opencv2/core/core.hpp" +#include "opencv2/opencv.hpp" class Tracker { public: @@ -11,3 +12,14 @@ 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..9862b43 --- /dev/null +++ b/samples/tracking_demo.cpp @@ -0,0 +1,104 @@ +#include +#include +#include "tracking.hpp" + +using namespace std; +using namespace cv; + +struct MouseCallbackState +{ + bool is_selection_started; + bool is_selection_finished; + Point point_first; + Point point_second; +}; + +void OnMouse(int event, int x, int y, int flags, void* param) +{ + MouseCallbackState* mouse = (MouseCallbackState*)param; + + switch (event) + { + case EVENT_LBUTTONDOWN: + + mouse->is_selection_started = true; + mouse->is_selection_finished = false; + mouse->point_first.x = x; + mouse->point_first.y = y; + break; + + case EVENT_LBUTTONUP: + + mouse->is_selection_started = false; + mouse->is_selection_finished = true; + if (mouse->point_first.x != x && mouse->point_first.y != y) + { + mouse->point_second.x = x; + mouse->point_second.y = y; + } + break; + + case EVENT_MOUSEMOVE: + + if (mouse->is_selection_finished == false) + { + mouse->point_second.x = x; + mouse->point_second.y = y; + } + break; + } + +} +int main(int argc, const char** argv) +{ + //init + VideoCapture capture; + Mat frame; + Rect roi; + MedianFlowTracker track; + char c; + MouseCallbackState p; + std::string vidName = "C:\\MyProjects\\itseez-ss-2016-practice\\test\\test_data\\video\\pedestrians.mpg"; + bool flag = capture.open(vidName); + namedWindow("Track"); + setMouseCallback("Track", OnMouse, &p); + + if (flag) + { + flag = capture.read(frame); + + if (frame.empty()) + { + cout<< " --(!) No captured frame -- Break!"; + return -1; + } + + imshow("Track", frame); + // select obj + while (1) + { + c = waitKey(1000); + roi = Rect(p.point_first, p.point_second); + if ((p.point_first.x < p.point_second.x) && (p.point_first.y < p.point_second.y) && !roi.empty()) break; + } + rectangle(frame, roi, Scalar(255, 0, 0));//draw rect + imshow("Track", frame); + + if (!track.Init(frame, roi)) + { + cout << "Init error"; + return -1; + }; + while (capture.read(frame)) + { + track.Track(frame); + rectangle(frame, roi, Scalar(255, 0, 0));//draw rect + imshow("Track", frame); + } + capture.release(); + } + else + cout << "--(!)Error opening video capture" << endl; + + return 0; +} \ No newline at end of file diff --git a/src/tracking.cpp b/src/tracking.cpp index 26cbe06..3a86f40 100644 --- a/src/tracking.cpp +++ b/src/tracking.cpp @@ -1,13 +1,93 @@ #include "tracking.hpp" #include +#include using std::string; using std::shared_ptr; using namespace cv; -shared_ptr Tracker::CreateTracker(const string &name) { - std::cerr << "Failed to create tracker with name '" << name << "'" - << std::endl; - return nullptr; +shared_ptr Tracker::CreateTracker(const string &name) +{ + if (name == "median_flow") + { + return std::make_shared(); + } + else + { + std::cerr << "Failed to create tracker with name '" << name << "'" + << std::endl; + return nullptr; + } + +} + +bool MedianFlowTracker::Init(const cv::Mat &frame, const cv::Rect &roi) +{ + if (frame.empty()) return false; + if (roi.empty()) return false; + frame_ = frame; + position_ = roi; + return true; +} + +cv::Rect MedianFlowTracker::Track(const cv::Mat & frame) +{ + //init + TermCriteria termcrit(TermCriteria::COUNT | TermCriteria::EPS, 20, 0.03); + Size subPixWinSize(10, 10), winSize(31, 31); + Mat tmp, tmp_gray, next_gray, prev_gray; + std::vector features_prev, features_next; // Mat? + std::vector status; + std::vector err; + frame_(position_).copyTo(tmp); + + // find features + cvtColor(tmp, tmp_gray, COLOR_BGR2GRAY); + goodFeaturesToTrack(tmp_gray, features_prev, -1, 0.01, 10); + assert(features_prev.size() > 0); + + //calc optical flow + cvtColor(frame_, prev_gray, COLOR_BGR2GRAY); + cvtColor(frame, next_gray, COLOR_BGR2GRAY); + calcOpticalFlowPyrLK(prev_gray, next_gray, features_prev, features_next, status, err, + winSize, 3, termcrit, 0, 0.001); + + //filtration bad points + + size_t i, k; // counters + + for( i = k = 0; i < features_next.size(); i++ ) + { + if (!status[i]) + continue; + features_prev[k++] = features_prev[i]; + features_next[k++] = features_next[i]; + + } + features_prev.resize(k); // new points + features_next.resize(k); + + //find median X and Y offsets + std::vector offsetX; + std::vector offsetY; + Point2f newObjCenter; + for (i = 0; i < features_next.size(); i++) + { + offsetX[i] = features_next[i].x - features_prev[i].x; + offsetY[i] = features_next[i].y - features_prev[i].y; + } + + float medianX , medianY; + + std::sort(offsetX.begin(), offsetX.end()); + std::sort(offsetY.begin(), offsetY.end()); + + medianX = (int)offsetX[offsetX.size()/2]; + medianY = (int)offsetY[offsetY.size()/2]; + + // new rect position + Rect newPos(medianX - position_.width / 2, medianY - position_.height / 2, position_.width, position_.height); + + return newPos; } From d734ac11d331bcd7767e41295724cfad6579e38b Mon Sep 17 00:00:00 2001 From: ivanvikhrev Date: Mon, 8 Oct 2018 22:32:04 +0300 Subject: [PATCH 2/2] dont crash dont work --- samples/tracking_demo.cpp | 17 +++++++++++------ src/tracking.cpp | 12 +++++++----- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/samples/tracking_demo.cpp b/samples/tracking_demo.cpp index 9862b43..6a30bc6 100644 --- a/samples/tracking_demo.cpp +++ b/samples/tracking_demo.cpp @@ -81,24 +81,29 @@ int main(int argc, const char** argv) roi = Rect(p.point_first, p.point_second); if ((p.point_first.x < p.point_second.x) && (p.point_first.y < p.point_second.y) && !roi.empty()) break; } - rectangle(frame, roi, Scalar(255, 0, 0));//draw rect + rectangle(frame, roi, Scalar(255, 0, 255));//draw rect imshow("Track", frame); - + + waitKey(1000); + if (!track.Init(frame, roi)) { cout << "Init error"; return -1; - }; + } + while (capture.read(frame)) { - track.Track(frame); - rectangle(frame, roi, Scalar(255, 0, 0));//draw rect + roi = track.Track(frame); + rectangle(frame, roi, Scalar(255, 0, 255));//draw rect imshow("Track", frame); + c = waitKey(33); + if (c == 27) break; } capture.release(); } else cout << "--(!)Error opening video capture" << endl; - + waitKey(0); return 0; } \ No newline at end of file diff --git a/src/tracking.cpp b/src/tracking.cpp index 3a86f40..0d0b87c 100644 --- a/src/tracking.cpp +++ b/src/tracking.cpp @@ -40,11 +40,12 @@ cv::Rect MedianFlowTracker::Track(const cv::Mat & frame) std::vector features_prev, features_next; // Mat? std::vector status; std::vector err; - frame_(position_).copyTo(tmp); + tmp = frame_(position_); + //frame_(position_).copyTo(tmp); // find features cvtColor(tmp, tmp_gray, COLOR_BGR2GRAY); - goodFeaturesToTrack(tmp_gray, features_prev, -1, 0.01, 10); + goodFeaturesToTrack(tmp_gray, features_prev, 100 , 0.01, 10); assert(features_prev.size() > 0); //calc optical flow @@ -61,7 +62,7 @@ cv::Rect MedianFlowTracker::Track(const cv::Mat & frame) { if (!status[i]) continue; - features_prev[k++] = features_prev[i]; + features_prev[k] = features_prev[i]; features_next[k++] = features_next[i]; } @@ -72,10 +73,11 @@ cv::Rect MedianFlowTracker::Track(const cv::Mat & frame) std::vector offsetX; std::vector offsetY; Point2f newObjCenter; + for (i = 0; i < features_next.size(); i++) { - offsetX[i] = features_next[i].x - features_prev[i].x; - offsetY[i] = features_next[i].y - features_prev[i].y; + offsetX.push_back( features_next[i].x - features_prev[i].x); + offsetY.push_back( features_next[i].y - features_prev[i].y); } float medianX , medianY;