ViSP  2.10.0
vpKltOpencv.cpp
1 /****************************************************************************
2  *
3  * $Id: vpKltOpencv.cpp 5189 2015-01-21 16:42:18Z ayol $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2014 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 #if defined(VISP_HAVE_OPENCV) && (VISP_HAVE_OPENCV_VERSION >= 0x020408)
54 
55 #include <string>
56 
57 #include <visp/vpDisplay.h>
58 #include <visp/vpKltOpencv.h>
59 #include <visp/vpTrackingException.h>
60 
65  : m_gray(), m_prevGray(), m_points_id(), m_maxCount(500), m_termcrit(), m_winSize(10), m_qualityLevel(0.01),
66  m_minDistance(15), m_minEigThreshold(1e-4), m_harris_k(0.04), m_blockSize(3), m_useHarrisDetector(1), m_pyrMaxLevel(3),
67  m_next_points_id(0), m_initial_guess(false)
68 {
69  m_termcrit = cv::TermCriteria(cv::TermCriteria::COUNT|cv::TermCriteria::EPS, 20, 0.03);
70 
71 }
72 
77  : m_gray(), m_prevGray(), m_points_id(), m_maxCount(500), m_termcrit(), m_winSize(10), m_qualityLevel(0.01),
78  m_minDistance(15), m_minEigThreshold(1e-4), m_harris_k(0.04), m_blockSize(3), m_useHarrisDetector(1), m_pyrMaxLevel(3),
79  m_next_points_id(0), m_initial_guess(false)
80 {
81  *this = copy;
82 }
83 
88 {
89  m_gray = copy.m_gray;
90  m_prevGray = copy.m_prevGray;
91  m_points[0] = copy.m_points[0];
92  m_points[1] = copy.m_points[1];
93  m_points_id = copy.m_points_id;
94  m_maxCount = copy.m_maxCount;
95  m_termcrit = copy.m_termcrit;
96  m_winSize = copy.m_winSize;
100  m_harris_k = copy.m_harris_k;
101  m_blockSize = copy.m_blockSize;
106 
107  return *this;
108 }
109 
111 {
112 }
113 
124 void vpKltOpencv::initTracking(const cv::Mat &I, const cv::Mat &mask)
125 {
126  m_next_points_id = 0;
127 
128  //cvtColor(I, m_gray, cv::COLOR_BGR2GRAY);
129  I.copyTo(m_gray);
130 
131  for (size_t i=0; i<2; i++) {
132  m_points[i].clear();
133  }
134 
135  m_points_id.clear();
136 
137  cv::goodFeaturesToTrack(m_gray, m_points[1], m_maxCount, m_qualityLevel, m_minDistance, mask, m_blockSize, 0, m_harris_k);
138 
139  if(m_points[1].size() > 0){
140  cv::cornerSubPix(m_gray, m_points[1], cv::Size(m_winSize, m_winSize), cv::Size(-1,-1), m_termcrit);
141 
142  for (size_t i=0; i < m_points[1].size(); i++)
143  m_points_id.push_back(m_next_points_id++);
144  }
145 }
146 
152 void vpKltOpencv::track(const cv::Mat &I)
153 {
154  if(m_points[1].size() == 0)
155  throw vpTrackingException(vpTrackingException::fatalError, "Not enough key points to track.");
156 
157  std::vector<float> err;
158  int flags = 0;
159 
160  cv::swap(m_prevGray, m_gray);
161 
162  if (m_initial_guess) {
163  flags |= cv::OPTFLOW_USE_INITIAL_FLOW;
164  m_initial_guess = false;
165  }
166  else {
167  std::swap(m_points[1], m_points[0]);
168  }
169 
170  //cvtColor(I, m_gray, cv::COLOR_BGR2GRAY);
171  I.copyTo(m_gray);
172 
173  if(m_prevGray.empty()){
174  m_gray.copyTo(m_prevGray);
175  }
176 
177  std::vector<uchar> status;
178 
179  cv::calcOpticalFlowPyrLK(m_prevGray, m_gray, m_points[0], m_points[1], status, err, cv::Size(m_winSize, m_winSize),
181 
182  // Remove points that are lost
183  for (int i=(int)status.size()-1; i>=0; i--) {
184  if (status[(size_t)i] == 0) { // point is lost
185  m_points[0].erase(m_points[0].begin()+i);
186  m_points[1].erase(m_points[1].begin()+i);
187  m_points_id.erase(m_points_id.begin()+i);
188  }
189  }
190 }
191 
205 void vpKltOpencv::getFeature(const int &index, int &id, float &x, float &y) const
206 {
207  if ((size_t)index >= m_points[1].size()){
208  throw(vpException(vpException::badValue, "Feature [%d] doesn't exist", index));
209  }
210 
211  x = m_points[1][(size_t)index].x;
212  y = m_points[1][(size_t)index].y;
213  id = m_points_id[(size_t)index];
214 }
215 
224  const vpColor &color, unsigned int thickness)
225 {
226  vpKltOpencv::display(I, m_points[1], m_points_id, color, thickness);
227 }
228 
241 void vpKltOpencv::display(const vpImage<unsigned char> &I, const std::vector<cv::Point2f> &features,
242  const vpColor &color, unsigned int thickness)
243 {
244  vpImagePoint ip;
245  for (size_t i = 0 ; i < features.size() ; i++) {
246  ip.set_u( vpMath::round(features[i].x ) );
247  ip.set_v( vpMath::round(features[i].y ) );
248  vpDisplay::displayCross(I, ip, 10+thickness, color, thickness);
249  }
250 }
251 
264 void vpKltOpencv::display(const vpImage<vpRGBa> &I, const std::vector<cv::Point2f> &features,
265  const vpColor &color, unsigned int thickness)
266 {
267  vpImagePoint ip;
268  for (size_t i = 0 ; i < features.size() ; i++) {
269  ip.set_u( vpMath::round(features[i].x ) );
270  ip.set_v( vpMath::round(features[i].y ) );
271  vpDisplay::displayCross(I, ip, 10+thickness, color, thickness);
272  }
273 }
274 
289 void vpKltOpencv::display(const vpImage<unsigned char> &I, const std::vector<cv::Point2f> &features,
290  const std::vector<long> &featuresid,
291  const vpColor &color, unsigned int thickness)
292 {
293  vpImagePoint ip;
294  for (size_t i = 0; i < features.size(); i++) {
295  ip.set_u( vpMath::round(features[i].x ) );
296  ip.set_v( vpMath::round(features[i].y ) );
297  vpDisplay::displayCross(I, ip, 10, color, thickness);
298 
299  std::ostringstream id;
300  id << featuresid[i];
301  ip.set_u( vpMath::round( features[i].x + 5 ) );
302  vpDisplay::displayText(I, ip, id.str(), color);
303  }
304 }
305 
320 void vpKltOpencv::display(const vpImage<vpRGBa> &I, const std::vector<cv::Point2f> &features,
321  const std::vector<long> &featuresid,
322  const vpColor &color, unsigned int thickness)
323 {
324  vpImagePoint ip;
325  for (size_t i = 0 ; i < features.size() ; i++) {
326  ip.set_u( vpMath::round(features[i].x ) );
327  ip.set_v( vpMath::round(features[i].y ) );
328  vpDisplay::displayCross(I, ip, 10, color, thickness);
329 
330  std::ostringstream id;
331  id << featuresid[i];
332  ip.set_u( vpMath::round( features[i].x + 5 ) );
333  vpDisplay::displayText(I, ip, id.str(), color);
334  }
335 }
336 
342 void vpKltOpencv::setMaxFeatures(const int maxCount)
343 {
344  m_maxCount = maxCount;
345 }
346 
353 void vpKltOpencv::setWindowSize(const int winSize)
354 {
355  m_winSize = winSize;
356 }
357 
366 void vpKltOpencv::setQuality(double qualityLevel)
367 {
368  m_qualityLevel = qualityLevel;
369 }
370 
377 {
378  m_harris_k = harris_k;
379 }
380 
386 void vpKltOpencv::setUseHarris(const int useHarrisDetector)
387 {
388  m_useHarrisDetector = useHarrisDetector;
389 }
390 
397 void vpKltOpencv::setMinDistance(double minDistance)
398 {
399  m_minDistance = minDistance;
400 }
401 
406 void vpKltOpencv::setMinEigThreshold(double minEigThreshold)
407 {
408  m_minEigThreshold = minEigThreshold;
409 }
410 
420 void vpKltOpencv::setBlockSize(const int blockSize)
421 {
422  m_blockSize = blockSize;
423 }
424 
432 void vpKltOpencv::setPyramidLevels(const int pyrMaxLevel)
433 {
434  m_pyrMaxLevel = pyrMaxLevel;
435 }
436 
448 void
449 vpKltOpencv::setInitialGuess(const std::vector<cv::Point2f> &guess_pts)
450 {
451  if(guess_pts.size() != m_points[1].size()){
453  "Cannot set initial guess: size feature vector [%d] and guess vector [%d] doesn't match",
454  m_points[1].size(), guess_pts.size()));
455  }
456 
457  m_points[1] = guess_pts;
458  m_initial_guess = true;
459 }
460 
468 void
469 vpKltOpencv::initTracking(const cv::Mat &I, const std::vector<cv::Point2f> &pts)
470 {
471  m_initial_guess = false;
472  m_points[1] = pts;
473  m_next_points_id = 0;
474  m_points_id.clear();
475  for(size_t i=0; i < m_points[1].size(); i++) {
476  m_points_id.push_back(m_next_points_id ++);
477  }
478 
479  I.copyTo(m_gray);
480 }
481 
482 void
483 vpKltOpencv::initTracking(const cv::Mat &I, const std::vector<cv::Point2f> &pts, const std::vector<long> &ids)
484 {
485  m_initial_guess = false;
486  m_points[1] = pts;
487  m_points_id.clear();
488 
489  if(ids.size() != pts.size()){
490  m_next_points_id = 0;
491  for(size_t i=0; i < m_points[1].size(); i++)
492  m_points_id.push_back(m_next_points_id ++);
493  }
494  else{
495  long max = 0;
496  for(size_t i=0; i < m_points[1].size(); i++){
497  m_points_id.push_back(ids[i]);
498  if(ids[i] > max) max = ids[i];
499  }
500  m_next_points_id = max + 1;
501  }
502 
503  I.copyTo(m_gray);
504 }
505 
512 void vpKltOpencv::addFeature(const float &x, const float &y)
513 {
514  cv::Point2f f(x, y);
515  m_points[1].push_back(f);
516  m_points_id.push_back(m_next_points_id++);
517 }
518 
529 void vpKltOpencv::addFeature(const long &id, const float &x, const float &y)
530 {
531  cv::Point2f f(x, y);
532  m_points[1].push_back(f);
533  m_points_id.push_back(id);
534  if (id >= m_next_points_id)
535  m_next_points_id = id + 1;
536 }
537 
544 void vpKltOpencv::addFeature(const cv::Point2f &f)
545 {
546  m_points[1].push_back(f);
547  m_points_id.push_back(m_next_points_id++);
548 }
549 
554 void vpKltOpencv::suppressFeature(const int &index)
555 {
556  if ((size_t)index >= m_points[1].size()){
557  throw(vpException(vpException::badValue, "Feature [%d] doesn't exist", index));
558  }
559 
560  m_points[1].erase(m_points[1].begin()+index);
561  m_points_id.erase(m_points_id.begin()+index);
562 }
563 
564 
565 #elif defined(VISP_HAVE_OPENCV)
566 
567 #include <string>
568 
569 #include <visp/vpKltOpencv.h>
570 
571 void vpKltOpencv::clean()
572 {
573  if (image) cvReleaseImage(&image);
574  if (prev_image) cvReleaseImage(&prev_image);
575  if (pyramid) cvReleaseImage(&pyramid);
576  if (prev_pyramid) cvReleaseImage(&prev_pyramid);
577 
578  image = NULL;
579  prev_image = NULL;
580  pyramid = NULL;
581  prev_pyramid = NULL;
582 
583  swap_temp = NULL;
584  countFeatures = 0;
585  countPrevFeatures = 0;
586  flags = 0;
587  initialized = 0;
588  globalcountFeatures = 0;
589 }
590 
591 void vpKltOpencv::cleanAll()
592 {
593  clean();
594  if (features) cvFree(&features);
595  if (prev_features) cvFree(&prev_features);
596  if (status) cvFree(&status);
597  if (lostDuringTrack) cvFree(&lostDuringTrack);
598  if (featuresid) cvFree(&featuresid);
599  if (prev_featuresid) cvFree(&prev_featuresid);
600  features = NULL;
601  prev_features = NULL;
602  status = NULL;
603  lostDuringTrack = 0;
604  featuresid = NULL;
605  prev_featuresid = NULL;
606 }
607 
608 void vpKltOpencv::reset()
609 {
610  clean();
611 
612 }
613 
618  : initialized(0), maxFeatures(50), globalcountFeatures(0), win_size(10), quality(0.01),
619  min_distance(10), harris_free_parameter(0.04), block_size(3), use_harris(1),
620  pyramid_level(3), _tid(-1), image(NULL), prev_image(NULL), pyramid(NULL),
621  prev_pyramid(NULL), swap_temp(NULL), countFeatures(0), countPrevFeatures(0),
622  features(NULL), prev_features(NULL), featuresid(NULL), prev_featuresid(NULL),
623  flags(0), initial_guess(false), lostDuringTrack(0), status(0), OnInitialize(0),
624  OnFeatureLost(0), OnNewFeature(0), OnMeasureFeature(0), IsFeatureValid(0)
625 {
626  features = (CvPoint2D32f*)cvAlloc((unsigned int)maxFeatures*sizeof(features[0]));
627  prev_features = (CvPoint2D32f*)cvAlloc((unsigned int)maxFeatures*sizeof(prev_features[0]));
628  status = (char*)cvAlloc((size_t)maxFeatures);
629  lostDuringTrack = (bool*)cvAlloc((size_t)maxFeatures);
630  featuresid = (long*)cvAlloc((unsigned int)maxFeatures*sizeof(long));
631  prev_featuresid = (long*)cvAlloc((unsigned int)maxFeatures*sizeof(long));
632 }
633 
638  : initialized(0), maxFeatures(50), globalcountFeatures(0), win_size(10), quality(0.01),
639  min_distance(10), harris_free_parameter(0.04), block_size(3), use_harris(1),
640  pyramid_level(3), _tid(-1), image(NULL), prev_image(NULL), pyramid(NULL),
641  prev_pyramid(NULL), swap_temp(NULL), countFeatures(0), countPrevFeatures(0),
642  features(NULL), prev_features(NULL), featuresid(NULL), prev_featuresid(NULL),
643  flags(0), initial_guess(false), lostDuringTrack(0), status(0), OnInitialize(0),
644  OnFeatureLost(0), OnNewFeature(0), OnMeasureFeature(0), IsFeatureValid(0)
645 {
646  *this = copy;
647 }
648 
653 {
654  //Shallow copy of primitives
655  initialized = copy.initialized;
656  maxFeatures = copy.maxFeatures;
657  countFeatures = copy.countFeatures;
658  countPrevFeatures = copy.countPrevFeatures;
659  globalcountFeatures = copy.globalcountFeatures;
660  flags = copy.flags;
661  win_size = copy.win_size;
662  quality = copy.quality;
663  min_distance = copy.min_distance;
664  harris_free_parameter = copy.harris_free_parameter;
665  block_size = copy.block_size;
666  use_harris = copy.use_harris;
667  pyramid_level = copy.pyramid_level;
668  _tid = copy._tid;
669 
670  OnInitialize = copy.OnInitialize;
671  OnFeatureLost = copy.OnFeatureLost;
672  OnNewFeature = copy.OnNewFeature;
673  OnMeasureFeature = copy.OnMeasureFeature;
674  IsFeatureValid = copy.IsFeatureValid;
675 
676  initial_guess = copy.initial_guess;
677  lostDuringTrack = copy.lostDuringTrack;
678 
679  if (!initialized) {
680  status = 0;
681  lostDuringTrack = 0;
682  countFeatures = 0;
683  countPrevFeatures = 0;
684  flags = 0;
685  initialized = 0;
686  globalcountFeatures = 0;
687  }
688 
689  if (copy.image)
690  {
691  image = cvCreateImage(cvGetSize(copy.image), 8, 1);
692  // /*IplImage **/cvCopyImage(copy.image,image);
693  cvCopy(copy.image, image, 0);
694  }
695 
696  if (copy.prev_image)
697  {
698  prev_image = cvCreateImage(cvGetSize(copy.prev_image), IPL_DEPTH_8U, 1);
699  // /*IplImage **/ cvCopyImage(copy.prev_image,prev_image);
700  cvCopy(copy.prev_image, prev_image, 0);
701  }
702 
703  if (copy.pyramid)
704  {
705  pyramid = cvCreateImage(cvGetSize(copy.pyramid), IPL_DEPTH_8U, 1);
706  // /*IplImage **/cvCopyImage(copy.pyramid,pyramid);
707  cvCopy(copy.pyramid, pyramid, 0);
708  }
709 
710  if (copy.prev_pyramid)
711  {
712  prev_pyramid = cvCreateImage(cvGetSize(copy.prev_pyramid), IPL_DEPTH_8U, 1);
713  // /*IplImage **/cvCopyImage(copy.prev_pyramid,prev_pyramid);
714  cvCopy(copy.prev_pyramid, prev_pyramid, 0);
715  }
716 
717  //Deep copy of arrays
718  if (copy.features) {
719  /*CvPoint2D32f **/features =
720  (CvPoint2D32f*)cvAlloc((unsigned int)copy.maxFeatures*sizeof(CvPoint2D32f));
721  for (int i = 0; i < copy.maxFeatures; i++)
722  features[i] = copy.features[i];
723  }
724 
725  if (copy.prev_features) {
726  /*CvPoint2D32f **/prev_features =
727  (CvPoint2D32f*)cvAlloc((unsigned int)copy.maxFeatures*sizeof(CvPoint2D32f));
728  for (int i = 0; i < copy.maxFeatures; i++)
729  prev_features[i] = copy.prev_features[i];
730  }
731 
732  if (copy.featuresid) {
733  /*long **/featuresid = (long*)cvAlloc((unsigned int)copy.maxFeatures*sizeof(long));
734  for (int i = 0; i < copy.maxFeatures; i++)
735  featuresid[i] = copy.featuresid[i];
736  }
737 
738  if (copy.prev_featuresid) {
739  /*long **/prev_featuresid = (long*)cvAlloc((unsigned int)copy.maxFeatures*sizeof(long));
740  for (int i = 0; i < copy.maxFeatures; i++)
741  prev_featuresid[i] = copy.prev_featuresid[i];
742  }
743 
744  if (copy.status) {
745  /*char **/status = (char*)cvAlloc((unsigned int)copy.maxFeatures*sizeof(char));
746  for (int i = 0; i < copy.maxFeatures; i++)
747  status[i] = copy.status[i];
748  }
749 
750  if (copy.lostDuringTrack) {
751  /*bool **/lostDuringTrack = (bool*)cvAlloc((unsigned int)copy.maxFeatures*sizeof(bool));
752  for (int i = 0; i < copy.maxFeatures; i++)
753  lostDuringTrack[i] = copy.lostDuringTrack[i];
754  }
755 
756  return *this;
757 }
758 
760 {
761  cleanAll();
762 }
763 
771 void vpKltOpencv::setMaxFeatures(const int input) {
772  initialized = 0; maxFeatures=input;
773 
774  if (features) cvFree(&features);
775  if (prev_features) cvFree(&prev_features);
776  if (status) cvFree(&status);
777  if (lostDuringTrack) cvFree(&lostDuringTrack);
778  if (featuresid) cvFree(&featuresid);
779  if (prev_featuresid) cvFree(&prev_featuresid);
780 
781 
782  features = (CvPoint2D32f*)cvAlloc((unsigned int)maxFeatures*sizeof(CvPoint2D32f));
783  prev_features = (CvPoint2D32f*)cvAlloc((unsigned int)maxFeatures*sizeof(CvPoint2D32f));
784  status = (char*)cvAlloc((unsigned int)maxFeatures*sizeof(char));
785  lostDuringTrack = (bool*)cvAlloc((unsigned int)maxFeatures*sizeof(bool));
786  featuresid = (long*)cvAlloc((unsigned int)maxFeatures*sizeof(long));
787  prev_featuresid = (long*)cvAlloc((unsigned int)maxFeatures*sizeof(long));
788 }
789 
800 void vpKltOpencv::initTracking(const IplImage *I, const IplImage *mask)
801 {
802  if (!I) {
803  throw(vpException(vpTrackingException::initializationError, "Image Not initialized")) ;
804  }
805 
806  if (I->depth != IPL_DEPTH_8U || I->nChannels != 1) {
807  throw(vpException(vpTrackingException::initializationError, "Bad Image format")) ;
808  }
809 
810  if (mask) {
811  if (mask->depth != IPL_DEPTH_8U || I->nChannels != 1) {
812  throw(vpException(vpTrackingException::initializationError, "Bad Image format")) ;
813  }
814  }
815 
816  //Creation des buffers
817  CvSize Sizeim, SizeI;
818  SizeI = cvGetSize(I);
819  bool b_imOK = true;
820  if(image != NULL){
821  Sizeim = cvGetSize(image);
822  if(SizeI.width != Sizeim.width || SizeI.height != Sizeim.height) b_imOK = false;
823  }
824  if(image == NULL || prev_image == NULL || pyramid==NULL || prev_pyramid ==NULL || !b_imOK){
825  reset();
826  image = cvCreateImage(cvGetSize(I), 8, 1);image->origin = I->origin;
827  prev_image = cvCreateImage(cvGetSize(I), IPL_DEPTH_8U, 1);
828  pyramid = cvCreateImage(cvGetSize(I), IPL_DEPTH_8U, 1);
829  prev_pyramid = cvCreateImage(cvGetSize(I), IPL_DEPTH_8U, 1);
830  }else{
831  swap_temp = 0;
832  countFeatures = 0;
833  countPrevFeatures = 0;
834  flags = 0;
835  initialized = 0;
836  globalcountFeatures = 0;
837  }
838 
839  initialized = 1;
840 
841  //Import
842  cvCopy(I, image, 0);
843 
844  //Recherche de points d'interets
845  countFeatures = maxFeatures;
846  countPrevFeatures = 0;
847  IplImage* eig = cvCreateImage(cvGetSize(image), 32, 1);
848  IplImage* temp = cvCreateImage(cvGetSize(image), 32, 1);
849  cvGoodFeaturesToTrack(image, eig, temp, features,
850  &countFeatures, quality, min_distance,
851  mask, block_size, use_harris, harris_free_parameter);
852  cvFindCornerSubPix(image, features, countFeatures, cvSize(win_size, win_size),
853  cvSize(-1,-1),cvTermCriteria(CV_TERMCRIT_ITER|
854  CV_TERMCRIT_EPS,20,0.03));
855  cvReleaseImage(&eig);
856  cvReleaseImage(&temp);
857 
858  if (OnInitialize)
859  OnInitialize(_tid);
860 
861  //printf("Number of features at init: %d\n", countFeatures);
862  for (int boucle=0; boucle<countFeatures;boucle++) {
863  featuresid[boucle] = globalcountFeatures;
864  globalcountFeatures++;
865 
866  if (OnNewFeature){
867  OnNewFeature(_tid, boucle, featuresid[boucle], features[boucle].x,
868  features[boucle].y);
869  }
870  }
871 }
872 
880 void
881 vpKltOpencv::initTracking(const IplImage *I, CvPoint2D32f *pts, int size)
882 {
883  if (size > maxFeatures)
885  "Cannot initialize tracker from points"));
886 
887  //Creation des buffers
888  CvSize Sizeim, SizeI;
889  SizeI = cvGetSize(I);
890  bool b_imOK = true;
891  if(image != NULL){
892  Sizeim = cvGetSize(image);
893  if(SizeI.width != Sizeim.width || SizeI.height != Sizeim.height) b_imOK = false;
894  }
895  if(image == NULL || prev_image == NULL || pyramid==NULL || prev_pyramid ==NULL || !b_imOK){
896  reset();
897  image = cvCreateImage(cvGetSize(I), 8, 1);image->origin = I->origin;
898  prev_image = cvCreateImage(cvGetSize(I), IPL_DEPTH_8U, 1);
899  pyramid = cvCreateImage(cvGetSize(I), IPL_DEPTH_8U, 1);
900  prev_pyramid = cvCreateImage(cvGetSize(I), IPL_DEPTH_8U, 1);
901  } else {
902  flags = 0;
903  }
904  // Save current features as previous features
905  countFeatures = size;
906  for (int i=0; i<countFeatures;i++) {
907  features[i] = pts[i];
908  featuresid[i] = i;
909  }
910 
911  globalcountFeatures = size;
912  initialized = 1;
913 
914  cvCopy(I, image, 0);
915 }
916 
917 void
918 vpKltOpencv::initTracking(const IplImage *I, CvPoint2D32f *pts, long *fid, int size)
919 {
920  if (size > maxFeatures)
922  "Cannot initialize tracker from points"));
923 
924  //Creation des buffers
925  CvSize Sizeim, SizeI;
926  SizeI = cvGetSize(I);
927  bool b_imOK = true;
928  if(image != NULL){
929  Sizeim = cvGetSize(image);
930  if(SizeI.width != Sizeim.width || SizeI.height != Sizeim.height) b_imOK = false;
931  }
932  if(image == NULL || prev_image == NULL || pyramid==NULL || prev_pyramid ==NULL || !b_imOK){
933  reset();
934  image = cvCreateImage(cvGetSize(I), 8, 1);image->origin = I->origin;
935  prev_image = cvCreateImage(cvGetSize(I), IPL_DEPTH_8U, 1);
936  pyramid = cvCreateImage(cvGetSize(I), IPL_DEPTH_8U, 1);
937  prev_pyramid = cvCreateImage(cvGetSize(I), IPL_DEPTH_8U, 1);
938  } else {
939  flags = 0;
940  }
941  // Save current features as previous features
942  countFeatures = size;
943  long max = 0;
944  for (int i=0; i<countFeatures;i++) {
945  features[i] = pts[i];
946  featuresid[i] = fid[i];
947  if (fid[i] > max)
948  max = fid[i];
949  }
950 
951  globalcountFeatures = max + 1;
952  initialized = 1;
953 
954  cvCopy(I, image, 0);
955 }
956 
957 void vpKltOpencv::track(const IplImage *I)
958 {
959  if (!initialized) {
960  vpERROR_TRACE("KLT Not initialized") ;
962  "KLT Not initialized")) ;
963  }
964 
965  if (!I) {
967  "Image Not initialized")) ;
968  }
969 
970  if (I->depth != IPL_DEPTH_8U || I->nChannels != 1) {
972  "Bad Image format")) ;
973  }
974 
975 
976 
977  CV_SWAP(prev_image, image, swap_temp);
978  CV_SWAP(prev_pyramid, pyramid, swap_temp);
979 
980  cvCopy(I, image, 0);
981 
982  if(!initial_guess){
983  // Save current features as previous features
984  countPrevFeatures = countFeatures;
985  for (int boucle=0; boucle<countFeatures;boucle++) {
986  prev_featuresid[boucle] = featuresid[boucle];
987  }
988 
989  CvPoint2D32f *swap_features = 0;
990  CV_SWAP(prev_features, features, swap_features);
991  }
992 
993  if (countFeatures <= 0) return;
994 
995  cvCalcOpticalFlowPyrLK( prev_image, image, prev_pyramid, pyramid,
996  prev_features, features, countFeatures,
997  cvSize(win_size, win_size), pyramid_level,
998  status, 0, cvTermCriteria(CV_TERMCRIT_ITER
999  |CV_TERMCRIT_EPS,20,0.03),
1000  flags );
1001 
1002  if(!initial_guess)
1003  flags |= CV_LKFLOW_PYR_A_READY;
1004  else{
1005  flags = CV_LKFLOW_PYR_A_READY;
1006  initial_guess = false;
1007  }
1008 
1009  int i,k;
1010  for (i = k = 0; i < countFeatures ; i++) {
1011  if (!status[i]) {
1012  lostDuringTrack[i] = 1;
1013  if (OnFeatureLost)
1014  OnFeatureLost(_tid, i, featuresid[i], features[i].x,
1015  features[i].y);
1016  continue;
1017  }
1018 
1019  if (IsFeatureValid) {
1020  if (!IsFeatureValid(_tid, features[i].x, features[i].y)) {
1021  lostDuringTrack[i] = 1;
1022  if (OnFeatureLost)
1023  OnFeatureLost(_tid, i, featuresid[i], features[i].x, features[i].y);
1024  continue;
1025  }
1026  }
1027  features[k] = features[i];
1028  featuresid[k] = featuresid[i];
1029 
1030  if (OnMeasureFeature) OnMeasureFeature(_tid, k, featuresid[k], features[k].x, features[k].y);
1031 
1032  lostDuringTrack[i] = 0;
1033  k++;
1034  }
1035  countFeatures = k;
1036 }
1037 
1046  vpColor color, unsigned int thickness)
1047 {
1048  if ((features == 0) || (I.bitmap==0) || (!initialized))
1049  {
1050  vpERROR_TRACE(" Memory problem ");
1051  throw(vpException(vpException::memoryAllocationError," Memory problem"));
1052  }
1053 
1054  vpKltOpencv::display(I, features, featuresid, countFeatures, color, thickness);
1055 }
1056 
1070 void vpKltOpencv::getFeature(int index, int &id, float &x, float &y) const
1071 {
1072  if (index >= countFeatures)
1073  {
1074  vpERROR_TRACE(" Memory problem ");
1075  throw(vpException(vpException::memoryAllocationError," Memory problem"));
1076  }
1077 
1078  x = features[index].x;
1079  y = features[index].y;
1080  id = featuresid[index];
1081 }
1082 
1083 
1091 void
1092 vpKltOpencv::setInitialGuess(CvPoint2D32f **guess_pts)
1093 {
1094  // Save current features as previous features
1095  countPrevFeatures = countFeatures;
1096  for (int boucle=0; boucle<countFeatures;boucle++) {
1097  prev_featuresid[boucle] = featuresid[boucle];
1098  }
1099 
1100  CvPoint2D32f *swap_features = NULL;
1101  CV_SWAP(prev_features, *guess_pts, swap_features);
1102 
1103  CV_SWAP(features, prev_features, swap_features);
1104 
1105  flags |= CV_LKFLOW_INITIAL_GUESSES;
1106 
1107  initial_guess = true;
1108 }
1109 
1118 void vpKltOpencv::getPrevFeature(int index, int &id, float &x, float &y) const
1119 {
1120  if (index >= countPrevFeatures)
1121  {
1122  vpERROR_TRACE(" Memory problem ");
1123  throw(vpException(vpException::memoryAllocationError," Memory problem"));
1124  }
1125 
1126  x = prev_features[index].x;
1127  y = prev_features[index].y;
1128  id = prev_featuresid[index];
1129 }
1130 
1137 void vpKltOpencv::addFeature(const int &id,
1138  const float &x, const float &y)
1139 {
1140  if (maxFeatures == countFeatures)
1141  {
1142  vpERROR_TRACE(" Cannot add the feature ");
1143  return;
1144  }
1145 
1146  CvPoint2D32f f;
1147  f.x = x;
1148  f.y = y;
1149  features[countFeatures] = f;
1150  featuresid[countFeatures] = id;
1151  countFeatures ++;
1152 }
1153 
1154 void vpKltOpencv::suppressFeature(int index)
1155 {
1156  if (index >= countFeatures)
1157  {
1158  vpERROR_TRACE(" Memory problem ");
1159  throw(vpException(vpException::memoryAllocationError," Memory problem"));
1160  }
1161 
1162  countFeatures --;
1163 
1164  for (int i=index ; i < countFeatures; i ++) {
1165  features[i] = features[i+1];
1166  featuresid[i] = featuresid[i+1];
1167  }
1168 }
1169 
1184 void vpKltOpencv::display(const vpImage<unsigned char>& I,const CvPoint2D32f* features_list,
1185  const int &nbFeatures, vpColor color, unsigned int thickness)
1186 {
1187  vpImagePoint ip;
1188  for (int i = 0 ; i < nbFeatures ; i++)
1189  {
1190  ip.set_u( vpMath::round(features_list[i].x ) );
1191  ip.set_v( vpMath::round(features_list[i].y ) );
1192  vpDisplay::displayCross(I, ip, 10+thickness, color, thickness) ;
1193  }
1194 }
1209 void vpKltOpencv::display(const vpImage<vpRGBa>& I,const CvPoint2D32f* features_list,
1210  const int &nbFeatures, vpColor color, unsigned int thickness)
1211 {
1212  vpImagePoint ip;
1213  for (int i = 0 ; i < nbFeatures ; i++)
1214  {
1215  ip.set_u( vpMath::round(features_list[i].x ) );
1216  ip.set_v( vpMath::round(features_list[i].y ) );
1217  vpDisplay::displayCross(I, ip, 10+thickness, color, thickness) ;
1218  }
1219 }
1220 
1237 void vpKltOpencv::display(const vpImage<unsigned char>& I,const CvPoint2D32f* features_list,
1238  const long *featuresid_list, const int &nbFeatures,
1239  vpColor color, unsigned int thickness)
1240 {
1241  vpImagePoint ip;
1242  for (int i = 0 ; i < nbFeatures ; i++)
1243  {
1244  ip.set_u( vpMath::round(features_list[i].x ) );
1245  ip.set_v( vpMath::round(features_list[i].y ) );
1246  vpDisplay::displayCross(I, ip, 10+thickness, color, thickness) ;
1247 
1248  char id[10];
1249  sprintf(id, "%ld", featuresid_list[i]);
1250  ip.set_u( vpMath::round( features_list[i].x + 5 ) );
1251  vpDisplay::displayText(I, ip, id, color);
1252  }
1253 }
1254 
1271 void vpKltOpencv::display(const vpImage<vpRGBa>& I,const CvPoint2D32f* features_list,
1272  const long *featuresid_list, const int &nbFeatures,
1273  vpColor color, unsigned int thickness)
1274 {
1275  vpImagePoint ip;
1276  for (int i = 0 ; i < nbFeatures ; i++)
1277  {
1278  ip.set_u( vpMath::round(features_list[i].x ) );
1279  ip.set_v( vpMath::round(features_list[i].y ) );
1280  vpDisplay::displayCross(I, ip, 10, color, thickness) ;
1281 
1282  char id[10];
1283  sprintf(id, "%ld", featuresid_list[i]);
1284  ip.set_u( vpMath::round( features_list[i].x + 5 ) );
1285  vpDisplay::displayText(I, ip, id, color);
1286  }
1287 }
1288 
1289 #endif
void addFeature(const float &x, const float &y)
double m_harris_k
Definition: vpKltOpencv.h:167
cv::Mat m_gray
Definition: vpKltOpencv.h:158
void setHarrisFreeParameter(double harris_k)
#define vpERROR_TRACE
Definition: vpDebug.h:395
Type * bitmap
points toward the bitmap
Definition: vpImage.h:120
vpKltOpencv & operator=(const vpKltOpencv &copy)
Definition: vpKltOpencv.cpp:87
cv::Mat m_prevGray
Definition: vpKltOpencv.h:158
Class to define colors available for display functionnalities.
Definition: vpColor.h:125
void setMaxFeatures(const int maxCount)
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
Definition: vpDisplay.cpp:887
void setMinEigThreshold(double minEigThreshold)
void setMinDistance(double minDistance)
error that can be emited by ViSP classes.
Definition: vpException.h:76
virtual ~vpKltOpencv()
cv::TermCriteria m_termcrit
Definition: vpKltOpencv.h:162
static int round(const double x)
Definition: vpMath.h:228
void display(const vpImage< unsigned char > &I, const vpColor &color=vpColor::red, unsigned int thickness=1)
void setQuality(double qualityLevel)
bool m_initial_guess
Definition: vpKltOpencv.h:172
std::vector< long > m_points_id
Keypoint id.
Definition: vpKltOpencv.h:160
Error that can be emited by the vpTracker class and its derivates.
void set_u(const double u)
Definition: vpImagePoint.h:217
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:228
void getFeature(const int &index, int &id, float &x, float &y) const
double m_minDistance
Definition: vpKltOpencv.h:165
double m_minEigThreshold
Definition: vpKltOpencv.h:166
void initTracking(const cv::Mat &I, const cv::Mat &mask=cv::Mat())
void setInitialGuess(const std::vector< cv::Point2f > &guess_pts)
void setPyramidLevels(const int pyrMaxLevel)
double m_qualityLevel
Definition: vpKltOpencv.h:164
int m_useHarrisDetector
Definition: vpKltOpencv.h:169
void setWindowSize(const int winSize)
Wrapper for the KLT (Kanade-Lucas-Tomasi) feature tracker implemented in OpenCV.
Definition: vpKltOpencv.h:79
void suppressFeature(const int &index)
void setBlockSize(const int blockSize)
std::vector< cv::Point2f > m_points[2]
Previous [0] and current [1] keypoint location.
Definition: vpKltOpencv.h:159
long m_next_points_id
Definition: vpKltOpencv.h:171
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:93
void setUseHarris(const int useHarrisDetector)
int m_pyrMaxLevel
Definition: vpKltOpencv.h:170
void track(const cv::Mat &I)