diff --git a/modules/contrib/include/opencv2/contrib/hybridtracker.hpp b/modules/contrib/include/opencv2/contrib/hybridtracker.hpp new file mode 100644 index 0000000000..c83c0eafa2 --- /dev/null +++ b/modules/contrib/include/opencv2/contrib/hybridtracker.hpp @@ -0,0 +1,228 @@ +//*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of Intel Corporation may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_HYBRIDTRACKER_H_ +#define __OPENCV_HYBRIDTRACKER_H_ + +#include "opencv2/core/core.hpp" +#include "opencv2/core/operations.hpp" +#include "opencv2/imgproc/imgproc.hpp" +#include "opencv2/features2d/features2d.hpp" +#include "opencv2/video/tracking.hpp" +#include "opencv2/ml/ml.hpp" + +#ifdef __cplusplus + +namespace cv +{ + +// Motion model for tracking algorithm. Currently supports objects that do not move much. +// To add Kalman filter +struct CV_EXPORTS CvMotionModel +{ + enum {LOW_PASS_FILTER = 0, KALMAN_FILTER = 1, EM = 2}; + + CvMotionModel() + { + } + + float low_pass_gain; // low pass gain + CvEMParams em_params; // EM parameters +}; + +// Mean Shift Tracker parameters for specifying use of HSV channel and CamShift parameters. +struct CV_EXPORTS CvMeanShiftTrackerParams +{ + enum { H = 0, HS = 1, HSV = 2 }; + CvMeanShiftTrackerParams(int tracking_type = CvMeanShiftTrackerParams::HS, + CvTermCriteria term_crit = CvTermCriteria()) + { + } + + int tracking_type; + float h_range[]; + float s_range[]; + float v_range[]; + CvTermCriteria term_crit; +}; + +// Feature tracking parameters +struct CV_EXPORTS CvFeatureTrackerParams +{ + enum { SIFT = 0, SURF = 1, OPTICAL_FLOW = 2 }; + CvFeatureTrackerParams(int feature_type = 0, int window_size = 0) + { + feature_type = 0; + window_size = 0; + } + + int feature_type; // Feature type to use + int window_size; // Window size in pixels around which to search for new window +}; + +// Hybrid Tracking parameters for specifying weights of individual trackers and motion model. +struct CV_EXPORTS CvHybridTrackerParams +{ + CvHybridTrackerParams(float ft_tracker_weight = 0.5, float ms_tracker_weight = 0.5, + CvFeatureTrackerParams ft_params = CvFeatureTrackerParams(), + CvMeanShiftTrackerParams ms_params = CvMeanShiftTrackerParams(), + CvMotionModel model = CvMotionModel()) + { + } + + float ft_tracker_weight; + float ms_tracker_weight; + CvFeatureTrackerParams ft_params; + CvMeanShiftTrackerParams ms_params; + CvEMParams em_params; + int motion_model; + float low_pass_gain; +}; + +// Performs Camshift using parameters from MeanShiftTrackerParams +class CV_EXPORTS CvMeanShiftTracker +{ +private: + Mat hsv, hue; + Mat backproj; + Mat mask, maskroi; + MatND hist; + Rect prev_trackwindow; + RotatedRect prev_trackbox; + Point2f prev_center; + +public: + CvMeanShiftTrackerParams params; + + CvMeanShiftTracker(); + CvMeanShiftTracker(CvMeanShiftTrackerParams _params = CvMeanShiftTrackerParams()); + ~CvMeanShiftTracker(); + void newTrackingWindow(Mat image, Rect selection); + RotatedRect updateTrackingWindow(Mat image); + Mat getHistogramProjection(int type); + void setTrackingWindow(Rect _window); + Rect getTrackingWindow(); + RotatedRect getTrackingEllipse(); + Point2f getTrackingCenter(); +}; + +// Performs SIFT/SURF feature tracking using parameters from FeatureTrackerParams +class CV_EXPORTS CvFeatureTracker +{ +private: + FeatureDetector* detector; + DescriptorExtractor* descriptor; + DescriptorMatcher* matcher; + vector matches; + + Mat prev_image; + Mat prev_image_bw; + Rect prev_trackwindow; + Point2d prev_center; + + int ittr; + vector features[2]; + +public: + Mat disp_matches; + CvFeatureTrackerParams params; + + CvFeatureTracker(); + CvFeatureTracker(CvFeatureTrackerParams params = CvFeatureTrackerParams(0,0)); + ~CvFeatureTracker(); + void newTrackingWindow(Mat image, Rect selection); + Rect updateTrackingWindow(Mat image); + Rect updateTrackingWindowWithSIFT(Mat image); + Rect updateTrackingWindowWithFlow(Mat image); + void setTrackingWindow(Rect _window); + Rect getTrackingWindow(); + Point2f getTrackingCenter(); +}; + +// Performs Hybrid Tracking and combines individual trackers using EM or filters +class CV_EXPORTS CvHybridTracker +{ +private: + CvMeanShiftTracker* mstracker; + CvFeatureTracker* fttracker; + + CvMat* samples; + CvMat* labels; + CvEM em_model; + + Rect prev_window; + Point2f prev_center; + Mat prev_proj; + RotatedRect trackbox; + + int ittr; + Point2f curr_center; + + inline float getL2Norm(Point2f p1, Point2f p2); + Mat getDistanceProjection(Mat image, Point2f center); + Mat getGaussianProjection(Mat image, int ksize, double sigma, Point2f center); + void updateTrackerWithEM(Mat image); + void updateTrackerWithLowPassFilter(Mat image); + +public: + CvHybridTrackerParams params; + CvHybridTracker(); + CvHybridTracker(CvHybridTrackerParams params = CvHybridTrackerParams()); + ~CvHybridTracker(); + + void newTracker(Mat image, Rect selection); + void updateTracker(Mat image); + Rect getTrackingWindow(); +}; + +typedef CvMotionModel MotionModel; +typedef CvMeanShiftTrackerParams MeanShiftTrackerParams; +typedef CvFeatureTrackerParams FeatureTrackerParams; +typedef CvHybridTrackerParams HybridTrackerParams; +typedef CvMeanShiftTracker MeanShiftTracker; +typedef CvFeatureTracker FeatureTracker; +typedef CvHybridTracker HybridTracker; +} + +#endif + +#endif diff --git a/modules/contrib/src/colortracker.cpp b/modules/contrib/src/colortracker.cpp new file mode 100644 index 0000000000..70f6fa04cc --- /dev/null +++ b/modules/contrib/src/colortracker.cpp @@ -0,0 +1,137 @@ +//*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of Intel Corporation may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ +#include "precomp.hpp" +#include "opencv2/contrib/hybridtracker.hpp" + +using namespace cv; +using namespace std; + +CvMeanShiftTracker::CvMeanShiftTracker(CvMeanShiftTrackerParams _params) : params(_params) +{ +} + +CvMeanShiftTracker::~CvMeanShiftTracker() +{ +} + +void CvMeanShiftTracker::newTrackingWindow(Mat image, Rect selection) +{ + hist.release(); + int channels[] = { 0, 0 , 1, 1}; + float hrange[] = { 0, 180 }; + float srange[] = { 0, 1 }; + const float* ranges[] = {hrange, srange}; + + cvtColor(image, hsv, CV_BGR2HSV); + inRange(hsv, Scalar(0, 30, MIN(10, 256)), Scalar(180, 256, MAX(10, 256)), mask); + + hue.create(hsv.size(), CV_8UC2); + mixChannels(&hsv, 1, &hue, 1, channels, 2); + + Mat roi(hue, selection); + Mat maskroi(mask, selection); + int ch[] = {0, 1}; + int chsize[] = {32, 32}; + calcHist(&roi, 1, ch, maskroi, hist, 1, chsize, ranges); + normalize(hist, hist, 0, 255, CV_MINMAX); + + prev_trackwindow = selection; +} + +RotatedRect CvMeanShiftTracker::updateTrackingWindow(Mat image) +{ + int channels[] = { 0, 0 , 1, 1}; + float hrange[] = { 0, 180 }; + float srange[] = { 0, 1 }; + const float* ranges[] = {hrange, srange}; + + cvtColor(image, hsv, CV_BGR2HSV); + inRange(hsv, Scalar(0, 30, MIN(10, 256)), Scalar(180, 256, MAX(10, 256)), mask); + hue.create(hsv.size(), CV_8UC2); + mixChannels(&hsv, 1, &hue, 1, channels, 2); + int ch[] = {0, 1}; + calcBackProject(&hue, 1, ch, hist, backproj, ranges); + backproj &= mask; + + prev_trackbox = CamShift(backproj, prev_trackwindow, TermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1)); + int cols = backproj.cols, rows = backproj.rows, r = (MIN(cols, rows) + 5) / 6; + prev_trackwindow = Rect(prev_trackwindow.x - r, prev_trackwindow.y - r, prev_trackwindow.x + r, + prev_trackwindow.y + r) & Rect(0, 0, cols, rows); + + prev_center.x = prev_trackwindow.x + prev_trackwindow.width / 2; + prev_center.y = prev_trackwindow.y + prev_trackwindow.height / 2; + +#ifdef DEBUG_HYTRACKER + ellipse(image, prev_trackbox, Scalar(0, 0, 255), 1, CV_AA); +#endif + + return prev_trackbox; +} + +Mat CvMeanShiftTracker::getHistogramProjection(int type) +{ + Mat ms_backproj_f(backproj.size(), type); + backproj.convertTo(ms_backproj_f, type); + return ms_backproj_f; +} + +void CvMeanShiftTracker::setTrackingWindow(Rect window) +{ + prev_trackwindow = window; +} + +Rect CvMeanShiftTracker::getTrackingWindow() +{ + return prev_trackwindow; +} + +RotatedRect CvMeanShiftTracker::getTrackingEllipse() +{ + return prev_trackbox; +} + +Point2f CvMeanShiftTracker::getTrackingCenter() +{ + return prev_center; +} + + diff --git a/modules/contrib/src/featuretracker.cpp b/modules/contrib/src/featuretracker.cpp new file mode 100644 index 0000000000..48bdfe88f8 --- /dev/null +++ b/modules/contrib/src/featuretracker.cpp @@ -0,0 +1,219 @@ +//*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of Intel Corporation may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ +#include "precomp.hpp" +#include +#include +#include +#include "opencv2/calib3d/calib3d.hpp" +#include "opencv2/contrib/hybridtracker.hpp" + +using namespace cv; + +CvFeatureTracker::CvFeatureTracker(CvFeatureTrackerParams _params) : + params(_params) +{ + switch (params.feature_type) + { + case CvFeatureTrackerParams::SIFT: + detector = new SiftFeatureDetector( + SIFT::DetectorParams::GET_DEFAULT_THRESHOLD(), + SIFT::DetectorParams::GET_DEFAULT_EDGE_THRESHOLD() + 0.7, + SIFT::CommonParams::DEFAULT_NOCTAVES + 4, + SIFT::CommonParams::DEFAULT_NOCTAVE_LAYERS + 2, + SIFT::CommonParams::DEFAULT_FIRST_OCTAVE, + SIFT::CommonParams::FIRST_ANGLE); + case CvFeatureTrackerParams::SURF: + detector = new SurfFeatureDetector(400, 3, 4); + default: + detector = new GoodFeaturesToTrackDetector(); + } + + descriptor = new SurfDescriptorExtractor(3, 4, false); + + matcher = new BruteForceMatcher > (); +} + +CvFeatureTracker::~CvFeatureTracker() +{ +} + +void CvFeatureTracker::newTrackingWindow(Mat image, Rect selection) +{ + image.copyTo(prev_image); + cvtColor(prev_image, prev_image_bw, CV_BGR2GRAY); + prev_trackwindow = selection; + prev_center.x = selection.x; + prev_center.y = selection.y; + ittr = 0; +} + +Rect CvFeatureTracker::updateTrackingWindow(Mat image) +{ + if(params.feature_type == CvFeatureTrackerParams::OPTICAL_FLOW) + return updateTrackingWindowWithFlow(image); + else + updateTrackingWindowWithSIFT(image); +} + +Rect CvFeatureTracker::updateTrackingWindowWithSIFT(Mat image) +{ + ittr++; + vector prev_keypoints, curr_keypoints; + vector prev_keys, curr_keys; + Mat prev_desc, curr_desc; + + Rect window = prev_trackwindow; + Mat mask = Mat::zeros(image.size(), CV_8UC1); + rectangle(mask, Point(window.x, window.y), Point(window.x + window.width, + window.y + window.height), Scalar(255), CV_FILLED); + + detector->detect(prev_image, prev_keypoints, mask); + + window.x -= params.window_size; + window.y -= params.window_size; + window.width += params.window_size; + window.height += params.window_size; + rectangle(mask, Point(window.x, window.y), Point(window.x + window.width, + window.y + window.height), Scalar(255), CV_FILLED); + + detector->detect(image, curr_keypoints, mask); + + if (prev_keypoints.size() > 4 && curr_keypoints.size() > 4) + { + descriptor->compute(prev_image, prev_keypoints, prev_desc); + descriptor->compute(image, curr_keypoints, curr_desc); + + matcher->match(prev_desc, curr_desc, matches); + + for (int i = 0; i < matches.size(); i++) + { + prev_keys.push_back(prev_keypoints[matches[i].queryIdx].pt); + curr_keys.push_back(curr_keypoints[matches[i].trainIdx].pt); + } + + Mat T = findHomography(prev_keys, curr_keys, CV_LMEDS); + + prev_trackwindow.x += T.at (0, 2); + prev_trackwindow.y += T.at (1, 2); + } + + prev_center.x = prev_trackwindow.x; + prev_center.y = prev_trackwindow.y; + prev_image = image; + return prev_trackwindow; +} + +Rect CvFeatureTracker::updateTrackingWindowWithFlow(Mat image) +{ + ittr++; + Size subPixWinSize(10,10), winSize(31,31); + Mat image_bw; + TermCriteria termcrit(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 20, 0.03); + vector status; + vector err; + + cvtColor(image, image_bw, CV_BGR2GRAY); + cvtColor(prev_image, prev_image_bw, CV_BGR2GRAY); + + if (ittr == 1) + { + Mat mask = Mat::zeros(image.size(), CV_8UC1); + rectangle(mask, Point(prev_trackwindow.x, prev_trackwindow.y), Point( + prev_trackwindow.x + prev_trackwindow.width, prev_trackwindow.y + + prev_trackwindow.height), Scalar(255), CV_FILLED); + goodFeaturesToTrack(image_bw, features[1], 500, 0.01, 20, mask, 3, 0, 0.04); + cornerSubPix(image_bw, features[1], subPixWinSize, Size(-1, -1), termcrit); + } + else + { + calcOpticalFlowPyrLK(prev_image_bw, image_bw, features[0], features[1], + status, err, winSize, 3, termcrit); + + Point2f feature0_center(0, 0); + Point2f feature1_center(0, 0); + int goodtracks = 0; + for (int i = 0; i < features[1].size(); i++) + { + if (status[i] == 1) + { + feature0_center.x += features[0][i].x; + feature0_center.y += features[0][i].y; + feature1_center.x += features[1][i].x; + feature1_center.y += features[1][i].y; + goodtracks++; + } + } + + feature0_center.x /= goodtracks; + feature0_center.y /= goodtracks; + feature1_center.x /= goodtracks; + feature1_center.y /= goodtracks; + + prev_center.x += (feature1_center.x - feature0_center.x); + prev_center.y += (feature1_center.y - feature0_center.y); + + prev_trackwindow.x = (int)prev_center.x; + prev_trackwindow.y = (int)prev_center.y; + } + + swap(features[0], features[1]); + image.copyTo(prev_image); +} + +void CvFeatureTracker::setTrackingWindow(Rect _window) +{ + prev_trackwindow = _window; +} + +Rect CvFeatureTracker::getTrackingWindow() +{ + return prev_trackwindow; +} + +Point2f CvFeatureTracker::getTrackingCenter() +{ + Point2f center(0, 0); + center.x = prev_center.x + prev_trackwindow.width/2.0; + center.y = prev_center.y + prev_trackwindow.height/2.0; + return center; +} + diff --git a/modules/contrib/src/hybridtracker.cpp b/modules/contrib/src/hybridtracker.cpp new file mode 100644 index 0000000000..eb750e8602 --- /dev/null +++ b/modules/contrib/src/hybridtracker.cpp @@ -0,0 +1,225 @@ +//*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2008-2011, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of Intel Corporation may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ +#include "precomp.hpp" +#include "opencv2/contrib/hybridtracker.hpp" + +using namespace cv; +using namespace std; + +CvHybridTracker::CvHybridTracker() { + +} + +CvHybridTracker::CvHybridTracker(HybridTrackerParams _params) : + params(_params) { + params.ft_params.feature_type = CvFeatureTrackerParams::SIFT; + mstracker = new CvMeanShiftTracker(params.ms_params); + fttracker = new CvFeatureTracker(params.ft_params); +} + +CvHybridTracker::~CvHybridTracker() { + if (mstracker != NULL) + delete mstracker; + if (fttracker != NULL) + delete fttracker; +} + +inline float CvHybridTracker::getL2Norm(Point2f p1, Point2f p2) { + float distance = (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y + - p2.y); + return sqrt(distance); +} + +Mat CvHybridTracker::getDistanceProjection(Mat image, Point2f center) { + Mat hist(image.size(), CV_64F); + + double lu = getL2Norm(Point(0, 0), center); + double ru = getL2Norm(Point(0, image.size().width), center); + double rd = getL2Norm(Point(image.size().height, image.size().width), + center); + double ld = getL2Norm(Point(image.size().height, 0), center); + + double max = (lu < ru) ? lu : ru; + max = (max < rd) ? max : rd; + max = (max < ld) ? max : ld; + + for (int i = 0; i < hist.rows; i++) + for (int j = 0; j < hist.cols; j++) + hist.at (i, j) = 1.0 - (getL2Norm(Point(i, j), center) + / max); + + return hist; +} + +Mat CvHybridTracker::getGaussianProjection(Mat image, int ksize, double sigma, + Point2f center) { + Mat kernel = getGaussianKernel(ksize, sigma, CV_64F); + double max = kernel.at (ksize / 2); + + Mat hist(image.size(), CV_64F); + for (int i = 0; i < hist.rows; i++) + for (int j = 0; j < hist.cols; j++) { + int pos = getL2Norm(Point(i, j), center); + if (pos < ksize / 2.0) + hist.at (i, j) = 1.0 - (kernel.at (pos) / max); + } + + return hist; +} + +void CvHybridTracker::newTracker(Mat image, Rect selection) { + prev_proj = Mat::zeros(image.size(), CV_64FC1); + prev_center = Point2f(selection.x + selection.width / 2.0, selection.y + + selection.height / 2.0); + prev_window = selection; + + mstracker->newTrackingWindow(image, selection); + fttracker->newTrackingWindow(image, selection); + + params.em_params.covs = NULL; + params.em_params.means = NULL; + params.em_params.probs = NULL; + params.em_params.nclusters = 1; + params.em_params.weights = NULL; + params.em_params.cov_mat_type = CvEM::COV_MAT_SPHERICAL; + params.em_params.start_step = CvEM::START_AUTO_STEP; + params.em_params.term_crit.max_iter = 10000; + params.em_params.term_crit.epsilon = 0.001; + params.em_params.term_crit.type = CV_TERMCRIT_ITER | CV_TERMCRIT_EPS; + + samples = cvCreateMat(2, 1, CV_32FC1); + labels = cvCreateMat(2, 1, CV_32SC1); + + ittr = 0; +} + +void CvHybridTracker::updateTracker(Mat image) { + ittr++; + + //copy over clean images: TODO + mstracker->updateTrackingWindow(image); + fttracker->updateTrackingWindowWithFlow(image); + + if (params.motion_model == CvMotionModel::EM) + updateTrackerWithEM(image); + else + updateTrackerWithLowPassFilter(image); + + // Regression to find new weights + Point2f ms_center = mstracker->getTrackingEllipse().center; + Point2f ft_center = fttracker->getTrackingCenter(); + +#ifdef DEBUG_HYTRACKER + circle(image, ms_center, 3, Scalar(0, 0, 255), -1, 8); + circle(image, ft_center, 3, Scalar(255, 0, 0), -1, 8); + putText(image, "ms", Point(ms_center.x+2, ms_center.y), FONT_HERSHEY_PLAIN, 0.75, Scalar(255, 255, 255)); + putText(image, "ft", Point(ft_center.x+2, ft_center.y), FONT_HERSHEY_PLAIN, 0.75, Scalar(255, 255, 255)); +#endif + + double ms_len = getL2Norm(ms_center, curr_center); + double ft_len = getL2Norm(ft_center, curr_center); + double total_len = ms_len + ft_len; + + params.ms_tracker_weight *= (ittr - 1); + params.ms_tracker_weight += (ms_len / total_len); + params.ms_tracker_weight /= ittr; + params.ft_tracker_weight *= (ittr - 1); + params.ft_tracker_weight += (ft_len / total_len); + params.ft_tracker_weight /= ittr; + + circle(image, prev_center, 3, Scalar(0, 0, 0), -1, 8); + circle(image, curr_center, 3, Scalar(255, 255, 255), -1, 8); + + prev_center = curr_center; + prev_window.x = (int)(curr_center.x-prev_window.width/2.0); + prev_window.y = (int)(curr_center.y-prev_window.height/2.0); + + mstracker->setTrackingWindow(prev_window); + fttracker->setTrackingWindow(prev_window); +} + +void CvHybridTracker::updateTrackerWithEM(Mat image) { + Mat ms_backproj = mstracker->getHistogramProjection(CV_64F); + Mat ms_distproj = getDistanceProjection(image, mstracker->getTrackingCenter()); + Mat ms_proj = ms_backproj.mul(ms_distproj); + + float dist_err = getL2Norm(mstracker->getTrackingCenter(), fttracker->getTrackingCenter()); + Mat ft_gaussproj = getGaussianProjection(image, dist_err, -1, fttracker->getTrackingCenter()); + Mat ft_distproj = getDistanceProjection(image, fttracker->getTrackingCenter()); + Mat ft_proj = ft_gaussproj.mul(ft_distproj); + + Mat proj = params.ms_tracker_weight * ms_proj + params.ft_tracker_weight * ft_proj + prev_proj; + + int sample_count = countNonZero(proj); + cvReleaseMat(&samples); + cvReleaseMat(&labels); + samples = cvCreateMat(sample_count, 2, CV_32FC1); + labels = cvCreateMat(sample_count, 1, CV_32SC1); + + int count = 0; + for (int i = 0; i < proj.rows; i++) + for (int j = 0; j < proj.cols; j++) + if (proj.at (i, j) > 0) { + samples->data.fl[count * 2] = i; + samples->data.fl[count * 2 + 1] = j; + count++; + } + + em_model.train(samples, 0, params.em_params, labels); + + curr_center.x = em_model.getMeans().at (0, 0); + curr_center.y = em_model.getMeans().at (0, 1); +} + +void CvHybridTracker::updateTrackerWithLowPassFilter(Mat image) { + RotatedRect ms_track = mstracker->getTrackingEllipse(); + Point2f ft_center = fttracker->getTrackingCenter(); + + float a = params.low_pass_gain; + curr_center.x = (1.0 - a) * prev_center.x + a * (params.ms_tracker_weight * ms_track.center.x + params.ft_tracker_weight * ft_center.x); + curr_center.y = (1.0 - a) * prev_center.y + a * (params.ms_tracker_weight * ms_track.center.y + params.ft_tracker_weight * ft_center.y); +} + +Rect CvHybridTracker::getTrackingWindow() { + return prev_window; +} + diff --git a/modules/highgui/include/opencv2/highgui/highgui.hpp b/modules/highgui/include/opencv2/highgui/highgui.hpp index 0f7e5d46e7..6468568c9a 100644 --- a/modules/highgui/include/opencv2/highgui/highgui.hpp +++ b/modules/highgui/include/opencv2/highgui/highgui.hpp @@ -129,6 +129,27 @@ typedef void (*MouseCallback )(int event, int x, int y, int flags, void* param); //! assigns callback for mouse events CV_EXPORTS void setMouseCallback( const string& windowName, MouseCallback onMouse, void* param=0); + +enum +{ + // 8bit, color or not + IMREAD_UNCHANGED =-1, + // 8bit, gray + IMREAD_GRAYSCALE =0, + // ?, color + IMREAD_COLOR =1, + // any depth, ? + IMREAD_ANYDEPTH =2, + // ?, any color + IMREAD_ANYCOLOR =4 +}; + +enum +{ + IMWRITE_JPEG_QUALITY =1, + IMWRITE_PNG_COMPRESSION =16, + IMWRITE_PXM_BINARY =32 +}; CV_EXPORTS_W Mat imread( const string& filename, int flags=1 ); CV_EXPORTS_W bool imwrite( const string& filename, InputArray img, diff --git a/samples/cpp/hybridtrackingsample.cpp b/samples/cpp/hybridtrackingsample.cpp new file mode 100644 index 0000000000..244a191a2d --- /dev/null +++ b/samples/cpp/hybridtrackingsample.cpp @@ -0,0 +1,178 @@ +/* + * + * Hybrid Tracking in OpenCV + * Usage: ./hybridtrackingsample live + * + * For Benchmarking against the Bonn benchmark dataset + * wget http://www.iai.uni-bonn.de/~kleind/tracking/datasets/seqG.zip + * unzip seqG.zip -d ./seqG + * ffmpeg -i seqG/Vid_G_rubikscube.avi seqG/%04d.png + * ./hytrack seqG/Vid_G_rubikscube.txt + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "opencv2/contrib/hybridtracker.hpp" + +using namespace cv; +using namespace std; + +Mat frame, image; +Rect selection; +Point origin; +bool selectObject = false; +int trackObject = 0; +int live = 1; + +void drawRectangle(Mat* image, Rect win) { + rectangle(*image, Point(win.x, win.y), Point(win.x + win.width, win.y + + win.height), Scalar(0, 255, 0), 2, CV_AA); +} + +void onMouse(int event, int x, int y, int, void*) { + if (selectObject) { + selection.x = MIN(x, origin.x); + selection.y = MIN(y, origin.y); + selection.width = std::abs(x - origin.x); + selection.height = std::abs(y - origin.y); + selection &= Rect(0, 0, image.cols, image.rows); + } + + switch (event) { + case CV_EVENT_LBUTTONDOWN: + origin = Point(x, y); + selection = Rect(x, y, 0, 0); + selectObject = true; + break; + case CV_EVENT_LBUTTONUP: + selectObject = false; + trackObject = -1; + break; + } +} + +void help() +{ + printf("Usage: ./hytrack live or ./hytrack \n\ +For Live View or Benchmarking. Read documentation is source code.\n\n"); +} + + +int main(int argc, char** argv) +{ + if(argc != 2) { + help(); + return 1; + } + + FILE* f; + VideoCapture cap; + char test_file[20] = ""; + char dir[20] = ""; + + if (strcmp(argv[1], "live") != 0) + { + sprintf(test_file, "%s", argv[1]); + f = fopen(test_file, "r"); + char vid[20]; + fscanf(f, "%s\n", vid); + cout << "Benchmarking against " << vid << endl; + live = 0; + } + else + { + cap.open(0); + if (!cap.isOpened()) + { + cout << "Failed to open camera" << endl; + return 0; + } + cout << "Opened camera" << endl; + cap.set(CV_CAP_PROP_FRAME_WIDTH, 640); + cap.set(CV_CAP_PROP_FRAME_HEIGHT, 480); + cap >> frame; + } + + HybridTrackerParams params; + // motion model params + params.motion_model = CvMotionModel::LOW_PASS_FILTER; + params.low_pass_gain = 0.1; + // mean shift params + params.ms_tracker_weight = 0.8; + params.ms_params.tracking_type = CvMeanShiftTrackerParams::HS; + // feature tracking params + params.ft_tracker_weight = 0.2; + params.ft_params.feature_type = CvFeatureTrackerParams::OPTICAL_FLOW; + params.ft_params.window_size = 0; + + HybridTracker tracker(params); + char img_file[20] = "seqG/0001.png"; + char img_file_num[10]; + namedWindow("Win", 1); + + setMouseCallback("Win", onMouse, 0); + + int i = 0; + float w[4]; + while(1) + { + i++; + if (live) + { + cap >> frame; + frame.copyTo(image); + } + else + { + fscanf(f, "%d %f %f %f %f\n", &i, &w[0], &w[1], &w[2], &w[3]); + sprintf(img_file, "seqG/%04d.png", i); + image = imread(img_file, CV_LOAD_IMAGE_COLOR); + selection = Rect(w[0]*image.cols, w[1]*image.rows, w[2]*image.cols, w[3]*image.rows); + } + + if (image.data == NULL) + continue; + + sprintf(img_file_num, "Frame: %d", i); + putText(image, img_file_num, Point(10, image.rows-20), FONT_HERSHEY_PLAIN, 0.75, Scalar(255, 255, 255)); + if (!image.empty()) + { + + if (trackObject < 0) + { + tracker.newTracker(image, selection); + trackObject = 1; + } + + if (trackObject) + { + tracker.updateTracker(image); + drawRectangle(&image, tracker.getTrackingWindow()); + } + + if (selectObject && selection.width > 0 && selection.height > 0) + { + Mat roi(image, selection); + bitwise_not(roi, roi); + } + + drawRectangle(&image, Rect(w[0]*image.cols, w[1]*image.rows, w[2]*image.cols, w[3]*image.rows)); + imshow("Win", image); + + waitKey(100); + } + else + i = 0; + } + + fclose(f); + return 0; + +} diff --git a/samples/python2/common.pyc b/samples/python2/common.pyc new file mode 100644 index 0000000000..0ec494cf18 Binary files /dev/null and b/samples/python2/common.pyc differ