47 #include <visp3/core/vpConfig.h>
49 #if defined(VISP_HAVE_OPENCV) && (VISP_HAVE_OPENCV_VERSION >= 0x020408)
53 #include <visp3/core/vpDisplay.h>
54 #include <visp3/klt/vpKltOpencv.h>
55 #include <visp3/core/vpTrackingException.h>
61 : m_gray(), m_prevGray(), m_points_id(), m_maxCount(500), m_termcrit(), m_winSize(10), m_qualityLevel(0.01),
62 m_minDistance(15), m_minEigThreshold(1e-4), m_harris_k(0.04), m_blockSize(3), m_useHarrisDetector(1), m_pyrMaxLevel(3),
63 m_next_points_id(0), m_initial_guess(false)
65 m_termcrit = cv::TermCriteria(cv::TermCriteria::COUNT|cv::TermCriteria::EPS, 20, 0.03);
73 : m_gray(), m_prevGray(), m_points_id(), m_maxCount(500), m_termcrit(), m_winSize(10), m_qualityLevel(0.01),
74 m_minDistance(15), m_minEigThreshold(1e-4), m_harris_k(0.04), m_blockSize(3), m_useHarrisDetector(1), m_pyrMaxLevel(3),
75 m_next_points_id(0), m_initial_guess(false)
127 for (
size_t i=0; i<2; i++) {
138 for (
size_t i=0; i <
m_points[1].size(); i++)
153 std::vector<float> err;
159 flags |= cv::OPTFLOW_USE_INITIAL_FLOW;
173 std::vector<uchar> status;
179 for (
int i=(
int)status.size()-1; i>=0; i--) {
180 if (status[(
size_t)i] == 0) {
203 if ((
size_t)index >=
m_points[1].size()){
220 const vpColor &color,
unsigned int thickness)
238 const vpColor &color,
unsigned int thickness)
241 for (
size_t i = 0 ; i < features.size() ; i++) {
261 const vpColor &color,
unsigned int thickness)
264 for (
size_t i = 0 ; i < features.size() ; i++) {
286 const std::vector<long> &featuresid,
287 const vpColor &color,
unsigned int thickness)
290 for (
size_t i = 0; i < features.size(); i++) {
295 std::ostringstream id;
317 const std::vector<long> &featuresid,
318 const vpColor &color,
unsigned int thickness)
321 for (
size_t i = 0 ; i < features.size() ; i++) {
326 std::ostringstream id;
447 if(guess_pts.size() !=
m_points[1].size()){
449 "Cannot set initial guess: size feature vector [%d] and guess vector [%d] doesn't match",
450 m_points[1].size(), guess_pts.size()));
473 if(guess_pts.size() != init_pts.size()){
475 "Cannot set initial guess: size init vector [%d] and guess vector [%d] doesn't match",
476 init_pts.size(), guess_pts.size()));
499 for(
size_t i=0; i <
m_points[1].size(); i++) {
513 if(ids.size() != pts.size()){
515 for(
size_t i=0; i <
m_points[1].size(); i++)
520 for(
size_t i=0; i <
m_points[1].size(); i++){
522 if(ids[i] > max) max = ids[i];
581 if ((
size_t)index >=
m_points[1].size()){
590 #elif defined(VISP_HAVE_OPENCV)
594 #include <visp3/klt/vpKltOpencv.h>
596 void vpKltOpencv::clean()
598 if (image) cvReleaseImage(&image);
599 if (prev_image) cvReleaseImage(&prev_image);
600 if (pyramid) cvReleaseImage(&pyramid);
601 if (prev_pyramid) cvReleaseImage(&prev_pyramid);
610 countPrevFeatures = 0;
613 globalcountFeatures = 0;
616 void vpKltOpencv::cleanAll()
619 if (features) cvFree(&features);
620 if (prev_features) cvFree(&prev_features);
621 if (status) cvFree(&status);
622 if (lostDuringTrack) cvFree(&lostDuringTrack);
623 if (featuresid) cvFree(&featuresid);
624 if (prev_featuresid) cvFree(&prev_featuresid);
626 prev_features = NULL;
630 prev_featuresid = NULL;
633 void vpKltOpencv::reset()
643 : initialized(0), maxFeatures(50), globalcountFeatures(0), win_size(10), quality(0.01),
644 min_distance(10), harris_free_parameter(0.04), block_size(3), use_harris(1),
645 pyramid_level(3), _tid(-1), image(NULL), prev_image(NULL), pyramid(NULL),
646 prev_pyramid(NULL), swap_temp(NULL), countFeatures(0), countPrevFeatures(0),
647 features(NULL), prev_features(NULL), featuresid(NULL), prev_featuresid(NULL),
648 flags(0), initial_guess(false), lostDuringTrack(0), status(0), OnInitialize(0),
649 OnFeatureLost(0), OnNewFeature(0), OnMeasureFeature(0), IsFeatureValid(0)
651 features = (CvPoint2D32f*)cvAlloc((
unsigned int)maxFeatures*
sizeof(features[0]));
652 prev_features = (CvPoint2D32f*)cvAlloc((
unsigned int)maxFeatures*
sizeof(prev_features[0]));
653 status = (
char*)cvAlloc((
size_t)maxFeatures);
654 lostDuringTrack = (
bool*)cvAlloc((
size_t)maxFeatures);
655 featuresid = (
long*)cvAlloc((
unsigned int)maxFeatures*
sizeof(long));
656 prev_featuresid = (
long*)cvAlloc((
unsigned int)maxFeatures*
sizeof(long));
663 : initialized(0), maxFeatures(50), globalcountFeatures(0), win_size(10), quality(0.01),
664 min_distance(10), harris_free_parameter(0.04), block_size(3), use_harris(1),
665 pyramid_level(3), _tid(-1), image(NULL), prev_image(NULL), pyramid(NULL),
666 prev_pyramid(NULL), swap_temp(NULL), countFeatures(0), countPrevFeatures(0),
667 features(NULL), prev_features(NULL), featuresid(NULL), prev_featuresid(NULL),
668 flags(0), initial_guess(false), lostDuringTrack(0), status(0), OnInitialize(0),
669 OnFeatureLost(0), OnNewFeature(0), OnMeasureFeature(0), IsFeatureValid(0)
680 initialized = copy.initialized;
681 maxFeatures = copy.maxFeatures;
682 countFeatures = copy.countFeatures;
683 countPrevFeatures = copy.countPrevFeatures;
684 globalcountFeatures = copy.globalcountFeatures;
686 win_size = copy.win_size;
687 quality = copy.quality;
688 min_distance = copy.min_distance;
689 harris_free_parameter = copy.harris_free_parameter;
690 block_size = copy.block_size;
691 use_harris = copy.use_harris;
692 pyramid_level = copy.pyramid_level;
695 OnInitialize = copy.OnInitialize;
696 OnFeatureLost = copy.OnFeatureLost;
697 OnNewFeature = copy.OnNewFeature;
698 OnMeasureFeature = copy.OnMeasureFeature;
699 IsFeatureValid = copy.IsFeatureValid;
701 initial_guess = copy.initial_guess;
702 lostDuringTrack = copy.lostDuringTrack;
708 countPrevFeatures = 0;
711 globalcountFeatures = 0;
716 image = cvCreateImage(cvGetSize(copy.image), 8, 1);
718 cvCopy(copy.image, image, 0);
723 prev_image = cvCreateImage(cvGetSize(copy.prev_image), IPL_DEPTH_8U, 1);
725 cvCopy(copy.prev_image, prev_image, 0);
730 pyramid = cvCreateImage(cvGetSize(copy.pyramid), IPL_DEPTH_8U, 1);
732 cvCopy(copy.pyramid, pyramid, 0);
735 if (copy.prev_pyramid)
737 prev_pyramid = cvCreateImage(cvGetSize(copy.prev_pyramid), IPL_DEPTH_8U, 1);
739 cvCopy(copy.prev_pyramid, prev_pyramid, 0);
745 (CvPoint2D32f*)cvAlloc((
unsigned int)copy.maxFeatures*
sizeof(CvPoint2D32f));
746 for (
int i = 0; i < copy.maxFeatures; i++)
747 features[i] = copy.features[i];
750 if (copy.prev_features) {
752 (CvPoint2D32f*)cvAlloc((
unsigned int)copy.maxFeatures*
sizeof(CvPoint2D32f));
753 for (
int i = 0; i < copy.maxFeatures; i++)
754 prev_features[i] = copy.prev_features[i];
757 if (copy.featuresid) {
758 featuresid = (
long*)cvAlloc((
unsigned int)copy.maxFeatures*
sizeof(long));
759 for (
int i = 0; i < copy.maxFeatures; i++)
760 featuresid[i] = copy.featuresid[i];
763 if (copy.prev_featuresid) {
764 prev_featuresid = (
long*)cvAlloc((
unsigned int)copy.maxFeatures*
sizeof(long));
765 for (
int i = 0; i < copy.maxFeatures; i++)
766 prev_featuresid[i] = copy.prev_featuresid[i];
770 status = (
char*)cvAlloc((
unsigned int)copy.maxFeatures*
sizeof(char));
771 for (
int i = 0; i < copy.maxFeatures; i++)
772 status[i] = copy.status[i];
775 if (copy.lostDuringTrack) {
776 lostDuringTrack = (
bool*)cvAlloc((
unsigned int)copy.maxFeatures*
sizeof(bool));
777 for (
int i = 0; i < copy.maxFeatures; i++)
778 lostDuringTrack[i] = copy.lostDuringTrack[i];
797 initialized = 0; maxFeatures=input;
799 if (features) cvFree(&features);
800 if (prev_features) cvFree(&prev_features);
801 if (status) cvFree(&status);
802 if (lostDuringTrack) cvFree(&lostDuringTrack);
803 if (featuresid) cvFree(&featuresid);
804 if (prev_featuresid) cvFree(&prev_featuresid);
807 features = (CvPoint2D32f*)cvAlloc((
unsigned int)maxFeatures*
sizeof(CvPoint2D32f));
808 prev_features = (CvPoint2D32f*)cvAlloc((
unsigned int)maxFeatures*
sizeof(CvPoint2D32f));
809 status = (
char*)cvAlloc((
unsigned int)maxFeatures*
sizeof(char));
810 lostDuringTrack = (
bool*)cvAlloc((
unsigned int)maxFeatures*
sizeof(bool));
811 featuresid = (
long*)cvAlloc((
unsigned int)maxFeatures*
sizeof(long));
812 prev_featuresid = (
long*)cvAlloc((
unsigned int)maxFeatures*
sizeof(long));
831 if (I->depth != IPL_DEPTH_8U || I->nChannels != 1) {
836 if (mask->depth != IPL_DEPTH_8U || I->nChannels != 1) {
842 CvSize Sizeim, SizeI;
843 SizeI = cvGetSize(I);
846 Sizeim = cvGetSize(image);
847 if(SizeI.width != Sizeim.width || SizeI.height != Sizeim.height) b_imOK =
false;
849 if(image == NULL || prev_image == NULL || pyramid==NULL || prev_pyramid ==NULL || !b_imOK){
851 image = cvCreateImage(cvGetSize(I), 8, 1);image->origin = I->origin;
852 prev_image = cvCreateImage(cvGetSize(I), IPL_DEPTH_8U, 1);
853 pyramid = cvCreateImage(cvGetSize(I), IPL_DEPTH_8U, 1);
854 prev_pyramid = cvCreateImage(cvGetSize(I), IPL_DEPTH_8U, 1);
858 countPrevFeatures = 0;
861 globalcountFeatures = 0;
870 countFeatures = maxFeatures;
871 countPrevFeatures = 0;
872 IplImage* eig = cvCreateImage(cvGetSize(image), 32, 1);
873 IplImage* temp = cvCreateImage(cvGetSize(image), 32, 1);
874 cvGoodFeaturesToTrack(image, eig, temp, features,
875 &countFeatures, quality, min_distance,
876 mask, block_size, use_harris, harris_free_parameter);
877 cvFindCornerSubPix(image, features, countFeatures, cvSize(win_size, win_size),
878 cvSize(-1,-1),cvTermCriteria(CV_TERMCRIT_ITER|
879 CV_TERMCRIT_EPS,20,0.03));
880 cvReleaseImage(&eig);
881 cvReleaseImage(&temp);
887 for (
int boucle=0; boucle<countFeatures;boucle++) {
888 featuresid[boucle] = globalcountFeatures;
889 globalcountFeatures++;
892 OnNewFeature(_tid, boucle, featuresid[boucle], features[boucle].x,
908 if (size > maxFeatures)
910 "Cannot initialize tracker from points"));
913 CvSize Sizeim, SizeI;
914 SizeI = cvGetSize(I);
917 Sizeim = cvGetSize(image);
918 if(SizeI.width != Sizeim.width || SizeI.height != Sizeim.height) b_imOK =
false;
920 if(image == NULL || prev_image == NULL || pyramid==NULL || prev_pyramid ==NULL || !b_imOK){
922 image = cvCreateImage(cvGetSize(I), 8, 1);image->origin = I->origin;
923 prev_image = cvCreateImage(cvGetSize(I), IPL_DEPTH_8U, 1);
924 pyramid = cvCreateImage(cvGetSize(I), IPL_DEPTH_8U, 1);
925 prev_pyramid = cvCreateImage(cvGetSize(I), IPL_DEPTH_8U, 1);
930 countFeatures = size;
931 for (
int i=0; i<countFeatures;i++) {
932 features[i] = pts[i];
936 globalcountFeatures = size;
945 if (size > maxFeatures)
947 "Cannot initialize tracker from points"));
950 CvSize Sizeim, SizeI;
951 SizeI = cvGetSize(I);
954 Sizeim = cvGetSize(image);
955 if(SizeI.width != Sizeim.width || SizeI.height != Sizeim.height) b_imOK =
false;
957 if(image == NULL || prev_image == NULL || pyramid==NULL || prev_pyramid ==NULL || !b_imOK){
959 image = cvCreateImage(cvGetSize(I), 8, 1);image->origin = I->origin;
960 prev_image = cvCreateImage(cvGetSize(I), IPL_DEPTH_8U, 1);
961 pyramid = cvCreateImage(cvGetSize(I), IPL_DEPTH_8U, 1);
962 prev_pyramid = cvCreateImage(cvGetSize(I), IPL_DEPTH_8U, 1);
967 countFeatures = size;
969 for (
int i=0; i<countFeatures;i++) {
970 features[i] = pts[i];
971 featuresid[i] = fid[i];
976 globalcountFeatures = max + 1;
987 "KLT Not initialized")) ;
992 "Image Not initialized")) ;
995 if (I->depth != IPL_DEPTH_8U || I->nChannels != 1) {
997 "Bad Image format")) ;
1002 CV_SWAP(prev_image, image, swap_temp);
1003 CV_SWAP(prev_pyramid, pyramid, swap_temp);
1005 cvCopy(I, image, 0);
1009 countPrevFeatures = countFeatures;
1010 for (
int boucle=0; boucle<countFeatures;boucle++) {
1011 prev_featuresid[boucle] = featuresid[boucle];
1014 CvPoint2D32f *swap_features = 0;
1015 CV_SWAP(prev_features, features, swap_features);
1018 if (countFeatures <= 0)
return;
1020 cvCalcOpticalFlowPyrLK( prev_image, image, prev_pyramid, pyramid,
1021 prev_features, features, countFeatures,
1022 cvSize(win_size, win_size), pyramid_level,
1023 status, 0, cvTermCriteria(CV_TERMCRIT_ITER
1024 |CV_TERMCRIT_EPS,20,0.03),
1028 flags |= CV_LKFLOW_PYR_A_READY;
1030 flags = CV_LKFLOW_PYR_A_READY;
1031 initial_guess =
false;
1035 for (i = k = 0; i < countFeatures ; i++) {
1037 lostDuringTrack[i] = 1;
1039 OnFeatureLost(_tid, i, featuresid[i], features[i].x,
1044 if (IsFeatureValid) {
1045 if (!IsFeatureValid(_tid, features[i].x, features[i].y)) {
1046 lostDuringTrack[i] = 1;
1048 OnFeatureLost(_tid, i, featuresid[i], features[i].x, features[i].y);
1052 features[k] = features[i];
1053 featuresid[k] = featuresid[i];
1055 if (OnMeasureFeature) OnMeasureFeature(_tid, k, featuresid[k], features[k].x, features[k].y);
1057 lostDuringTrack[i] = 0;
1071 vpColor color,
unsigned int thickness)
1073 if ((features == 0) || (I.
bitmap==0) || (!initialized))
1097 if (index >= countFeatures)
1103 x = features[index].x;
1104 y = features[index].y;
1105 id = featuresid[index];
1120 countPrevFeatures = countFeatures;
1121 for (
int boucle=0; boucle<countFeatures;boucle++) {
1122 prev_featuresid[boucle] = featuresid[boucle];
1125 CvPoint2D32f *swap_features = NULL;
1126 CV_SWAP(prev_features, *guess_pts, swap_features);
1128 CV_SWAP(features, prev_features, swap_features);
1130 flags |= CV_LKFLOW_INITIAL_GUESSES;
1132 initial_guess =
true;
1152 countPrevFeatures = size;
1153 countFeatures = size;
1154 for (
int boucle=0; boucle<size;boucle++) {
1155 prev_featuresid[boucle] = fid[boucle];
1156 featuresid[boucle] = fid[boucle];
1159 CvPoint2D32f *swap_features = NULL;
1160 CvPoint2D32f *swap_features2 = NULL;
1161 CV_SWAP(prev_features, *init_pts, swap_features);
1166 CV_SWAP(features, *guess_pts, swap_features2);
1168 flags |= CV_LKFLOW_INITIAL_GUESSES;
1170 initial_guess =
true;
1181 void vpKltOpencv::getPrevFeature(
int index,
int &
id,
float &x,
float &y)
const
1183 if (index >= countPrevFeatures)
1189 x = prev_features[index].x;
1190 y = prev_features[index].y;
1191 id = prev_featuresid[index];
1201 const float &x,
const float &y)
1203 if (maxFeatures == countFeatures)
1212 features[countFeatures] = f;
1213 featuresid[countFeatures] = id;
1219 if (index >= countFeatures)
1227 for (
int i=index ; i < countFeatures; i ++) {
1228 features[i] = features[i+1];
1229 featuresid[i] = featuresid[i+1];
1248 const int &nbFeatures,
vpColor color,
unsigned int thickness)
1251 for (
int i = 0 ; i < nbFeatures ; i++)
1273 const int &nbFeatures,
vpColor color,
unsigned int thickness)
1276 for (
int i = 0 ; i < nbFeatures ; i++)
1301 const long *featuresid_list,
const int &nbFeatures,
1302 vpColor color,
unsigned int thickness)
1305 for (
int i = 0 ; i < nbFeatures ; i++)
1312 sprintf(
id,
"%ld", featuresid_list[i]);
1335 const long *featuresid_list,
const int &nbFeatures,
1336 vpColor color,
unsigned int thickness)
1339 for (
int i = 0 ; i < nbFeatures ; i++)
1346 sprintf(
id,
"%ld", featuresid_list[i]);
1354 class VISP_EXPORT dummy_vpKltOpencv
1357 dummy_vpKltOpencv() {};
1360 #if !defined(VISP_BUILD_SHARED_LIBS)
1362 void dummy_vpKltOpenCV_fct() {};
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)
void set_v(const double v)
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)
static void displayCross(const vpImage< unsigned char > &I, const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)
void setWindowSize(const int winSize)
Wrapper for the KLT (Kanade-Lucas-Tomasi) feature tracker implemented in OpenCV. Thus to enable this ...
void suppressFeature(const int &index)
void setBlockSize(const int blockSize)
void getFeature(const int &index, long &id, float &x, float &y) const
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)