39 #include <visp3/vision/vpKeyPointSurf.h>
41 #if defined(VISP_HAVE_OPENCV_NONFREE) && (VISP_HAVE_OPENCV_VERSION >= 0x010100) && (VISP_HAVE_OPENCV_VERSION < 0x030000) // Require opencv >= 1.1.0 < 3.0.0
43 #include <visp3/core/vpImageConvert.h>
44 #include <visp3/core/vpImageTools.h>
45 #include <visp3/core/vpDisplay.h>
46 #include <visp3/core/vpDebug.h>
54 double compareSURFDescriptors(
const float* d1,
const float* d2,
double best,
int length );
55 int naiveNearestNeighbor(
const float *vec,
int laplacian,
56 const CvSeq *model_keypoints,
57 const CvSeq *model_descriptors );
58 int naiveNearestNeighbor(
const float *vec,
59 const CvSeq *ref_keypoints,
60 const CvSeq *ref_descriptors );
61 void findPairs(
const CvSeq* objectKeypoints,
62 const CvSeq* objectDescriptors,
63 const CvSeq* imageKeypoints,
64 const CvSeq* imageDescriptors,
65 std::vector<int>& ptpairs );
68 double compareSURFDescriptors(
const float* d1,
const float* d2,
double best,
int length )
70 double total_cost = 0;
72 assert( length % 4 == 0 );
73 for( i = 0; i < length; i += 4 )
75 double t0 = d1[i] - d2[i];
76 double t1 = d1[i+1] - d2[i+1];
77 double t2 = d1[i+2] - d2[i+2];
78 double t3 = d1[i+3] - d2[i+3];
79 total_cost += t0*t0 + t1*t1 + t2*t2 + t3*t3;
80 if( total_cost > best )
88 int naiveNearestNeighbor(
const float *vec,
int laplacian,
89 const CvSeq *model_keypoints,
90 const CvSeq *model_descriptors )
92 int length = (int)(model_descriptors->elem_size/(
int)
sizeof(float));
94 double d, dist1 = 1e6, dist2 = 1e6;
95 CvSeqReader reader, kreader;
96 cvStartReadSeq( model_keypoints, &kreader, 0 );
97 cvStartReadSeq( model_descriptors, &reader, 0 );
99 for( i = 0; i < model_descriptors->total; i++ )
101 const CvSURFPoint* kp = (
const CvSURFPoint*)kreader.ptr;
102 const float* mvec = (
const float*)reader.ptr;
103 CV_NEXT_SEQ_ELEM( kreader.seq->elem_size, kreader );
104 CV_NEXT_SEQ_ELEM( reader.seq->elem_size, reader );
105 if( laplacian != kp->laplacian )
107 d = compareSURFDescriptors( vec, mvec, dist2, length );
114 else if ( d < dist2 )
117 if ( dist1 < 0.6*dist2 )
124 int naiveNearestNeighbor(
const float *vec,
125 const CvSeq *ref_keypoints,
126 const CvSeq *ref_descriptors )
128 int length = (int)(ref_descriptors->elem_size/(
int)
sizeof(float));
129 int i, neighbor = -1;
130 double d, dist1 = 1e6, dist2 = 1e6;
131 CvSeqReader reader, kreader;
132 cvStartReadSeq( ref_keypoints, &kreader, 0 );
133 cvStartReadSeq( ref_descriptors, &reader, 0 );
135 for( i = 0; i < ref_descriptors->total; i++ )
137 const float* mvec = (
const float*)reader.ptr;
138 CV_NEXT_SEQ_ELEM( kreader.seq->elem_size, kreader );
139 CV_NEXT_SEQ_ELEM( reader.seq->elem_size, reader );
140 d = compareSURFDescriptors( vec, mvec, dist2, length );
147 else if ( d < dist2 )
150 if ( dist1 < 0.6*dist2 )
158 void findPairs(
const CvSeq* objectKeypoints,
159 const CvSeq* objectDescriptors,
160 const CvSeq* imageKeypoints,
161 const CvSeq* imageDescriptors,
162 std::vector<int>& ptpairs )
165 CvSeqReader reader, kreader;
166 cvStartReadSeq( objectKeypoints, &kreader );
167 cvStartReadSeq( objectDescriptors, &reader );
170 for( i = 0; i < objectDescriptors->total; i++ )
172 const CvSURFPoint* kp = (
const CvSURFPoint*)kreader.ptr;
173 const float* descriptor = (
const float*)reader.ptr;
174 CV_NEXT_SEQ_ELEM( kreader.seq->elem_size, kreader );
175 CV_NEXT_SEQ_ELEM( reader.seq->elem_size, reader );
176 int nearest_neighbor = naiveNearestNeighbor( descriptor,
180 if( nearest_neighbor >= 0 )
182 ptpairs.push_back(i);
183 ptpairs.push_back(nearest_neighbor);
199 storage(NULL), params(), storage_cur(NULL), image_keypoints(NULL), image_descriptors(NULL),
200 ref_keypoints(NULL), ref_descriptors(NULL), hessianThreshold(500), descriptorType(extendedDescriptor)
208 void vpKeyPointSurf::init()
210 #if (VISP_HAVE_OPENCV_VERSION >= 0x020400) // Require opencv >= 2.4.0
211 cv::initModule_nonfree();
214 storage = cvCreateMemStorage(0);
215 params = cvSURFParams(hessianThreshold, descriptorType);
224 cvReleaseMemStorage(&storage);
225 if(storage_cur!=NULL){
226 cvReleaseMemStorage(&storage_cur);
241 IplImage* model = NULL;
246 CvSize size = cvSize(width, height);
247 model = cvCreateImageHeader(size, IPL_DEPTH_8U, 1);
248 model->imageData = (
char*)I.
bitmap;
253 cvExtractSURF( model, 0, &ref_keypoints, &ref_descriptors, storage, params );
255 const unsigned int nbPoints = (
unsigned int)ref_keypoints->total;
259 for(
unsigned int i = 0; i < nbPoints; i++ )
261 CvSURFPoint* r1 = (CvSURFPoint*)cvGetSeqElem(ref_keypoints, (
int)i);
268 model->imageData = NULL;
269 cvReleaseImageHeader(&model);
271 cvReleaseImage(&model);
298 const unsigned int height,
const unsigned int width)
303 vpTRACE(
"Bad size for the subimage");
305 "Bad size for the subimage"));
311 (
unsigned int)iP.
get_i(),
312 (
unsigned int)iP.
get_j(),
313 height, width, subImage);
317 for(
unsigned int k = 0; k < nbRefPoint; k++)
349 (
unsigned int)rectangle.
getWidth()));
365 IplImage* currentImage = NULL;
370 CvSize size = cvSize(width, height);
371 currentImage = cvCreateImageHeader(size, IPL_DEPTH_8U, 1);
372 currentImage->imageData = (
char*)I.
bitmap;
379 if(storage_cur != NULL){
380 cvReleaseMemStorage(&storage_cur);
383 storage_cur = cvCreateMemStorage(0);
385 cvExtractSURF( currentImage, 0, &image_keypoints, &image_descriptors,
386 storage_cur, params );
388 CvSeqReader reader, kreader;
389 cvStartReadSeq( ref_keypoints, &kreader );
390 cvStartReadSeq( ref_descriptors, &reader );
393 std::list<int> indexImagePair;
394 std::list<int> indexReferencePair;
397 unsigned int nbrPair = 0;
399 for(
int i = 0; i < ref_descriptors->total; i++ )
401 const CvSURFPoint* kp = (
const CvSURFPoint*)kreader.ptr;
402 const float* descriptor = (
const float*)reader.ptr;
403 CV_NEXT_SEQ_ELEM( kreader.seq->elem_size, kreader );
404 CV_NEXT_SEQ_ELEM( reader.seq->elem_size, reader );
405 int nearest_neighbor = naiveNearestNeighbor( descriptor,
409 if( nearest_neighbor >= 0 )
411 indexReferencePair.push_back(i);
412 indexImagePair.push_back(nearest_neighbor);
417 std::list<int>::const_iterator indexImagePairIter = indexImagePair.begin();
418 std::list<int>::const_iterator indexReferencePairIter = indexReferencePair.begin();
428 for (
unsigned int i = 0; i < nbrPair; i++)
430 int index = *indexImagePairIter;
432 CvSURFPoint* r1 = (CvSURFPoint*)cvGetSeqElem(image_keypoints, index);
440 ++indexImagePairIter;
441 ++indexReferencePairIter;
445 currentImage->imageData = NULL;
446 cvReleaseImageHeader(¤tImage);
448 cvReleaseImage(¤tImage);
475 const unsigned int height,
const unsigned int width)
480 vpTRACE(
"Bad size for the subimage");
482 "Bad size for the subimage"));
488 (
unsigned int)iP.
get_i(),
489 (
unsigned int)iP.
get_j(),
490 height, width, subImage);
492 unsigned int nbMatchedPoint = this->
matchPoint(subImage);
494 for(
unsigned int k = 0; k < nbMatchedPoint; k++)
502 return(nbMatchedPoint);
528 (
unsigned int)rectangle.
getWidth()));
599 std::list<int*>* pairPoints =
new std::list<int*>;
601 if(descriptorList.size() != laplacianList.size()){
602 vpTRACE(
"Error, the two lists have different number of element");
607 cvStartReadSeq( ref_descriptors, &reader );
609 std::list<float*>::const_iterator descriptorListIter = descriptorList.begin();
610 std::list<int>::const_iterator laplacianListIter = laplacianList.begin();
611 descriptorList.front();
613 while(descriptorListIter != descriptorList.end()){
614 float* descriptor = *descriptorListIter;
616 int nearest_neighbor = naiveNearestNeighbor( descriptor, *laplacianListIter, ref_keypoints, ref_descriptors);
618 if(nearest_neighbor >= 0){
621 tab[0] = nearest_neighbor;
623 pairPoints->push_back(tab);
626 ++descriptorListIter;
641 vpTRACE(
"Index of the reference point out of range");
645 float* descriptor = NULL;
648 cvStartReadSeq( ref_descriptors, &reader );
650 for(
int j = 0; j < ref_descriptors->total; j++ ){
652 descriptor = (
float*)reader.ptr;
655 CV_NEXT_SEQ_ELEM( reader.seq->elem_size, reader );
669 vpTRACE(
"Index of the reference point out of range");
674 cvStartReadSeq( ref_keypoints, &reader );
678 for(
int j = 0; j < ref_keypoints->total; j++ ){
680 const CvSURFPoint* kp = (
const CvSURFPoint*)reader.ptr;
681 laplacian = kp->laplacian;
684 CV_NEXT_SEQ_ELEM( reader.seq->elem_size, reader );
700 vpTRACE(
"Index of the reference point out of range");
705 cvStartReadSeq( ref_keypoints, &reader );
707 for(
int j = 0; j < ref_keypoints->total; j++ ){
709 const CvSURFPoint* kp = (
const CvSURFPoint*)reader.ptr;
714 CV_NEXT_SEQ_ELEM( reader.seq->elem_size, reader );
718 #elif !defined(VISP_BUILD_SHARED_LIBS)
720 void dummy_vpKeyPointSurf() {};
class that defines what is a Keypoint. This class provides all the basic elements to implement classe...
void getDescriptorParamReferencePoint(const int index, int &size, float &dir)
unsigned int getWidth() const
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
Type * bitmap
points toward the bitmap
Class to define colors available for display functionnalities.
int getLaplacianReferencePoint(const int index)
error that can be emited by ViSP classes.
unsigned int matchPoint(const vpImage< unsigned char > &I)
void display(const vpImage< unsigned char > &Iref, const vpImage< unsigned char > &Icurrent, unsigned int size=3)
static const vpColor green
void set_i(const double ii)
float * getDescriptorReferencePoint(const int index)
bool _reference_computed
flag to indicate if the reference has been built.
std::vector< vpImagePoint > referenceImagePointsList
unsigned int buildReference(const vpImage< unsigned char > &I)
void set_j(const double jj)
static void displayCross(const vpImage< unsigned char > &I, const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)
std::vector< unsigned int > matchedReferencePoints
unsigned int getHeight() const
Defines a rectangle in the plane.
std::vector< vpImagePoint > currentImagePointsList
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
virtual ~vpKeyPointSurf()