39 #include <visp3/vision/vpKeyPointSurf.h> 41 #if defined(VISP_HAVE_OPENCV_NONFREE) && (VISP_HAVE_OPENCV_VERSION >= 0x010100) && \ 42 (VISP_HAVE_OPENCV_VERSION < 0x030000) // Require opencv >= 1.1.0 < 3.0.0 44 #include <visp3/core/vpDebug.h> 45 #include <visp3/core/vpDisplay.h> 46 #include <visp3/core/vpImageConvert.h> 47 #include <visp3/core/vpImageTools.h> 55 double compareSURFDescriptors(
const float *d1,
const float *d2,
double best,
int length);
56 int naiveNearestNeighbor(
const float *vec,
int laplacian,
const CvSeq *model_keypoints,
const CvSeq *model_descriptors);
57 int naiveNearestNeighbor(
const float *vec,
const CvSeq *ref_keypoints,
const CvSeq *ref_descriptors);
58 void findPairs(
const CvSeq *objectKeypoints,
const CvSeq *objectDescriptors,
const CvSeq *imageKeypoints,
59 const CvSeq *imageDescriptors, std::vector<int> &ptpairs);
62 double compareSURFDescriptors(
const float *d1,
const float *d2,
double best,
int length)
64 double total_cost = 0;
66 assert(length % 4 == 0);
67 for (i = 0; i < length; i += 4) {
68 double t0 = d1[i] - d2[i];
69 double t1 = d1[i + 1] - d2[i + 1];
70 double t2 = d1[i + 2] - d2[i + 2];
71 double t3 = d1[i + 3] - d2[i + 3];
72 total_cost += t0 * t0 + t1 * t1 + t2 * t2 + t3 * t3;
73 if (total_cost > best)
81 int naiveNearestNeighbor(
const float *vec,
int laplacian,
const CvSeq *model_keypoints,
const CvSeq *model_descriptors)
83 int length = (int)(model_descriptors->elem_size / (
int)
sizeof(float));
85 double d, dist1 = 1e6, dist2 = 1e6;
86 CvSeqReader reader, kreader;
87 cvStartReadSeq(model_keypoints, &kreader, 0);
88 cvStartReadSeq(model_descriptors, &reader, 0);
90 for (i = 0; i < model_descriptors->total; i++) {
91 const CvSURFPoint *kp = (
const CvSURFPoint *)kreader.ptr;
92 const float *mvec = (
const float *)reader.ptr;
93 CV_NEXT_SEQ_ELEM(kreader.seq->elem_size, kreader);
94 CV_NEXT_SEQ_ELEM(reader.seq->elem_size, reader);
95 if (laplacian != kp->laplacian)
97 d = compareSURFDescriptors(vec, mvec, dist2, length);
102 }
else if (d < dist2)
105 if (dist1 < 0.6 * dist2)
112 int naiveNearestNeighbor(
const float *vec,
const CvSeq *ref_keypoints,
const CvSeq *ref_descriptors)
114 int length = (int)(ref_descriptors->elem_size / (
int)
sizeof(float));
115 int i, neighbor = -1;
116 double dist1 = 1e6, dist2 = 1e6;
117 CvSeqReader reader, kreader;
118 cvStartReadSeq(ref_keypoints, &kreader, 0);
119 cvStartReadSeq(ref_descriptors, &reader, 0);
121 for (i = 0; i < ref_descriptors->total; i++) {
122 const float *mvec = (
const float *)reader.ptr;
123 CV_NEXT_SEQ_ELEM(kreader.seq->elem_size, kreader);
124 CV_NEXT_SEQ_ELEM(reader.seq->elem_size, reader);
125 double d = compareSURFDescriptors(vec, mvec, dist2, length);
130 }
else if (d < dist2)
133 if (dist1 < 0.6 * dist2)
139 void findPairs(
const CvSeq *objectKeypoints,
const CvSeq *objectDescriptors,
const CvSeq *imageKeypoints,
140 const CvSeq *imageDescriptors, std::vector<int> &ptpairs)
143 CvSeqReader reader, kreader;
144 cvStartReadSeq(objectKeypoints, &kreader);
145 cvStartReadSeq(objectDescriptors, &reader);
148 for (i = 0; i < objectDescriptors->total; i++) {
149 const CvSURFPoint *kp = (
const CvSURFPoint *)kreader.ptr;
150 const float *descriptor = (
const float *)reader.ptr;
151 CV_NEXT_SEQ_ELEM(kreader.seq->elem_size, kreader);
152 CV_NEXT_SEQ_ELEM(reader.seq->elem_size, reader);
153 int nearest_neighbor = naiveNearestNeighbor(descriptor, kp->laplacian, imageKeypoints, imageDescriptors);
154 if (nearest_neighbor >= 0) {
155 ptpairs.push_back(i);
156 ptpairs.push_back(nearest_neighbor);
168 vpKeyPointSurf::vpKeyPointSurf()
169 :
vpBasicKeyPoint(), storage(NULL), params(), storage_cur(NULL), image_keypoints(NULL), image_descriptors(NULL),
170 ref_keypoints(NULL), ref_descriptors(NULL), hessianThreshold(500), descriptorType(extendedDescriptor)
178 void vpKeyPointSurf::init()
180 #if (VISP_HAVE_OPENCV_VERSION >= 0x020400) // Require opencv >= 2.4.0 181 cv::initModule_nonfree();
184 storage = cvCreateMemStorage(0);
185 params = cvSURFParams(hessianThreshold, descriptorType);
192 vpKeyPointSurf::~vpKeyPointSurf()
194 cvReleaseMemStorage(&storage);
195 if (storage_cur != NULL) {
196 cvReleaseMemStorage(&storage_cur);
211 IplImage *model = NULL;
216 CvSize size = cvSize(width, height);
217 model = cvCreateImageHeader(size, IPL_DEPTH_8U, 1);
218 model->imageData = (
char *)I.
bitmap;
223 cvExtractSURF(model, 0, &ref_keypoints, &ref_descriptors, storage, params);
225 const unsigned int nbPoints = (
unsigned int)ref_keypoints->total;
227 referenceImagePointsList.resize(nbPoints);
229 for (
unsigned int i = 0; i < nbPoints; i++) {
230 CvSURFPoint *r1 = (CvSURFPoint *)cvGetSeqElem(ref_keypoints, (
int)i);
232 referenceImagePointsList[i].set_i(r1->pt.y);
233 referenceImagePointsList[i].set_j(r1->pt.x);
237 model->imageData = NULL;
238 cvReleaseImageHeader(&model);
240 cvReleaseImage(&model);
243 _reference_computed =
true;
265 const unsigned int height,
const unsigned int width)
268 vpTRACE(
"Bad size for the subimage");
276 unsigned int nbRefPoint = this->buildReference(subImage);
278 for (
unsigned int k = 0; k < nbRefPoint; k++) {
279 (referenceImagePointsList[k]).set_i((referenceImagePointsList[k]).get_i() + iP.
get_i());
280 (referenceImagePointsList[k]).set_j((referenceImagePointsList[k]).get_j() + iP.
get_j());
303 return (this->buildReference(I, iP, (
unsigned int)rectangle.
getHeight(), (
unsigned int)rectangle.
getWidth()));
318 IplImage *currentImage = NULL;
323 CvSize size = cvSize(width, height);
324 currentImage = cvCreateImageHeader(size, IPL_DEPTH_8U, 1);
325 currentImage->imageData = (
char *)I.
bitmap;
332 if (storage_cur != NULL) {
333 cvReleaseMemStorage(&storage_cur);
336 storage_cur = cvCreateMemStorage(0);
338 cvExtractSURF(currentImage, 0, &image_keypoints, &image_descriptors, storage_cur, params);
340 CvSeqReader reader, kreader;
341 cvStartReadSeq(ref_keypoints, &kreader);
342 cvStartReadSeq(ref_descriptors, &reader);
344 std::list<int> indexImagePair;
345 std::list<int> indexReferencePair;
347 unsigned int nbrPair = 0;
349 for (
int i = 0; i < ref_descriptors->total; i++) {
350 const CvSURFPoint *kp = (
const CvSURFPoint *)kreader.ptr;
351 const float *descriptor = (
const float *)reader.ptr;
352 CV_NEXT_SEQ_ELEM(kreader.seq->elem_size, kreader);
353 CV_NEXT_SEQ_ELEM(reader.seq->elem_size, reader);
354 int nearest_neighbor = naiveNearestNeighbor(descriptor, kp->laplacian, image_keypoints, image_descriptors);
355 if (nearest_neighbor >= 0) {
356 indexReferencePair.push_back(i);
357 indexImagePair.push_back(nearest_neighbor);
362 std::list<int>::const_iterator indexImagePairIter = indexImagePair.begin();
363 std::list<int>::const_iterator indexReferencePairIter = indexReferencePair.begin();
365 matchedReferencePoints.resize(0);
370 currentImagePointsList.resize(nbrPair);
371 matchedReferencePoints.resize(nbrPair);
373 for (
unsigned int i = 0; i < nbrPair; i++) {
374 int index = *indexImagePairIter;
376 CvSURFPoint *r1 = (CvSURFPoint *)cvGetSeqElem(image_keypoints, index);
378 currentImagePointsList[i].set_i(r1->pt.y);
379 currentImagePointsList[i].set_j(r1->pt.x);
381 matchedReferencePoints[i] = (
unsigned int)*indexReferencePairIter;
383 ++indexImagePairIter;
384 ++indexReferencePairIter;
388 currentImage->imageData = NULL;
389 cvReleaseImageHeader(¤tImage);
391 cvReleaseImage(¤tImage);
416 const unsigned int height,
const unsigned int width)
419 vpTRACE(
"Bad size for the subimage");
427 unsigned int nbMatchedPoint = this->matchPoint(subImage);
429 for (
unsigned int k = 0; k < nbMatchedPoint; k++) {
430 (currentImagePointsList[k]).set_i((currentImagePointsList[k]).get_i() + iP.
get_i());
431 (currentImagePointsList[k]).set_j((currentImagePointsList[k]).get_j() + iP.
get_j());
434 return (nbMatchedPoint);
456 return (this->matchPoint(I, iP, (
unsigned int)rectangle.
getHeight(), (
unsigned int)rectangle.
getWidth()));
492 for (
unsigned int i = 0; i < matchedReferencePoints.size(); i++) {
519 for (
unsigned int i = 0; i < matchedReferencePoints.size(); i++) {
524 std::list<int *> *vpKeyPointSurf::matchPoint(std::list<float *> descriptorList, std::list<int> laplacianList)
526 std::list<int *> *pairPoints =
new std::list<int *>;
528 if (descriptorList.size() != laplacianList.size()) {
529 vpTRACE(
"Error, the two lists have different number of element");
534 cvStartReadSeq(ref_descriptors, &reader);
536 std::list<float *>::const_iterator descriptorListIter = descriptorList.begin();
537 std::list<int>::const_iterator laplacianListIter = laplacianList.begin();
538 descriptorList.front();
540 while (descriptorListIter != descriptorList.end()) {
541 float *descriptor = *descriptorListIter;
543 int nearest_neighbor = naiveNearestNeighbor(descriptor, *laplacianListIter, ref_keypoints, ref_descriptors);
545 if (nearest_neighbor >= 0) {
548 tab[0] = nearest_neighbor;
550 pairPoints->push_back(tab);
553 ++descriptorListIter;
566 float *vpKeyPointSurf::getDescriptorReferencePoint(
const int index)
568 if (index >= static_cast<int>(referenceImagePointsList.size()) || index < 0) {
569 vpTRACE(
"Index of the reference point out of range");
573 float *descriptor = NULL;
576 cvStartReadSeq(ref_descriptors, &reader);
578 for (
int j = 0; j < ref_descriptors->total; j++) {
580 descriptor = (
float *)reader.ptr;
583 CV_NEXT_SEQ_ELEM(reader.seq->elem_size, reader);
595 int vpKeyPointSurf::getLaplacianReferencePoint(
const int index)
597 if (index >= static_cast<int>(referenceImagePointsList.size()) || index < 0) {
598 vpTRACE(
"Index of the reference point out of range");
603 cvStartReadSeq(ref_keypoints, &reader);
607 for (
int j = 0; j < ref_keypoints->total; j++) {
609 const CvSURFPoint *kp = (
const CvSURFPoint *)reader.ptr;
610 laplacian = kp->laplacian;
613 CV_NEXT_SEQ_ELEM(reader.seq->elem_size, reader);
627 void vpKeyPointSurf::getDescriptorParamReferencePoint(
const int index,
int &size,
float &dir)
629 if (index >= static_cast<int>(referenceImagePointsList.size()) || index < 0) {
630 vpTRACE(
"Index of the reference point out of range");
635 cvStartReadSeq(ref_keypoints, &reader);
637 for (
int j = 0; j < ref_keypoints->total; j++) {
639 const CvSURFPoint *kp = (
const CvSURFPoint *)reader.ptr;
644 CV_NEXT_SEQ_ELEM(reader.seq->elem_size, reader);
648 #elif !defined(VISP_BUILD_SHARED_LIBS) 651 void dummy_vpKeyPointSurf(){};
class that defines what is a Keypoint. This class provides all the basic elements to implement classe...
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.
error that can be emited by ViSP classes.
static const vpColor green
void set_i(const double ii)
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)
unsigned int getHeight() const
Defines a rectangle in the plane.
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...