TrackerFeatures.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ALVAR, A Library for Virtual and Augmented Reality.
3  *
4  * Copyright 2007-2012 VTT Technical Research Centre of Finland
5  *
6  * Contact: VTT Augmented Reality Team <alvar.info@vtt.fi>
7  * <http://www.vtt.fi/multimedia/alvar.html>
8  *
9  * ALVAR is free software; you can redistribute it and/or modify it under the
10  * terms of the GNU Lesser General Public License as published by the Free
11  * Software Foundation; either version 2.1 of the License, or (at your option)
12  * any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
17  * for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with ALVAR; if not, see
21  * <http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html>.
22  */
23 
24 #include "TrackerFeatures.h"
25 #include <cv.h>
26 
27 using namespace std;
28 
29 namespace alvar {
30 using namespace std;
31 
32 TrackerFeatures::TrackerFeatures(int _max_features, int _min_features, double _quality_level, double _min_distance, int _pyr_levels, int _win_size) :
33  x_res(0), y_res(0), frame_count(0), quality_level(0), min_distance(0), min_features(0), max_features(0), status(0),
34  img_eig(0), img_tmp(0), gray(0), prev_gray(0), pyramid(0), prev_pyramid(0), mask(0), next_id(0), win_size(0), pyr_levels(0),
35  prev_features(0), features(0), prev_feature_count(0), feature_count(0), prev_ids(0), ids(0)
36 {
37  next_id=1; // When this should be reset?
38  pyr_levels = _pyr_levels;
39  win_size = _win_size;
40  ChangeSettings(_max_features, _min_features, _quality_level, _min_distance);
41 }
42 
44  if (status) delete [] status;
45  if (prev_features) delete [] prev_features;
46  if (features) delete [] features;
47  if (prev_ids) delete [] prev_ids;
48  if (ids) delete [] ids;
49  if (img_eig) cvReleaseImage(&img_eig);
50  if (img_tmp) cvReleaseImage(&img_tmp);
51  if (gray) cvReleaseImage(&gray);
52  if (prev_gray) cvReleaseImage(&prev_gray);
53  if (pyramid) cvReleaseImage(&pyramid);
54  if (prev_pyramid) cvReleaseImage(&prev_pyramid);
55  if (mask) cvReleaseImage(&mask);
56 }
57 
58 void TrackerFeatures::ChangeSettings(int _max_features, int _min_features, double _quality_level, double _min_distance) {
59 
60  if(_max_features==max_features && _min_features==min_features && _quality_level==quality_level && _min_distance==min_distance) return;
61 
62  int common_features = min(feature_count, _max_features);
63  max_features = _max_features;
64  min_features = _min_features;
65  quality_level = _quality_level;
66  min_distance = _min_distance;
67  if (status) delete [] status; status = NULL;
68  if (prev_ids) delete [] prev_ids; prev_ids = NULL;
69  if (prev_features) delete [] prev_features; prev_features = NULL;
70  if (ids) {
71  int *ids_new = new int[max_features];
72  assert(common_features < max_features);
73  memcpy(ids_new, ids, sizeof(int)*common_features);
74  delete [] ids;
75  ids = ids_new;
76  } else {
77  ids = new int[max_features];
78  }
79  if (features) {
80  CvPoint2D32f *features_new = new CvPoint2D32f[max_features];
81  memcpy(features_new, features, sizeof(CvPoint2D32f)*common_features);
82  delete [] features;
83  features = features_new;
84  } else {
85  features = new CvPoint2D32f[max_features];
86  }
87  status = new char[max_features];
88  prev_ids = new int[max_features];
89  prev_features = new CvPoint2D32f[max_features];
91  feature_count=common_features;
92 
93  assert(ids);
94  assert(features);
95  assert(status);
96  assert(prev_ids);
97  assert(prev_features);
98 }
99 
101  feature_count=0;
102  frame_count=0;
103 }
104 
106  if (index > feature_count) return false;
107  feature_count--;
108  for (int i=index; i<feature_count; i++) {
109  features[i] = features[i+1];
110  ids[i] = ids[i+1];
111  }
112  return true;
113 }
114 
116  for (int i=0; i<feature_count; i++) {
117  if (ids[i] == id) return DelFeature(i);
118  }
119  return false;
120 }
121 
123  int removed_count=0;
124  float dist = 0.7f*float(min_distance);
125  for (int i=1; i<feature_count; i++) {
126  for (int ii=0; ii<i; ii++) {
127  float dx = features[i].x - features[ii].x;
128  float dy = features[i].y - features[ii].y;
129  if (dx < 0) dx = -dx; if (dy < 0) dy = -dy;
130  if ((dx < dist) && (dy < dist)) {
131  DelFeature(i); i--;
132  removed_count++;
133  break;
134  }
135  }
136  }
137  return removed_count;
138 }
139 
140 double TrackerFeatures::TrackHid(IplImage *img, IplImage *new_features_mask, bool add_features) {
141  if ((x_res != img->width) || (y_res != img->height)) {
142  if (img_eig) cvReleaseImage(&img_eig);
143  if (img_tmp) cvReleaseImage(&img_tmp);
144  if (gray) cvReleaseImage(&gray);
145  if (prev_gray) cvReleaseImage(&prev_gray);
146  if (pyramid) cvReleaseImage(&pyramid);
147  if (prev_pyramid) cvReleaseImage(&prev_pyramid);
148  if (mask) cvReleaseImage(&mask);
149  x_res = img->width; y_res = img->height;
150  img_eig = cvCreateImage(cvGetSize(img), IPL_DEPTH_32F, 1);
151  img_tmp = cvCreateImage(cvGetSize(img), IPL_DEPTH_32F, 1);
152  gray = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);
153  prev_gray = cvCreateImage(cvGetSize(img),IPL_DEPTH_8U, 1);
154  pyramid = cvCreateImage(cvSize(img->width+8,img->height/3), IPL_DEPTH_8U, 1);
155  prev_pyramid = cvCreateImage(cvSize(img->width+8,img->height/3), IPL_DEPTH_8U, 1);
156  mask = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);
157  frame_count=0;
158  if (min_distance == 0) {
159  min_distance = std::sqrt(double(img->width*img->height/max_features));
160  min_distance *= 0.8; //(double(min_features)/max_features);
161  }
162  }
163  // Swap
164  IplImage* tmp;
165  CvPoint2D32f* tmp2;
166  CV_SWAP(prev_gray, gray, tmp);
167  CV_SWAP(prev_features, features, tmp2);
169  memcpy(prev_ids, ids, sizeof(int)*max_features);
170  if (img->nChannels == 1) {
171  cvCopy(img, gray);
172  } else {
173  cvCvtColor(img, gray, CV_RGB2GRAY);
174  }
175  // TODO: We used to add features here
176  //if (prev_feature_count < 1) return -1;
177  frame_count++;
178  if (frame_count <= 1) {
179  memcpy(features, prev_features, sizeof(CvPoint2D32f)*prev_feature_count);
180  memcpy(ids, prev_ids, sizeof(int)*prev_feature_count);
182  } else if (prev_feature_count > 0) {
183  // Track
184  cvCalcOpticalFlowPyrLK(prev_gray, gray, prev_pyramid, pyramid,
186  cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,20,0.03), 0);
187  feature_count=0;
188  for (int i=0; i<prev_feature_count; i++) {
189  if (!status[i]) continue;
191  ids[feature_count] = prev_ids[i];
192  feature_count++;
193  }
194  }
195 
196  if (add_features) AddFeatures(new_features_mask);
197 
198  return 1;
199 }
200 
201 double TrackerFeatures::Reset(IplImage *img, IplImage *new_features_mask) {
202  feature_count=0;
203  frame_count=0;
204  return TrackHid(img, new_features_mask);
205 }
206 
207 double TrackerFeatures::Track(IplImage *img, bool add_features) {
208  return TrackHid(img, NULL); //, add_features);
209 }
210 
211 double TrackerFeatures::Track(IplImage* img, IplImage* mask)
212 {
213  return TrackHid(img, mask); //, true);
214 }
215 
217  cvSet(mask, cvScalar(255));
218  for (int i=0; i<feature_count; i++) {
219  cvRectangle(mask,
220  cvPoint(int(features[i].x-min_distance), int(features[i].y-min_distance)),
221  cvPoint(int(features[i].x+min_distance), int(features[i].y+min_distance)),
222  cvScalar(0), CV_FILLED);
223  }
224  return mask;
225 }
226 
227 int TrackerFeatures::AddFeatures(IplImage *new_features_mask) {
228  if (gray == NULL) return 0;
229  if (feature_count < min_features) {
230  int new_feature_count=max_features-feature_count;
231  if (new_features_mask == NULL) {
232  cvSet(mask, cvScalar(255));
233  for (int i=0; i<feature_count; i++) {
234  cvRectangle(mask,
235  cvPoint(int(features[i].x-min_distance), int(features[i].y-min_distance)),
236  cvPoint(int(features[i].x+min_distance), int(features[i].y+min_distance)),
237  cvScalar(0), CV_FILLED);
238  }
239  // Find new features
240  cvGoodFeaturesToTrack(gray, img_eig, img_tmp,
241  &(features[feature_count]), &new_feature_count,
242  quality_level, min_distance, mask, 3, 1, 0.04);
243 
244  } else {
245  cvGoodFeaturesToTrack(gray, img_eig, img_tmp,
246  &(features[feature_count]), &new_feature_count,
247  quality_level, min_distance, new_features_mask, 3, 1, 0.04);
248 
249  }
250  if (new_feature_count >= 1) {
251  for (int i=feature_count; i<feature_count+new_feature_count; i++) {
252  ids[i] = next_id;
253  next_id=((next_id+1)%(0x7fff));
254  }
255  feature_count += new_feature_count;
256  }
257  }
258  return feature_count;
259 }
260 
261 } // namespace alvar
Main ALVAR namespace.
Definition: Alvar.h:174
double TrackHid(IplImage *img, IplImage *mask=NULL, bool add_features=true)
Reset track features on specified mask area.
CvPoint2D32f * features
Track result: current features
double Track(IplImage *img)
Track features.
int prev_feature_count
Track result: count of previous features
TFSIMD_FORCE_INLINE const tfScalar & y() const
int * prev_ids
Track result: ID:s for previous features
int Purge()
Purge features that are considerably closer than the defined min_distance.
CvPoint2D32f * prev_features
Track result: previous features
int AddFeatures(IplImage *mask=NULL)
add features to the previously tracked frame if there are less than min_features
This file implements a feature tracker.
bool DelFeature(int index)
Stop tracking the identified feature (with index for features array)
bool DelFeatureId(int id)
Stop tracking the identified feature (with feature id)
TFSIMD_FORCE_INLINE const tfScalar & x() const
cv::Mat gray
int feature_count
Track result: count of current features
void ChangeSettings(int _max_features=100, int _min_features=90, double _quality_level=0.01, double _min_distance=10)
Change settings while running.
~TrackerFeatures()
Destructor.
int * ids
Track result: ID:s for current features
int min(int a, int b)
IplImage * NewFeatureMask()
Create and get the pointer to new_features_mask.


ar_track_alvar
Author(s): Scott Niekum
autogenerated on Mon Jun 10 2019 12:47:04