added hybrid (feature-based & meanshift-based) tracker (by Pushkar)
This commit is contained in:
parent
f69aa40310
commit
ae83fe7645
228
modules/contrib/include/opencv2/contrib/hybridtracker.hpp
Normal file
228
modules/contrib/include/opencv2/contrib/hybridtracker.hpp
Normal 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
|
137
modules/contrib/src/colortracker.cpp
Normal file
137
modules/contrib/src/colortracker.cpp
Normal 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;
|
||||
}
|
||||
|
||||
|
219
modules/contrib/src/featuretracker.cpp
Normal file
219
modules/contrib/src/featuretracker.cpp
Normal 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;
|
||||
}
|
||||
|
225
modules/contrib/src/hybridtracker.cpp
Normal file
225
modules/contrib/src/hybridtracker.cpp
Normal 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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
178
samples/cpp/hybridtrackingsample.cpp
Normal file
178
samples/cpp/hybridtrackingsample.cpp
Normal 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
BIN
samples/python2/common.pyc
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user