39 #include <visp3/vision/vpKeyPointSurf.h> 41 #if defined(VISP_HAVE_OPENCV_NONFREE) && (VISP_HAVE_OPENCV_VERSION < 0x030000) 43 #include <visp3/core/vpDebug.h> 44 #include <visp3/core/vpDisplay.h> 45 #include <visp3/core/vpImageConvert.h> 46 #include <visp3/core/vpImageTools.h> 54 double compareSURFDescriptors(
const float *d1,
const float *d2,
double best,
int length);
55 int naiveNearestNeighbor(
const float *vec,
int laplacian,
const CvSeq *model_keypoints,
const CvSeq *model_descriptors);
56 int naiveNearestNeighbor(
const float *vec,
const CvSeq *ref_keypoints,
const CvSeq *ref_descriptors);
57 void findPairs(
const CvSeq *objectKeypoints,
const CvSeq *objectDescriptors,
const CvSeq *imageKeypoints,
58 const CvSeq *imageDescriptors, std::vector<int> &ptpairs);
61 double compareSURFDescriptors(
const float *d1,
const float *d2,
double best,
int length)
63 double total_cost = 0;
65 assert(length % 4 == 0);
66 for (i = 0; i < length; i += 4) {
67 double t0 = d1[i] - d2[i];
68 double t1 = d1[i + 1] - d2[i + 1];
69 double t2 = d1[i + 2] - d2[i + 2];
70 double t3 = d1[i + 3] - d2[i + 3];
71 total_cost += t0 * t0 + t1 * t1 + t2 * t2 + t3 * t3;
72 if (total_cost > best)
80 int naiveNearestNeighbor(
const float *vec,
int laplacian,
const CvSeq *model_keypoints,
const CvSeq *model_descriptors)
82 int length = (int)(model_descriptors->elem_size / (
int)
sizeof(float));
84 double d, dist1 = 1e6, dist2 = 1e6;
85 CvSeqReader reader, kreader;
86 cvStartReadSeq(model_keypoints, &kreader, 0);
87 cvStartReadSeq(model_descriptors, &reader, 0);
89 for (i = 0; i < model_descriptors->total; i++) {
90 const CvSURFPoint *kp = (
const CvSURFPoint *)kreader.ptr;
91 const float *mvec = (
const float *)reader.ptr;
92 CV_NEXT_SEQ_ELEM(kreader.seq->elem_size, kreader);
93 CV_NEXT_SEQ_ELEM(reader.seq->elem_size, reader);
94 if (laplacian != kp->laplacian)
96 d = compareSURFDescriptors(vec, mvec, dist2, length);
101 }
else if (d < dist2)
104 if (dist1 < 0.6 * dist2)
111 int naiveNearestNeighbor(
const float *vec,
const CvSeq *ref_keypoints,
const CvSeq *ref_descriptors)
113 int length = (int)(ref_descriptors->elem_size / (
int)
sizeof(float));
114 int i, neighbor = -1;
115 double dist1 = 1e6, dist2 = 1e6;
116 CvSeqReader reader, kreader;
117 cvStartReadSeq(ref_keypoints, &kreader, 0);
118 cvStartReadSeq(ref_descriptors, &reader, 0);
120 for (i = 0; i < ref_descriptors->total; i++) {
121 const float *mvec = (
const float *)reader.ptr;
122 CV_NEXT_SEQ_ELEM(kreader.seq->elem_size, kreader);
123 CV_NEXT_SEQ_ELEM(reader.seq->elem_size, reader);
124 double d = compareSURFDescriptors(vec, mvec, dist2, length);
129 }
else if (d < dist2)
132 if (dist1 < 0.6 * dist2)
138 void findPairs(
const CvSeq *objectKeypoints,
const CvSeq *objectDescriptors,
const CvSeq *imageKeypoints,
139 const CvSeq *imageDescriptors, std::vector<int> &ptpairs)
142 CvSeqReader reader, kreader;
143 cvStartReadSeq(objectKeypoints, &kreader);
144 cvStartReadSeq(objectDescriptors, &reader);
147 for (i = 0; i < objectDescriptors->total; i++) {
148 const CvSURFPoint *kp = (
const CvSURFPoint *)kreader.ptr;
149 const float *descriptor = (
const float *)reader.ptr;
150 CV_NEXT_SEQ_ELEM(kreader.seq->elem_size, kreader);
151 CV_NEXT_SEQ_ELEM(reader.seq->elem_size, reader);
152 int nearest_neighbor = naiveNearestNeighbor(descriptor, kp->laplacian, imageKeypoints, imageDescriptors);
153 if (nearest_neighbor >= 0) {
154 ptpairs.push_back(i);
155 ptpairs.push_back(nearest_neighbor);
167 vpKeyPointSurf::vpKeyPointSurf()
168 :
vpBasicKeyPoint(), storage(NULL), params(), storage_cur(NULL), image_keypoints(NULL), image_descriptors(NULL),
169 ref_keypoints(NULL), ref_descriptors(NULL), hessianThreshold(500), descriptorType(extendedDescriptor)
177 void vpKeyPointSurf::init()
179 #if (VISP_HAVE_OPENCV_VERSION >= 0x020400) // Require opencv >= 2.4.0 180 cv::initModule_nonfree();
183 storage = cvCreateMemStorage(0);
184 params = cvSURFParams(hessianThreshold, descriptorType);
191 vpKeyPointSurf::~vpKeyPointSurf()
193 cvReleaseMemStorage(&storage);
194 if (storage_cur != NULL) {
195 cvReleaseMemStorage(&storage_cur);
210 IplImage *model = NULL;
215 CvSize size = cvSize(width, height);
216 model = cvCreateImageHeader(size, IPL_DEPTH_8U, 1);
217 model->imageData = (
char *)I.
bitmap;
222 cvExtractSURF(model, 0, &ref_keypoints, &ref_descriptors, storage, params);
224 unsigned int nbPoints = (
unsigned int)ref_keypoints->total;
228 for (
unsigned int i = 0; i < nbPoints; i++) {
229 CvSURFPoint *r1 = (CvSURFPoint *)cvGetSeqElem(ref_keypoints, (
int)i);
236 model->imageData = NULL;
237 cvReleaseImageHeader(&model);
239 cvReleaseImage(&model);
264 unsigned int height,
unsigned int width)
267 vpTRACE(
"Bad size for the subimage");
277 for (
unsigned int k = 0; k < nbRefPoint; k++) {
317 IplImage *currentImage = NULL;
322 CvSize size = cvSize(width, height);
323 currentImage = cvCreateImageHeader(size, IPL_DEPTH_8U, 1);
324 currentImage->imageData = (
char *)I.
bitmap;
331 if (storage_cur != NULL) {
332 cvReleaseMemStorage(&storage_cur);
335 storage_cur = cvCreateMemStorage(0);
337 cvExtractSURF(currentImage, 0, &image_keypoints, &image_descriptors, storage_cur, params);
339 CvSeqReader reader, kreader;
340 cvStartReadSeq(ref_keypoints, &kreader);
341 cvStartReadSeq(ref_descriptors, &reader);
343 std::list<int> indexImagePair;
344 std::list<int> indexReferencePair;
346 unsigned int nbrPair = 0;
348 for (
int i = 0; i < ref_descriptors->total; i++) {
349 const CvSURFPoint *kp = (
const CvSURFPoint *)kreader.ptr;
350 const float *descriptor = (
const float *)reader.ptr;
351 CV_NEXT_SEQ_ELEM(kreader.seq->elem_size, kreader);
352 CV_NEXT_SEQ_ELEM(reader.seq->elem_size, reader);
353 int nearest_neighbor = naiveNearestNeighbor(descriptor, kp->laplacian, image_keypoints, image_descriptors);
354 if (nearest_neighbor >= 0) {
355 indexReferencePair.push_back(i);
356 indexImagePair.push_back(nearest_neighbor);
361 std::list<int>::const_iterator indexImagePairIter = indexImagePair.begin();
362 std::list<int>::const_iterator indexReferencePairIter = indexReferencePair.begin();
372 for (
unsigned int i = 0; i < nbrPair; i++) {
373 int index = *indexImagePairIter;
375 CvSURFPoint *r1 = (CvSURFPoint *)cvGetSeqElem(image_keypoints, index);
382 ++indexImagePairIter;
383 ++indexReferencePairIter;
387 currentImage->imageData = NULL;
388 cvReleaseImageHeader(¤tImage);
390 cvReleaseImage(¤tImage);
415 unsigned int height,
unsigned int width)
418 vpTRACE(
"Bad size for the subimage");
426 unsigned int nbMatchedPoint = this->
matchPoint(subImage);
428 for (
unsigned int k = 0; k < nbMatchedPoint; k++) {
433 return (nbMatchedPoint);
523 std::list<int *> *vpKeyPointSurf::matchPoint(std::list<float *> descriptorList, std::list<int> laplacianList)
525 std::list<int *> *pairPoints =
new std::list<int *>;
527 if (descriptorList.size() != laplacianList.size()) {
528 vpTRACE(
"Error, the two lists have different number of element");
533 cvStartReadSeq(ref_descriptors, &reader);
535 std::list<float *>::const_iterator descriptorListIter = descriptorList.begin();
536 std::list<int>::const_iterator laplacianListIter = laplacianList.begin();
537 descriptorList.front();
539 while (descriptorListIter != descriptorList.end()) {
540 float *descriptor = *descriptorListIter;
542 int nearest_neighbor = naiveNearestNeighbor(descriptor, *laplacianListIter, ref_keypoints, ref_descriptors);
544 if (nearest_neighbor >= 0) {
547 tab[0] = nearest_neighbor;
549 pairPoints->push_back(tab);
552 ++descriptorListIter;
565 float *vpKeyPointSurf::getDescriptorReferencePoint(
int index)
568 vpTRACE(
"Index of the reference point out of range");
572 float *descriptor = NULL;
575 cvStartReadSeq(ref_descriptors, &reader);
577 for (
int j = 0; j < ref_descriptors->total; j++) {
579 descriptor = (
float *)reader.ptr;
582 CV_NEXT_SEQ_ELEM(reader.seq->elem_size, reader);
594 int vpKeyPointSurf::getLaplacianReferencePoint(
int index)
597 vpTRACE(
"Index of the reference point out of range");
602 cvStartReadSeq(ref_keypoints, &reader);
606 for (
int j = 0; j < ref_keypoints->total; j++) {
608 const CvSURFPoint *kp = (
const CvSURFPoint *)reader.ptr;
609 laplacian = kp->laplacian;
612 CV_NEXT_SEQ_ELEM(reader.seq->elem_size, reader);
626 void vpKeyPointSurf::getDescriptorParamReferencePoint(
int index,
int &size,
float &dir)
629 vpTRACE(
"Index of the reference point out of range");
634 cvStartReadSeq(ref_keypoints, &reader);
636 for (
int j = 0; j < ref_keypoints->total; j++) {
638 const CvSURFPoint *kp = (
const CvSURFPoint *)reader.ptr;
643 CV_NEXT_SEQ_ELEM(reader.seq->elem_size, reader);
647 #elif !defined(VISP_BUILD_SHARED_LIBS) 650 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 RGB colors available for display functionnalities.
error that can be emited by ViSP classes.
static const vpColor green
bool _reference_computed
flag to indicate if the reference has been built.
unsigned int buildReference(const vpImage< unsigned char > &I)
std::vector< vpImagePoint > referenceImagePointsList
unsigned int matchPoint(const vpImage< unsigned char > &I)
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 ...