added hybrid (feature-based & meanshift-based) tracker (by Pushkar)

This commit is contained in:
Vadim Pisarevsky 2011-08-26 12:22:19 +00:00
parent f69aa40310
commit ae83fe7645
7 changed files with 1008 additions and 0 deletions

View File

@ -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<DMatch> matches;
Mat prev_image;
Mat prev_image_bw;
Rect prev_trackwindow;
Point2d prev_center;
int ittr;
vector<Point2f> 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

View File

@ -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;
}

View File

@ -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 <stdio.h>
#include <iostream>
#include <highgui.h>
#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<L2<float> > ();
}
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<KeyPoint> prev_keypoints, curr_keypoints;
vector<Point2f> 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<double> (0, 2);
prev_trackwindow.y += T.at<double> (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<uchar> status;
vector<float> 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;
}

View File

@ -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<double> (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<double> (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<double> (i, j) = 1.0 - (kernel.at<double> (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<double> (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<double> (0, 0);
curr_center.y = em_model.getMeans().at<double> (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;
}

View File

@ -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,

View File

@ -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 <cv.h>
#include <ml.h>
#include <cvaux.h>
#include <highgui.h>
#include <stdio.h>
#include <time.h>
#include <iostream>
#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 <test_file> \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;
}

BIN
samples/python2/common.pyc Normal file

Binary file not shown.