51 #include <visp/vpConfig.h>
53 #if defined(VISP_HAVE_OPENCV) && (VISP_HAVE_OPENCV_VERSION >= 0x020408)
57 #include <visp/vpDisplay.h>
58 #include <visp/vpKltOpencv.h>
59 #include <visp/vpTrackingException.h>
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)
69 m_termcrit = cv::TermCriteria(cv::TermCriteria::COUNT|cv::TermCriteria::EPS, 20, 0.03);
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)
131 for (
size_t i=0; i<2; i++) {
142 for (
size_t i=0; i <
m_points[1].size(); i++)
157 std::vector<float> err;
163 flags |= cv::OPTFLOW_USE_INITIAL_FLOW;
177 std::vector<uchar> status;
183 for (
int i=(
int)status.size()-1; i>=0; i--) {
184 if (status[(
size_t)i] == 0) {
207 if ((
size_t)index >=
m_points[1].size()){
224 const vpColor &color,
unsigned int thickness)
242 const vpColor &color,
unsigned int thickness)
245 for (
size_t i = 0 ; i < features.size() ; i++) {
265 const vpColor &color,
unsigned int thickness)
268 for (
size_t i = 0 ; i < features.size() ; i++) {
290 const std::vector<long> &featuresid,
291 const vpColor &color,
unsigned int thickness)
294 for (
size_t i = 0; i < features.size(); i++) {
299 std::ostringstream id;
321 const std::vector<long> &featuresid,
322 const vpColor &color,
unsigned int thickness)
325 for (
size_t i = 0 ; i < features.size() ; i++) {
330 std::ostringstream id;
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()));
475 for(
size_t i=0; i <
m_points[1].size(); i++) {
489 if(ids.size() != pts.size()){
491 for(
size_t i=0; i <
m_points[1].size(); i++)
496 for(
size_t i=0; i <
m_points[1].size(); i++){
498 if(ids[i] > max) max = ids[i];
556 if ((
size_t)index >=
m_points[1].size()){
565 #elif defined(VISP_HAVE_OPENCV)
569 #include <visp/vpKltOpencv.h>
571 void vpKltOpencv::clean()
573 if (image) cvReleaseImage(&image);
574 if (prev_image) cvReleaseImage(&prev_image);
575 if (pyramid) cvReleaseImage(&pyramid);
576 if (prev_pyramid) cvReleaseImage(&prev_pyramid);
585 countPrevFeatures = 0;
588 globalcountFeatures = 0;
591 void vpKltOpencv::cleanAll()
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);
601 prev_features = NULL;
605 prev_featuresid = NULL;
608 void vpKltOpencv::reset()
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)
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));
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)
655 initialized = copy.initialized;
656 maxFeatures = copy.maxFeatures;
657 countFeatures = copy.countFeatures;
658 countPrevFeatures = copy.countPrevFeatures;
659 globalcountFeatures = copy.globalcountFeatures;
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;
670 OnInitialize = copy.OnInitialize;
671 OnFeatureLost = copy.OnFeatureLost;
672 OnNewFeature = copy.OnNewFeature;
673 OnMeasureFeature = copy.OnMeasureFeature;
674 IsFeatureValid = copy.IsFeatureValid;
676 initial_guess = copy.initial_guess;
677 lostDuringTrack = copy.lostDuringTrack;
683 countPrevFeatures = 0;
686 globalcountFeatures = 0;
691 image = cvCreateImage(cvGetSize(copy.image), 8, 1);
693 cvCopy(copy.image, image, 0);
698 prev_image = cvCreateImage(cvGetSize(copy.prev_image), IPL_DEPTH_8U, 1);
700 cvCopy(copy.prev_image, prev_image, 0);
705 pyramid = cvCreateImage(cvGetSize(copy.pyramid), IPL_DEPTH_8U, 1);
707 cvCopy(copy.pyramid, pyramid, 0);
710 if (copy.prev_pyramid)
712 prev_pyramid = cvCreateImage(cvGetSize(copy.prev_pyramid), IPL_DEPTH_8U, 1);
714 cvCopy(copy.prev_pyramid, prev_pyramid, 0);
720 (CvPoint2D32f*)cvAlloc((
unsigned int)copy.maxFeatures*
sizeof(CvPoint2D32f));
721 for (
int i = 0; i < copy.maxFeatures; i++)
722 features[i] = copy.features[i];
725 if (copy.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];
732 if (copy.featuresid) {
733 featuresid = (
long*)cvAlloc((
unsigned int)copy.maxFeatures*
sizeof(long));
734 for (
int i = 0; i < copy.maxFeatures; i++)
735 featuresid[i] = copy.featuresid[i];
738 if (copy.prev_featuresid) {
739 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];
745 status = (
char*)cvAlloc((
unsigned int)copy.maxFeatures*
sizeof(char));
746 for (
int i = 0; i < copy.maxFeatures; i++)
747 status[i] = copy.status[i];
750 if (copy.lostDuringTrack) {
751 lostDuringTrack = (
bool*)cvAlloc((
unsigned int)copy.maxFeatures*
sizeof(bool));
752 for (
int i = 0; i < copy.maxFeatures; i++)
753 lostDuringTrack[i] = copy.lostDuringTrack[i];
772 initialized = 0; maxFeatures=input;
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);
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));
806 if (I->depth != IPL_DEPTH_8U || I->nChannels != 1) {
811 if (mask->depth != IPL_DEPTH_8U || I->nChannels != 1) {
817 CvSize Sizeim, SizeI;
818 SizeI = cvGetSize(I);
821 Sizeim = cvGetSize(image);
822 if(SizeI.width != Sizeim.width || SizeI.height != Sizeim.height) b_imOK =
false;
824 if(image == NULL || prev_image == NULL || pyramid==NULL || prev_pyramid ==NULL || !b_imOK){
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);
833 countPrevFeatures = 0;
836 globalcountFeatures = 0;
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);
862 for (
int boucle=0; boucle<countFeatures;boucle++) {
863 featuresid[boucle] = globalcountFeatures;
864 globalcountFeatures++;
867 OnNewFeature(_tid, boucle, featuresid[boucle], features[boucle].x,
883 if (size > maxFeatures)
885 "Cannot initialize tracker from points"));
888 CvSize Sizeim, SizeI;
889 SizeI = cvGetSize(I);
892 Sizeim = cvGetSize(image);
893 if(SizeI.width != Sizeim.width || SizeI.height != Sizeim.height) b_imOK =
false;
895 if(image == NULL || prev_image == NULL || pyramid==NULL || prev_pyramid ==NULL || !b_imOK){
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);
905 countFeatures = size;
906 for (
int i=0; i<countFeatures;i++) {
907 features[i] = pts[i];
911 globalcountFeatures = size;
920 if (size > maxFeatures)
922 "Cannot initialize tracker from points"));
925 CvSize Sizeim, SizeI;
926 SizeI = cvGetSize(I);
929 Sizeim = cvGetSize(image);
930 if(SizeI.width != Sizeim.width || SizeI.height != Sizeim.height) b_imOK =
false;
932 if(image == NULL || prev_image == NULL || pyramid==NULL || prev_pyramid ==NULL || !b_imOK){
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);
942 countFeatures = size;
944 for (
int i=0; i<countFeatures;i++) {
945 features[i] = pts[i];
946 featuresid[i] = fid[i];
951 globalcountFeatures = max + 1;
962 "KLT Not initialized")) ;
967 "Image Not initialized")) ;
970 if (I->depth != IPL_DEPTH_8U || I->nChannels != 1) {
972 "Bad Image format")) ;
977 CV_SWAP(prev_image, image, swap_temp);
978 CV_SWAP(prev_pyramid, pyramid, swap_temp);
984 countPrevFeatures = countFeatures;
985 for (
int boucle=0; boucle<countFeatures;boucle++) {
986 prev_featuresid[boucle] = featuresid[boucle];
989 CvPoint2D32f *swap_features = 0;
990 CV_SWAP(prev_features, features, swap_features);
993 if (countFeatures <= 0)
return;
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),
1003 flags |= CV_LKFLOW_PYR_A_READY;
1005 flags = CV_LKFLOW_PYR_A_READY;
1006 initial_guess =
false;
1010 for (i = k = 0; i < countFeatures ; i++) {
1012 lostDuringTrack[i] = 1;
1014 OnFeatureLost(_tid, i, featuresid[i], features[i].x,
1019 if (IsFeatureValid) {
1020 if (!IsFeatureValid(_tid, features[i].x, features[i].y)) {
1021 lostDuringTrack[i] = 1;
1023 OnFeatureLost(_tid, i, featuresid[i], features[i].x, features[i].y);
1027 features[k] = features[i];
1028 featuresid[k] = featuresid[i];
1030 if (OnMeasureFeature) OnMeasureFeature(_tid, k, featuresid[k], features[k].x, features[k].y);
1032 lostDuringTrack[i] = 0;
1046 vpColor color,
unsigned int thickness)
1048 if ((features == 0) || (I.
bitmap==0) || (!initialized))
1072 if (index >= countFeatures)
1078 x = features[index].x;
1079 y = features[index].y;
1080 id = featuresid[index];
1095 countPrevFeatures = countFeatures;
1096 for (
int boucle=0; boucle<countFeatures;boucle++) {
1097 prev_featuresid[boucle] = featuresid[boucle];
1100 CvPoint2D32f *swap_features = NULL;
1101 CV_SWAP(prev_features, *guess_pts, swap_features);
1103 CV_SWAP(features, prev_features, swap_features);
1105 flags |= CV_LKFLOW_INITIAL_GUESSES;
1107 initial_guess =
true;
1118 void vpKltOpencv::getPrevFeature(
int index,
int &
id,
float &x,
float &y)
const
1120 if (index >= countPrevFeatures)
1126 x = prev_features[index].x;
1127 y = prev_features[index].y;
1128 id = prev_featuresid[index];
1138 const float &x,
const float &y)
1140 if (maxFeatures == countFeatures)
1149 features[countFeatures] = f;
1150 featuresid[countFeatures] = id;
1156 if (index >= countFeatures)
1164 for (
int i=index ; i < countFeatures; i ++) {
1165 features[i] = features[i+1];
1166 featuresid[i] = featuresid[i+1];
1185 const int &nbFeatures,
vpColor color,
unsigned int thickness)
1188 for (
int i = 0 ; i < nbFeatures ; i++)
1210 const int &nbFeatures,
vpColor color,
unsigned int thickness)
1213 for (
int i = 0 ; i < nbFeatures ; i++)
1238 const long *featuresid_list,
const int &nbFeatures,
1239 vpColor color,
unsigned int thickness)
1242 for (
int i = 0 ; i < nbFeatures ; i++)
1249 sprintf(
id,
"%ld", featuresid_list[i]);
1272 const long *featuresid_list,
const int &nbFeatures,
1273 vpColor color,
unsigned int thickness)
1276 for (
int i = 0 ; i < nbFeatures ; i++)
1283 sprintf(
id,
"%ld", featuresid_list[i]);
void addFeature(const float &x, const float &y)
void setHarrisFreeParameter(double harris_k)
Type * bitmap
points toward the bitmap
vpKltOpencv & operator=(const vpKltOpencv ©)
Class to define colors available for display functionnalities.
void setMaxFeatures(const int maxCount)
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
void setMinEigThreshold(double minEigThreshold)
void setMinDistance(double minDistance)
error that can be emited by ViSP classes.
cv::TermCriteria m_termcrit
static int round(const double x)
void display(const vpImage< unsigned char > &I, const vpColor &color=vpColor::red, unsigned int thickness=1)
void setQuality(double qualityLevel)
std::vector< long > m_points_id
Keypoint id.
Error that can be emited by the vpTracker class and its derivates.
void set_u(const double u)
virtual void displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)=0
void set_v(const double v)
void getFeature(const int &index, int &id, float &x, float &y) const
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)
void setWindowSize(const int winSize)
Wrapper for the KLT (Kanade-Lucas-Tomasi) feature tracker implemented in OpenCV.
void suppressFeature(const int &index)
void setBlockSize(const int blockSize)
std::vector< cv::Point2f > m_points[2]
Previous [0] and current [1] keypoint location.
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
void setUseHarris(const int useHarrisDetector)
void track(const cv::Mat &I)