parent
f69aa40310
commit
ae83fe7645
7 changed files with 1008 additions and 0 deletions
@ -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 |
@ -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; |
||||
} |
||||
|
||||
|
@ -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; |
||||
} |
||||
|
@ -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; |
||||
} |
||||
|
@ -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; |
||||
|
||||
} |
Binary file not shown.
Loading…
Reference in new issue