ViSP  2.7.0
vpKltOpencv.cpp
1 /****************************************************************************
2  *
3  * $Id: vpKltOpencv.cpp 4097 2013-02-05 09:32:17Z ayol $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2013 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  initial_guess = false;
137 
138  features = (CvPoint2D32f*)cvAlloc((unsigned int)maxFeatures*sizeof(features[0]));
139  prev_features = (CvPoint2D32f*)cvAlloc((unsigned int)maxFeatures*sizeof(prev_features[0]));
140  status = (char*)cvAlloc((size_t)maxFeatures);
141  lostDuringTrack = (bool*)cvAlloc((size_t)maxFeatures);
142  featuresid = (long*)cvAlloc((unsigned int)maxFeatures*sizeof(long));
143  prev_featuresid = (long*)cvAlloc((unsigned int)maxFeatures*sizeof(long));
144 
145 
146  _tid = -1;
147 }
148 
150 {
151  //Shallow copy of primitives
152  initialized = copy.initialized;
153  maxFeatures = copy.maxFeatures;
154  countFeatures = copy.countFeatures;
155  countPrevFeatures = copy.countPrevFeatures;
156  globalcountFeatures = copy.globalcountFeatures;
157  flags = copy.flags;
158  win_size = copy.win_size;
159  quality = copy.quality;
160  min_distance = copy.min_distance;
161  harris_free_parameter = copy.harris_free_parameter;
162  block_size = copy.block_size;
163  use_harris = copy.use_harris;
164  pyramid_level = copy.pyramid_level;
165  _tid = copy._tid;
166 
167  OnInitialize = copy.OnInitialize;
168  OnFeatureLost = copy.OnFeatureLost;
169  OnNewFeature = copy.OnNewFeature;
170  OnMeasureFeature = copy.OnMeasureFeature;
171  IsFeatureValid = copy.IsFeatureValid;
172 
173  if (!initialized) {
174  image = 0;
175  prev_image = 0;
176  pyramid = 0;
177  prev_pyramid = 0;
178  features = 0;
179  prev_features = 0;
180  status = 0;
181  lostDuringTrack = 0;
182  featuresid = 0;
183  prev_featuresid = 0;
184  swap_temp = 0;
185  countFeatures = 0;
186  countPrevFeatures = 0;
187  flags = 0;
188  initialized = 0;
189  globalcountFeatures = 0;
190  }
191 
192  if (copy.image)
193  {
194  image = cvCreateImage(cvGetSize(copy.image), 8, 1);
195  // /*IplImage **/cvCopyImage(copy.image,image);
196  cvCopy(copy.image, image, 0);
197  }
198 
199  if (copy.prev_image)
200  {
201  prev_image = cvCreateImage(cvGetSize(copy.prev_image), IPL_DEPTH_8U, 1);
202  // /*IplImage **/ cvCopyImage(copy.prev_image,prev_image);
203  cvCopy(copy.prev_image, prev_image, 0);
204  }
205 
206  if (copy.pyramid)
207  {
208  pyramid = cvCreateImage(cvGetSize(copy.pyramid), IPL_DEPTH_8U, 1);
209  // /*IplImage **/cvCopyImage(copy.pyramid,pyramid);
210  cvCopy(copy.pyramid, pyramid, 0);
211  }
212 
213  if (copy.prev_pyramid)
214  {
215  prev_pyramid = cvCreateImage(cvGetSize(copy.prev_pyramid), IPL_DEPTH_8U, 1);
216  // /*IplImage **/cvCopyImage(copy.prev_pyramid,prev_pyramid);
217  cvCopy(copy.prev_pyramid, prev_pyramid, 0);
218  }
219 
220  //Deep copy of arrays
221  if (copy.features) {
222  /*CvPoint2D32f **/features =
223  (CvPoint2D32f*)cvAlloc((unsigned int)copy.maxFeatures*sizeof(CvPoint2D32f));
224  for (int i = 0; i < copy.maxFeatures; i++)
225  features[i] = copy.features[i];
226  }
227 
228  if (copy.prev_features) {
229  /*CvPoint2D32f **/prev_features =
230  (CvPoint2D32f*)cvAlloc((unsigned int)copy.maxFeatures*sizeof(CvPoint2D32f));
231  for (int i = 0; i < copy.maxFeatures; i++)
232  prev_features[i] = copy.prev_features[i];
233  }
234 
235  if (copy.featuresid) {
236  /*long **/featuresid = (long*)cvAlloc((unsigned int)copy.maxFeatures*sizeof(long));
237  for (int i = 0; i < copy.maxFeatures; i++)
238  featuresid[i] = copy.featuresid[i];
239  }
240 
241  if (copy.prev_featuresid) {
242  /*long **/prev_featuresid = (long*)cvAlloc((unsigned int)copy.maxFeatures*sizeof(long));
243  for (int i = 0; i < copy.maxFeatures; i++)
244  prev_featuresid[i] = copy.prev_featuresid[i];
245  }
246 
247  if (copy.status) {
248  /*char **/status = (char*)cvAlloc((unsigned int)copy.maxFeatures*sizeof(char));
249  for (int i = 0; i < copy.maxFeatures; i++)
250  status[i] = copy.status[i];
251  }
252 
253  if (copy.lostDuringTrack) {
254  /*bool **/lostDuringTrack = (bool*)cvAlloc((unsigned int)copy.maxFeatures*sizeof(bool));
255  for (int i = 0; i < copy.maxFeatures; i++)
256  lostDuringTrack[i] = copy.lostDuringTrack[i];
257  }
258 }
259 
261 {
262  cleanAll();
263 }
264 
272 void vpKltOpencv::setMaxFeatures(const int input) {
273  initialized = 0; maxFeatures=input;
274 
275  if (features) cvFree(&features);
276  if (prev_features) cvFree(&prev_features);
277  if (status) cvFree(&status);
278  if (lostDuringTrack) cvFree(&lostDuringTrack);
279  if (featuresid) cvFree(&featuresid);
280  if (prev_featuresid) cvFree(&prev_featuresid);
281 
282 
283  features = (CvPoint2D32f*)cvAlloc((unsigned int)maxFeatures*sizeof(CvPoint2D32f));
284  prev_features = (CvPoint2D32f*)cvAlloc((unsigned int)maxFeatures*sizeof(CvPoint2D32f));
285  status = (char*)cvAlloc((unsigned int)maxFeatures*sizeof(char));
286  lostDuringTrack = (bool*)cvAlloc((unsigned int)maxFeatures*sizeof(bool));
287  featuresid = (long*)cvAlloc((unsigned int)maxFeatures*sizeof(long));
288  prev_featuresid = (long*)cvAlloc((unsigned int)maxFeatures*sizeof(long));
289 }
290 
291 void vpKltOpencv::initTracking(const IplImage *I, const IplImage *masque)
292 {
293  if (!I) {
294  throw(vpException(vpTrackingException::initializationError, "Image Not initialized")) ;
295  }
296 
297  if (I->depth != IPL_DEPTH_8U || I->nChannels != 1) {
298  throw(vpException(vpTrackingException::initializationError, "Bad Image format")) ;
299  }
300 
301  if (masque) {
302  if (masque->depth != IPL_DEPTH_8U || I->nChannels != 1) {
303  throw(vpException(vpTrackingException::initializationError, "Bad Image format")) ;
304  }
305  }
306 
307 
308  //Creation des buffers
309  CvSize Sizeim, SizeI;
310  SizeI = cvGetSize(I);
311  bool b_imOK = true;
312  if(image != NULL){
313  Sizeim = cvGetSize(image);
314  if(SizeI.width != Sizeim.width || SizeI.height != Sizeim.height) b_imOK = false;
315  }
316  if(image == NULL || prev_image == NULL || pyramid==NULL || prev_pyramid ==NULL || !b_imOK){
317  reset();
318  image = cvCreateImage(cvGetSize(I), 8, 1);image->origin = I->origin;
319  prev_image = cvCreateImage(cvGetSize(I), IPL_DEPTH_8U, 1);
320  pyramid = cvCreateImage(cvGetSize(I), IPL_DEPTH_8U, 1);
321  prev_pyramid = cvCreateImage(cvGetSize(I), IPL_DEPTH_8U, 1);
322  }else{
323  swap_temp = 0;
324  countFeatures = 0;
325  countPrevFeatures = 0;
326  flags = 0;
327  initialized = 0;
328  globalcountFeatures = 0;
329  }
330 
331  initialized = 1;
332 
333  //Import
334  cvCopy(I, image, 0);
335 
336  //Recherche de points d'int�rets
337  countFeatures = maxFeatures;
338  countPrevFeatures = 0;
339  IplImage* eig = cvCreateImage(cvGetSize(image), 32, 1);
340  IplImage* temp = cvCreateImage(cvGetSize(image), 32, 1);
341  cvGoodFeaturesToTrack(image, eig, temp, features,
342  &countFeatures, quality, min_distance,
343  masque, block_size, use_harris, harris_free_parameter);
344  cvFindCornerSubPix(image, features, countFeatures, cvSize(win_size, win_size),
345  cvSize(-1,-1),cvTermCriteria(CV_TERMCRIT_ITER|
346  CV_TERMCRIT_EPS,20,0.03));
347  cvReleaseImage(&eig);
348  cvReleaseImage(&temp);
349 
350  if (OnInitialize)
351  OnInitialize(_tid);
352 
353  //printf("Number of features at init: %d\n", countFeatures);
354  for (int boucle=0; boucle<countFeatures;boucle++) {
355  featuresid[boucle] = globalcountFeatures;
356  globalcountFeatures++;
357 
358  if (OnNewFeature){
359  OnNewFeature(_tid, boucle, featuresid[boucle], features[boucle].x,
360  features[boucle].y);
361  }
362  }
363 }
364 
365 
366 void vpKltOpencv::track(const IplImage *I)
367 {
368  if (!initialized) {
369  vpERROR_TRACE("KLT Not initialized") ;
371  "KLT Not initialized")) ;
372  }
373 
374  if (!I) {
376  "Image Not initialized")) ;
377  }
378 
379  if (I->depth != IPL_DEPTH_8U || I->nChannels != 1) {
381  "Bad Image format")) ;
382  }
383 
384 
385 
386  CV_SWAP(prev_image, image, swap_temp);
387  CV_SWAP(prev_pyramid, pyramid, swap_temp);
388 
389  cvCopy(I, image, 0);
390 
391  if(!initial_guess){
392  // Save current features as previous features
393  countPrevFeatures = countFeatures;
394  for (int boucle=0; boucle<countFeatures;boucle++) {
395  prev_featuresid[boucle] = featuresid[boucle];
396  }
397 
398  CvPoint2D32f *swap_features = 0;
399  CV_SWAP(prev_features, features, swap_features);
400  }
401 
402  if (countFeatures <= 0) return;
403 
404  cvCalcOpticalFlowPyrLK( prev_image, image, prev_pyramid, pyramid,
405  prev_features, features, countFeatures,
406  cvSize(win_size, win_size), pyramid_level,
407  status, 0, cvTermCriteria(CV_TERMCRIT_ITER
408  |CV_TERMCRIT_EPS,20,0.03),
409  flags );
410 
411  if(!initial_guess)
412  flags |= CV_LKFLOW_PYR_A_READY;
413  else{
414  flags = CV_LKFLOW_PYR_A_READY;
415  initial_guess = false;
416  }
417 
418  int i,k;
419  for (i = k = 0; i < countFeatures ; i++) {
420  if (!status[i]) {
421  lostDuringTrack[i] = 1;
422  if (OnFeatureLost)
423  OnFeatureLost(_tid, i, featuresid[i], features[i].x,
424  features[i].y);
425  continue;
426  }
427 
428  if (IsFeatureValid) {
429  if (!IsFeatureValid(_tid, features[i].x, features[i].y)) {
430  lostDuringTrack[i] = 1;
431  if (OnFeatureLost)
432  OnFeatureLost(_tid, i, featuresid[i], features[i].x, features[i].y);
433  continue;
434  }
435  }
436  features[k] = features[i];
437  featuresid[k] = featuresid[i];
438 
439  if (OnMeasureFeature) OnMeasureFeature(_tid, k, featuresid[k], features[k].x, features[k].y);
440 
441  lostDuringTrack[i] = 0;
442  k++;
443  }
444  countFeatures = k;
445 }
446 
448  vpColor color)
449 {
450  if ((features == 0) || (I.bitmap==0) || (!initialized))
451  {
452  vpERROR_TRACE(" Memory problem ");
453  throw(vpException(vpException::memoryAllocationError," Memory problem"));
454  }
455 
456  vpKltOpencv::display(I,features,featuresid,countFeatures,color);
457 }
458 
472 void vpKltOpencv::getFeature(int index, int &id, float &x, float &y) const
473 {
474  if (index >= countFeatures)
475  {
476  vpERROR_TRACE(" Memory problem ");
477  throw(vpException(vpException::memoryAllocationError," Memory problem"));
478  }
479 
480  x = features[index].x;
481  y = features[index].y;
482  id = featuresid[index];
483 }
484 
485 
493 void
494 vpKltOpencv::setInitialGuess(CvPoint2D32f **guess_pts)
495 {
496  // Save current features as previous features
497  countPrevFeatures = countFeatures;
498  for (int boucle=0; boucle<countFeatures;boucle++) {
499  prev_featuresid[boucle] = featuresid[boucle];
500  }
501 
502  CvPoint2D32f *swap_features = NULL;
503  CV_SWAP(prev_features, *guess_pts, swap_features);
504 
505  CV_SWAP(features, prev_features, swap_features);
506 
507  flags |= CV_LKFLOW_INITIAL_GUESSES;
508 
509  initial_guess = true;
510 }
511 
520 void vpKltOpencv::getPrevFeature(int index, int &id, float &x, float &y) const
521 {
522  if (index >= countPrevFeatures)
523  {
524  vpERROR_TRACE(" Memory problem ");
525  throw(vpException(vpException::memoryAllocationError," Memory problem"));
526  }
527 
528  x = prev_features[index].x;
529  y = prev_features[index].y;
530  id = prev_featuresid[index];
531 }
532 
539 void vpKltOpencv::addFeature(const int &id,
540  const float &x, const float &y)
541 {
542  if (maxFeatures == countFeatures)
543  {
544  vpERROR_TRACE(" Cannot add the feature ");
545  return;
546  }
547 
548  CvPoint2D32f f;
549  f.x = x;
550  f.y = y;
551  features[countFeatures] = f;
552  featuresid[countFeatures] = id;
553  countFeatures ++;
554 }
555 
557 {
558  if (index >= countFeatures)
559  {
560  vpERROR_TRACE(" Memory problem ");
561  throw(vpException(vpException::memoryAllocationError," Memory problem"));
562  }
563 
564  countFeatures --;
565 
566  for (int i=index ; i < countFeatures; i ++) {
567  features[i] = features[i+1];
568  featuresid[i] = featuresid[i+1];
569  }
570 }
571 
586 void vpKltOpencv::display(const vpImage<unsigned char>& I,const CvPoint2D32f* features_list,
587  const int &nbFeatures, vpColor color, unsigned int thickness)
588 {
589  vpImagePoint ip;
590  for (int i = 0 ; i < nbFeatures ; i++)
591  {
592  ip.set_u( vpMath::round(features_list[i].x ) );
593  ip.set_v( vpMath::round(features_list[i].y ) );
594  vpDisplay::displayCross(I, ip, 10, color, thickness) ;
595  }
596 }
611 void vpKltOpencv::display(const vpImage<vpRGBa>& I,const CvPoint2D32f* features_list,
612  const int &nbFeatures, vpColor color, unsigned int thickness)
613 {
614  vpImagePoint ip;
615  for (int i = 0 ; i < nbFeatures ; i++)
616  {
617  ip.set_u( vpMath::round(features_list[i].x ) );
618  ip.set_v( vpMath::round(features_list[i].y ) );
619  vpDisplay::displayCross(I, ip, 10, color, thickness) ;
620  }
621 }
622 
639 void vpKltOpencv::display(const vpImage<unsigned char>& I,const CvPoint2D32f* features_list,
640  const long *featuresid_list, const int &nbFeatures,
641  vpColor color, unsigned int thickness)
642 {
643  vpImagePoint ip;
644  for (int i = 0 ; i < nbFeatures ; i++)
645  {
646  ip.set_u( vpMath::round(features_list[i].x ) );
647  ip.set_v( vpMath::round(features_list[i].y ) );
648  vpDisplay::displayCross(I, ip, 10, color, thickness) ;
649 
650  char id[10];
651  sprintf(id, "%ld", featuresid_list[i]);
652  ip.set_u( vpMath::round( features_list[i].x + 5 ) );
653  vpDisplay::displayCharString(I, ip, id, color);
654  }
655 }
656 
673 void vpKltOpencv::display(const vpImage<vpRGBa>& I,const CvPoint2D32f* features_list,
674  const long *featuresid_list, const int &nbFeatures,
675  vpColor color, unsigned int thickness)
676 {
677  vpImagePoint ip;
678  for (int i = 0 ; i < nbFeatures ; i++)
679  {
680  ip.set_u( vpMath::round(features_list[i].x ) );
681  ip.set_v( vpMath::round(features_list[i].y ) );
682  vpDisplay::displayCross(I, ip, 10, color, thickness) ;
683 
684  char id[10];
685  sprintf(id, "%ld", featuresid_list[i]);
686  ip.set_u( vpMath::round( features_list[i].x + 5 ) );
687  vpDisplay::displayCharString(I, ip, id, color);
688  }
689 }
690 
691 #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)
error that can be emited by ViSP classes.
Definition: vpException.h:75
void setInitialGuess(CvPoint2D32f **guess_pts)
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)