diff --git a/.gitignore b/.gitignore index fd44ca29..bbfed659 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ *.csv *.out *.png +*.so mnist/ data/ caffe/ @@ -22,3 +23,7 @@ ehthumbs.db Icon? Thumbs.db *.swp + +# CMake # +cmake-build-debug/ +CMakeLists.txt diff --git a/src/yolo_v2_class.cpp b/src/yolo_v2_class.cpp index 7e170e5c..1a5ccac2 100644 --- a/src/yolo_v2_class.cpp +++ b/src/yolo_v2_class.cpp @@ -33,6 +33,17 @@ struct detector_gpu_t{ unsigned int *track_id; }; +#ifdef OPENCV +cv::Scalar obj_id_to_color(int obj_id) +{ + int const colors[6][3] = { { 1,0,1 },{ 0,0,1 },{ 0,1,1 },{ 0,1,0 },{ 1,1,0 },{ 1,0,0 } }; + int const offset = obj_id * 123457 % 6; + int const color_scale = 150 + (obj_id * 123457) % 100; + cv::Scalar color(colors[offset][0], colors[offset][1], colors[offset][2]); + color *= color_scale; + return color; +} +#endif YOLODLL_API Detector::Detector(std::string cfg_filename, std::string weight_filename, int gpu_id) : cur_gpu_id(gpu_id) { diff --git a/src/yolo_v2_class.hpp b/src/yolo_v2_class.hpp index 8abb9e2f..f93abaa0 100644 --- a/src/yolo_v2_class.hpp +++ b/src/yolo_v2_class.hpp @@ -145,7 +145,7 @@ private: -#if defined(TRACK_OPTFLOW) && defined(OPENCV) +#if defined(TRACK_OPTFLOW) && defined(OPENCV) && defined(GPU) #include #include @@ -319,6 +319,130 @@ public: return result_bbox_vec; } +}; + +#elif defined(TRACK_OPTFLOW) && defined(OPENCV) + +#include + +class Tracker_optflow { +public: + const int flow_error; + + + Tracker_optflow(int win_size = 9, int max_level = 3, int iterations = 8000, int _flow_error = -1) : + flow_error((_flow_error > 0)? _flow_error:(win_size*4)) + { + sync_PyrLKOpticalFlow = cv::SparsePyrLKOpticalFlow::create(); + sync_PyrLKOpticalFlow->setWinSize(cv::Size(win_size, win_size)); // 9, 15, 21, 31 + sync_PyrLKOpticalFlow->setMaxLevel(max_level); // +- 3 pt + + } + + // just to avoid extra allocations + cv::Mat src_mat; + cv::Mat dst_mat, dst_grey; + cv::Mat prev_pts_flow, cur_pts_flow; + cv::Mat status, err; + + cv::Mat src_grey; // used in both functions + cv::Ptr sync_PyrLKOpticalFlow; + + std::vector cur_bbox_vec; + std::vector good_bbox_vec_flags; + + void update_cur_bbox_vec(std::vector _cur_bbox_vec) + { + cur_bbox_vec = _cur_bbox_vec; + good_bbox_vec_flags = std::vector(cur_bbox_vec.size(), true); + cv::Mat prev_pts, cur_pts_flow; + + for (auto &i : cur_bbox_vec) { + float x_center = (i.x + i.w / 2.0F); + float y_center = (i.y + i.h / 2.0F); + prev_pts.push_back(cv::Point2f(x_center, y_center)); + } + + if (prev_pts.rows == 0) + prev_pts_flow = cv::Mat(); + else + cv::transpose(prev_pts, prev_pts_flow); + } + + + void update_tracking_flow(cv::Mat new_src_mat, std::vector _cur_bbox_vec) + { + if (new_src_mat.channels() == 3) { + if (src_mat.cols == 0) { + src_mat = cv::Mat(new_src_mat.size(), new_src_mat.type()); + src_grey = cv::Mat(new_src_mat.size(), CV_8UC1); + } + + update_cur_bbox_vec(_cur_bbox_vec); + + src_mat = new_src_mat; + cv::cvtColor(src_mat, src_grey, CV_BGR2GRAY, 1); + } + } + + + std::vector tracking_flow(cv::Mat new_dst_mat, bool check_error = true) + { + if (sync_PyrLKOpticalFlow.empty()) { + std::cout << "sync_PyrLKOpticalFlow isn't initialized \n"; + return cur_bbox_vec; + } + + if (dst_mat.cols == 0) { + dst_mat = cv::Mat(new_dst_mat.size(), new_dst_mat.type()); + dst_grey = cv::Mat(new_dst_mat.size(), CV_8UC1); + } + + dst_mat = new_dst_mat; + cv::cvtColor(dst_mat, dst_grey, CV_BGR2GRAY, 1); + + if (src_grey.rows != dst_grey.rows || src_grey.cols != dst_grey.cols) { + src_grey = dst_grey.clone(); + return cur_bbox_vec; + } + + ////sync_PyrLKOpticalFlow_gpu.sparse(src_grey_gpu, dst_grey_gpu, prev_pts_flow_gpu, cur_pts_flow_gpu, status_gpu, &err_gpu); // OpenCV 2.4.x + sync_PyrLKOpticalFlow->calc(src_grey, dst_grey, prev_pts_flow, cur_pts_flow, status, err); // OpenCV 3.x + + dst_grey.copyTo(src_grey); + + std::vector result_bbox_vec; + + if (err.cols == cur_bbox_vec.size() && status.cols == cur_bbox_vec.size()) + { + for (size_t i = 0; i < cur_bbox_vec.size(); ++i) + { + cv::Point2f cur_key_pt = cur_pts_flow.at(0, i); + cv::Point2f prev_key_pt = prev_pts_flow.at(0, i); + + float moved_x = cur_key_pt.x - prev_key_pt.x; + float moved_y = cur_key_pt.y - prev_key_pt.y; + + if (abs(moved_x) < 100 && abs(moved_y) < 100 && good_bbox_vec_flags[i]) + if (err.at(0, i) < flow_error && status.at(0, i) != 0 && + ((float)cur_bbox_vec[i].x + moved_x) > 0 && ((float)cur_bbox_vec[i].y + moved_y) > 0) + { + cur_bbox_vec[i].x += moved_x + 0.5; + cur_bbox_vec[i].y += moved_y + 0.5; + result_bbox_vec.push_back(cur_bbox_vec[i]); + } + else good_bbox_vec_flags[i] = false; + else good_bbox_vec_flags[i] = false; + + //if(!check_error && !good_bbox_vec_flags[i]) result_bbox_vec.push_back(cur_bbox_vec[i]); + } + } + + prev_pts_flow = cur_pts_flow; + + return result_bbox_vec; + } + }; #else @@ -329,14 +453,7 @@ class Tracker_optflow {}; #ifdef OPENCV -cv::Scalar obj_id_to_color(int obj_id) { - int const colors[6][3] = { { 1,0,1 },{ 0,0,1 },{ 0,1,1 },{ 0,1,0 },{ 1,1,0 },{ 1,0,0 } }; - int const offset = obj_id * 123457 % 6; - int const color_scale = 150 + (obj_id * 123457) % 100; - cv::Scalar color(colors[offset][0], colors[offset][1], colors[offset][2]); - color *= color_scale; - return color; -} +cv::Scalar obj_id_to_color(int obj_id); class preview_boxes_t { enum { frames_history = 30 }; // how long to keep the history saved