ViSP  2.6.2
vpKltOpencv.cpp
1 /****************************************************************************
2  *
3  * $Id: vpKltOpencv.cpp 3585 2012-03-01 21:38:35Z fspindle $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2012 by INRIA. All rights reserved.
7  *
8  * This software is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * ("GPL") version 2 as published by the Free Software Foundation.
11  * See the file LICENSE.txt at the root directory of this source
12  * distribution for additional information about the GNU GPL.
13  *
14  * For using ViSP with software that can not be combined with the GNU
15  * GPL, please contact INRIA about acquiring a ViSP Professional
16  * Edition License.
17  *
18  * See http://www.irisa.fr/lagadic/visp/visp.html for more information.
19  *
20  * This software was developed at:
21  * INRIA Rennes - Bretagne Atlantique
22  * Campus Universitaire de Beaulieu
23  * 35042 Rennes Cedex
24  * France
25  * http://www.irisa.fr/lagadic
26  *
27  * If you have questions regarding the use of this file, please contact
28  * INRIA at visp@inria.fr
29  *
30  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
31  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
32  *
33  *
34  * Description:
35  * Wrapper for the KLT (Kanade-Lucas-Tomasi) feature tracker implemented
36  * with opencv.
37  *
38  * Authors:
39  * Fabien Servant
40  * Fabien Spindler
41  *
42  *****************************************************************************/
43 
51 #include "visp/vpConfig.h"
52 
53 #ifdef VISP_HAVE_OPENCV
54 
55 #include <string>
56 
57 #include "vpKltOpencv.h"
58 
59 void vpKltOpencv::clean()
60 {
61  if (image) cvReleaseImage(&image);
62  if (prev_image) cvReleaseImage(&prev_image);
63  if (pyramid) cvReleaseImage(&pyramid);
64  if (prev_pyramid) cvReleaseImage(&prev_pyramid);
65 
66  image = 0;
67  prev_image = 0;
68  pyramid = 0;
69  prev_pyramid = 0;
70 
71  swap_temp = 0;
72  countFeatures = 0;
73  countPrevFeatures = 0;
74  flags = 0;
75  initialized = 0;
76  globalcountFeatures = 0;
77 }
78 
79 void vpKltOpencv::cleanAll()
80 {
81  clean();
82  if (features) cvFree(&features);
83  if (prev_features) cvFree(&prev_features);
84  if (status) cvFree(&status);
85  if (lostDuringTrack) cvFree(&lostDuringTrack);
86  if (featuresid) cvFree(&featuresid);
87  if (prev_featuresid) cvFree(&prev_featuresid);
88  features = 0;
89  prev_features = 0;
90  status = 0;
91  lostDuringTrack = 0;
92  featuresid = 0;
93  prev_featuresid = 0;
94 }
95 
96 void vpKltOpencv::reset()
97 {
98  clean();
99 
100 }
101 
103 {
104  //Valeurs par d�faut pour le KLT
105  initialized = 0;
106  maxFeatures = 50;
107  countFeatures = 0;
108  countPrevFeatures = 0;
109  globalcountFeatures = 0;
110  win_size = 10;
111  quality = 0.01;
112  min_distance = 10;
113  block_size = 3;
114  use_harris = 1;
115  pyramid_level = 3;
116  harris_free_parameter = 0.04;
117 
118  //Zeroing pointers
119  image = 0;
120  prev_image = 0;
121  pyramid = 0;
122  prev_pyramid = 0;
123  swap_temp = 0;
124  features = 0;
125  prev_features = 0;
126  flags = 0;
127  status = 0;
128  lostDuringTrack = 0;
129  featuresid = 0;
130  prev_featuresid = 0;
131  OnInitialize = 0;
132  OnFeatureLost = 0;
133  OnNewFeature = 0;
134  OnMeasureFeature = 0;
135  IsFeatureValid = 0;
136 
137  features = (CvPoint2D32f*)cvAlloc((unsigned int)maxFeatures*sizeof(features[0]));
138  prev_features = (CvPoint2D32f*)cvAlloc((unsigned int)maxFeatures*sizeof(prev_features[0]));
139  status = (char*)cvAlloc((size_t)maxFeatures);
140  lostDuringTrack = (bool*)cvAlloc((size_t)maxFeatures);
141  featuresid = (long*)cvAlloc((unsigned int)maxFeatures*sizeof(long));
142  prev_featuresid = (long*)cvAlloc((unsigned int)maxFeatures*sizeof(long));
143 
144 
145  _tid = -1;
146 }
147 
149 {
150  //Shallow copy of primitives
151  initialized = copy.initialized;
152  maxFeatures = copy.maxFeatures;
153  countFeatures = copy.countFeatures;
154  countPrevFeatures = copy.countPrevFeatures;
155  globalcountFeatures = copy.globalcountFeatures;
156  flags = copy.flags;
157  win_size = copy.win_size;
158  quality = copy.quality;
159  min_distance = copy.min_distance;
160  harris_free_parameter = copy.harris_free_parameter;
161  block_size = copy.block_size;
162  use_harris = copy.use_harris;
163  pyramid_level = copy.pyramid_level;
164  _tid = copy._tid;
165 
166  OnInitialize = copy.OnInitialize;
167  OnFeatureLost = copy.OnFeatureLost;
168  OnNewFeature = copy.OnNewFeature;
169  OnMeasureFeature = copy.OnMeasureFeature;
170  IsFeatureValid = copy.IsFeatureValid;
171 
172  if (!initialized) {
173  image = 0;
174  prev_image = 0;
175  pyramid = 0;
176  prev_pyramid = 0;
177  features = 0;
178  prev_features = 0;
179  status = 0;
180  lostDuringTrack = 0;
181  featuresid = 0;
182  prev_featuresid = 0;
183  swap_temp = 0;
184  countFeatures = 0;
185  countPrevFeatures = 0;
186  flags = 0;
187  initialized = 0;
188  globalcountFeatures = 0;
189  }
190 
191  if (copy.image)
192  {
193  image = cvCreateImage(cvGetSize(copy.image), 8, 1);
194  // /*IplImage **/cvCopyImage(copy.image,image);
195  cvCopy(copy.image, image, 0);
196  }
197 
198  if (copy.prev_image)
199  {
200  prev_image = cvCreateImage(cvGetSize(copy.prev_image), IPL_DEPTH_8U, 1);
201  // /*IplImage **/ cvCopyImage(copy.prev_image,prev_image);
202  cvCopy(copy.prev_image, prev_image, 0);
203  }
204 
205  if (copy.pyramid)
206  {
207  pyramid = cvCreateImage(cvGetSize(copy.pyramid), IPL_DEPTH_8U, 1);
208  // /*IplImage **/cvCopyImage(copy.pyramid,pyramid);
209  cvCopy(copy.pyramid, pyramid, 0);
210  }
211 
212  if (copy.prev_pyramid)
213  {
214  prev_pyramid = cvCreateImage(cvGetSize(copy.prev_pyramid), IPL_DEPTH_8U, 1);
215  // /*IplImage **/cvCopyImage(copy.prev_pyramid,prev_pyramid);
216  cvCopy(copy.prev_pyramid, prev_pyramid, 0);
217  }
218 
219  //Deep copy of arrays
220  if (copy.features) {
221  /*CvPoint2D32f **/features =
222  (CvPoint2D32f*)cvAlloc((unsigned int)copy.maxFeatures*sizeof(CvPoint2D32f));
223  for (int i = 0; i < copy.maxFeatures; i++)
224  features[i] = copy.features[i];
225  }
226 
227  if (copy.prev_features) {
228  /*CvPoint2D32f **/prev_features =
229  (CvPoint2D32f*)cvAlloc((unsigned int)copy.maxFeatures*sizeof(CvPoint2D32f));
230  for (int i = 0; i < copy.maxFeatures; i++)
231  prev_features[i] = copy.prev_features[i];
232  }
233 
234  if (copy.featuresid) {
235  /*long **/featuresid = (long*)cvAlloc((unsigned int)copy.maxFeatures*sizeof(long));
236  for (int i = 0; i < copy.maxFeatures; i++)
237  featuresid[i] = copy.featuresid[i];
238  }
239 
240  if (copy.prev_featuresid) {
241  /*long **/prev_featuresid = (long*)cvAlloc((unsigned int)copy.maxFeatures*sizeof(long));
242  for (int i = 0; i < copy.maxFeatures; i++)
243  prev_featuresid[i] = copy.prev_featuresid[i];
244  }
245 
246  if (copy.status) {
247  /*char **/status = (char*)cvAlloc((unsigned int)copy.maxFeatures*sizeof(char));
248  for (int i = 0; i < copy.maxFeatures; i++)
249  status[i] = copy.status[i];
250  }
251 
252  if (copy.lostDuringTrack) {
253  /*bool **/lostDuringTrack = (bool*)cvAlloc((unsigned int)copy.maxFeatures*sizeof(bool));
254  for (int i = 0; i < copy.maxFeatures; i++)
255  lostDuringTrack[i] = copy.lostDuringTrack[i];
256  }
257 }
258 
260 {
261  cleanAll();
262 }
263 
271 void vpKltOpencv::setMaxFeatures(const int input) {
272  initialized = 0; maxFeatures=input;
273 
274  if (features) cvFree(&features);
275  if (prev_features) cvFree(&prev_features);
276  if (status) cvFree(&status);
277  if (lostDuringTrack) cvFree(&lostDuringTrack);
278  if (featuresid) cvFree(&featuresid);
279  if (prev_featuresid) cvFree(&prev_featuresid);
280 
281 
282  features = (CvPoint2D32f*)cvAlloc((unsigned int)maxFeatures*sizeof(CvPoint2D32f));
283  prev_features = (CvPoint2D32f*)cvAlloc((unsigned int)maxFeatures*sizeof(CvPoint2D32f));
284  status = (char*)cvAlloc((unsigned int)maxFeatures*sizeof(char));
285  lostDuringTrack = (bool*)cvAlloc((unsigned int)maxFeatures*sizeof(bool));
286  featuresid = (long*)cvAlloc((unsigned int)maxFeatures*sizeof(long));
287  prev_featuresid = (long*)cvAlloc((unsigned int)maxFeatures*sizeof(long));
288 }
289 
290 void vpKltOpencv::initTracking(const IplImage *I, const IplImage *masque)
291 {
292  if (!I) {
293  throw(vpException(vpTrackingException::initializationError, "Image Not initialized")) ;
294  }
295 
296  if (I->depth != IPL_DEPTH_8U || I->nChannels != 1) {
297  throw(vpException(vpTrackingException::initializationError, "Bad Image format")) ;
298  }
299 
300  if (masque) {
301  if (masque->depth != IPL_DEPTH_8U || I->nChannels != 1) {
302  throw(vpException(vpTrackingException::initializationError, "Bad Image format")) ;
303  }
304  }
305 
306 
307  //Creation des buffers
308  CvSize Sizeim, SizeI;
309  SizeI = cvGetSize(I);
310  bool b_imOK = true;
311  if(image != NULL){
312  Sizeim = cvGetSize(image);
313  if(SizeI.width != Sizeim.width || SizeI.height != Sizeim.height) b_imOK = false;
314  }
315  if(image == NULL || prev_image == NULL || pyramid==NULL || prev_pyramid ==NULL || !b_imOK){
316  reset();
317  image = cvCreateImage(cvGetSize(I), 8, 1);image->origin = I->origin;
318  prev_image = cvCreateImage(cvGetSize(I), IPL_DEPTH_8U, 1);
319  pyramid = cvCreateImage(cvGetSize(I), IPL_DEPTH_8U, 1);
320  prev_pyramid = cvCreateImage(cvGetSize(I), IPL_DEPTH_8U, 1);
321  }else{
322  swap_temp = 0;
323  countFeatures = 0;
324  countPrevFeatures = 0;
325  flags = 0;
326  initialized = 0;
327  globalcountFeatures = 0;
328  }
329 
330  initialized = 1;
331 
332  //Import
333  cvCopy(I, image, 0);
334 
335  //Recherche de points d'int�rets
336  countFeatures = maxFeatures;
337  countPrevFeatures = 0;
338  IplImage* eig = cvCreateImage(cvGetSize(image), 32, 1);
339  IplImage* temp = cvCreateImage(cvGetSize(image), 32, 1);
340  cvGoodFeaturesToTrack(image, eig, temp, features,
341  &countFeatures, quality, min_distance,
342  masque, block_size, use_harris, harris_free_parameter);
343  cvFindCornerSubPix(image, features, countFeatures, cvSize(win_size, win_size),
344  cvSize(-1,-1),cvTermCriteria(CV_TERMCRIT_ITER|
345  CV_TERMCRIT_EPS,20,0.03));
346  cvReleaseImage(&eig);
347  cvReleaseImage(&temp);
348 
349  if (OnInitialize)
350  OnInitialize(_tid);
351 
352  //printf("Number of features at init: %d\n", countFeatures);
353  for (int boucle=0; boucle<countFeatures;boucle++) {
354  featuresid[boucle] = globalcountFeatures;
355  globalcountFeatures++;
356 
357  if (OnNewFeature){
358  OnNewFeature(_tid, boucle, featuresid[boucle], features[boucle].x,
359  features[boucle].y);
360  }
361  }
362 }
363 
364 
365 void vpKltOpencv::track(const IplImage *I)
366 {
367  if (!initialized) {
368  vpERROR_TRACE("KLT Not initialized") ;
370  "KLT Not initialized")) ;
371  }
372 
373  if (!I) {
375  "Image Not initialized")) ;
376  }
377 
378  if (I->depth != IPL_DEPTH_8U || I->nChannels != 1) {
380  "Bad Image format")) ;
381  }
382 
383  // Save current features as previous features
384  countPrevFeatures = countFeatures;
385  for (int boucle=0; boucle<countFeatures;boucle++) {
386  prev_featuresid[boucle] = featuresid[boucle];
387  }
388 
389  CvPoint2D32f *swap_features = 0;
390 
391  CV_SWAP(prev_image, image, swap_temp);
392  CV_SWAP(prev_pyramid, pyramid, swap_temp);
393  CV_SWAP(prev_features, features, swap_features);
394 
395  cvCopy(I, image, 0);
396 
397  if (countFeatures <= 0) return;
398 
399  cvCalcOpticalFlowPyrLK( prev_image, image, prev_pyramid, pyramid,
400  prev_features, features, countFeatures,
401  cvSize(win_size, win_size), pyramid_level,
402  status, 0, cvTermCriteria(CV_TERMCRIT_ITER
403  |CV_TERMCRIT_EPS,20,0.03),
404  flags );
405  flags |= CV_LKFLOW_PYR_A_READY;
406 
407  int i,k;
408  for (i = k = 0; i < countFeatures ; i++) {
409  if (!status[i]) {
410  lostDuringTrack[i] = 1;
411  if (OnFeatureLost)
412  OnFeatureLost(_tid, i, featuresid[i], features[i].x,
413  features[i].y);
414  continue;
415  }
416 
417  if (IsFeatureValid) {
418  if (!IsFeatureValid(_tid, features[i].x, features[i].y)) {
419  lostDuringTrack[i] = 1;
420  if (OnFeatureLost)
421  OnFeatureLost(_tid, i, featuresid[i], features[i].x, features[i].y);
422  continue;
423  }
424  }
425  features[k] = features[i];
426  featuresid[k] = featuresid[i];
427 
428  if (OnMeasureFeature) OnMeasureFeature(_tid, k, featuresid[k], features[k].x, features[k].y);
429 
430  lostDuringTrack[i] = 0;
431  k++;
432  }
433  countFeatures = k;
434 }
435 
437  vpColor color)
438 {
439  if ((features == 0) || (I.bitmap==0) || (!initialized))
440  {
441  vpERROR_TRACE(" Memory problem ");
442  throw(vpException(vpException::memoryAllocationError," Memory problem"));
443  }
444 
445  vpKltOpencv::display(I,features,featuresid,countFeatures,color);
446 }
447 
456 void vpKltOpencv::getFeature(int index, int &id, float &x, float &y) const
457 {
458  if (index >= countFeatures)
459  {
460  vpERROR_TRACE(" Memory problem ");
461  throw(vpException(vpException::memoryAllocationError," Memory problem"));
462  }
463 
464  x = features[index].x;
465  y = features[index].y;
466  id = featuresid[index];
467 }
468 
477 void vpKltOpencv::getPrevFeature(int index, int &id, float &x, float &y) const
478 {
479  if (index >= countPrevFeatures)
480  {
481  vpERROR_TRACE(" Memory problem ");
482  throw(vpException(vpException::memoryAllocationError," Memory problem"));
483  }
484 
485  x = prev_features[index].x;
486  y = prev_features[index].y;
487  id = prev_featuresid[index];
488 }
489 
496 void vpKltOpencv::addFeature(const int &id,
497  const float &x, const float &y)
498 {
499  if (maxFeatures == countFeatures)
500  {
501  vpERROR_TRACE(" Cannot add the feature ");
502  return;
503  }
504 
505  CvPoint2D32f f;
506  f.x = x;
507  f.y = y;
508  features[countFeatures] = f;
509  featuresid[countFeatures] = id;
510  countFeatures ++;
511 }
512 
514 {
515  if (index >= countFeatures)
516  {
517  vpERROR_TRACE(" Memory problem ");
518  throw(vpException(vpException::memoryAllocationError," Memory problem"));
519  }
520 
521  countFeatures --;
522 
523  for (int i=index ; i < countFeatures; i ++) {
524  features[i] = features[i+1];
525  featuresid[i] = featuresid[i+1];
526  }
527 }
528 
543 void vpKltOpencv::display(const vpImage<unsigned char>& I,const CvPoint2D32f* features_list,
544  const int &nbFeatures, vpColor color, unsigned int thickness)
545 {
546  vpImagePoint ip;
547  for (int i = 0 ; i < nbFeatures ; i++)
548  {
549  ip.set_u( vpMath::round(features_list[i].x ) );
550  ip.set_v( vpMath::round(features_list[i].y ) );
551  vpDisplay::displayCross(I, ip, 10, color, thickness) ;
552  }
553 }
554 
571 void vpKltOpencv::display(const vpImage<unsigned char>& I,const CvPoint2D32f* features_list,
572  const long *featuresid_list, const int &nbFeatures,
573  vpColor color, unsigned int thickness)
574 {
575  vpImagePoint ip;
576  for (int i = 0 ; i < nbFeatures ; i++)
577  {
578  ip.set_u( vpMath::round(features_list[i].x ) );
579  ip.set_v( vpMath::round(features_list[i].y ) );
580  vpDisplay::displayCross(I, ip, 10, color, thickness) ;
581 
582  char id[10];
583  sprintf(id, "%ld", featuresid_list[i]);
584  ip.set_u( vpMath::round( features_list[i].x + 5 ) );
585  vpDisplay::displayCharString(I, ip, id, color);
586  }
587 }
588 #endif
void track(const IplImage *I)
#define vpERROR_TRACE
Definition: vpDebug.h:379
Type * bitmap
points toward the bitmap
Definition: vpImage.h:115
Class to define colors available for display functionnalities.
Definition: vpColor.h:123
void addFeature(const int &id, const float &x, const float &y)
virtual ~vpKltOpencv()
static int round(const double x)
Definition: vpMath.h:228
void getFeature(int index, int &id, float &x, float &y) const
void set_u(const double u)
Definition: vpImagePoint.h:203
virtual void displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)=0
void set_v(const double v)
Definition: vpImagePoint.h:214
void getPrevFeature(int index, int &id, float &x, float &y) const
void initTracking(const IplImage *I, const IplImage *mask=NULL)
virtual void displayCharString(const vpImagePoint &ip, const char *text, const vpColor &color=vpColor::green)=0
Wrapper for the KLT (Kanade-Lucas-Tomasi) feature tracker implemented with OpenCV.
Definition: vpKltOpencv.h:141
void suppressFeature(int index)
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:92
void setMaxFeatures(const int input)
void display(const vpImage< unsigned char > &I, vpColor color=vpColor::red)