15 #if MRPT_HAS_OPENCV && MRPT_HAS_SIFT_HESS 22 #include <mrpt/otherlibs/do_opencv_includes.h> 23 #ifdef HAVE_OPENCV_NONFREE // MRPT_HAS_OPENCV_NONFREE 24 #include <opencv2/nonfree/nonfree.hpp> 26 #ifdef HAVE_OPENCV_FEATURES2D 27 #include <opencv2/features2d/features2d.hpp> 29 #ifdef HAVE_OPENCV_XFEATURES2D 30 #include <opencv2/xfeatures2d.hpp> 34 #ifdef MRPT_OS_WINDOWS 46 #if MRPT_OPENCV_VERSION_NUM >= 0x211 53 #if MRPT_HAS_OPENCV && MRPT_HAS_SIFT_HESS 56 IplImage* create_init_img(
const IplImage*,
int,
double);
57 IplImage*** build_gauss_pyr(IplImage*,
int,
int,
double);
58 IplImage*** build_dog_pyr(IplImage***,
int,
int);
59 CvSeq* scale_space_extrema(IplImage***,
int,
int,
double,
int, CvMemStorage*);
60 int is_extremum(IplImage***,
int,
int,
int,
int);
61 struct feature* new_feature(
void);
62 void calc_feature_scales(CvSeq*,
double,
int);
63 void adjust_for_img_dbl(CvSeq*);
64 void calc_feature_oris(CvSeq*, IplImage***);
65 void compute_descriptors(CvSeq*, IplImage***,
int,
int);
66 int feature_cmp(
void*,
void*,
void*);
67 void release_pyr(IplImage****,
int,
int);
69 #endif // MRPT_HAS_OPENCV 76 unsigned int nDesiredFeatures,
const TImageROI& ROI)
const 78 bool usingROI =
false;
98 img_grayscale.
swap(auximg);
101 switch (options.SIFTOptions.implementation)
109 #ifdef MRPT_OS_WINDOWS 111 char filImg[2000], filOut[2000], filFeat[2000];
114 GetTempPathA(1000, filOut);
116 GetTempPathA(1000, filImg);
121 bool onlyDesc = feats.
size() > 0 ? true :
false;
125 GetTempPathA(1000, filFeat);
127 filFeat, 1000,
"temp_feats.txt");
129 for (
size_t i = 0; i < feats.
size(); i++)
131 listPoints(i, 0) = feats[i]->x;
132 listPoints(i, 1) = feats[i]->y;
145 os::strcpy(paramImg, 1000,
"extractSIFT.exe -i");
159 "[extractFeaturesSIFT] Could not launch external " 160 "process... (extractSIFT.exe)")
167 aux.loadFromTextFile(filOut);
168 std::cout <<
"[computeSiftFeatures] " << aux.getRowCount()
169 <<
" features." << std::endl;
172 nFeats = feats.
size();
175 nFeats = aux.getRowCount();
179 for (
size_t i = 0; itFeat != feats.
end(); i++, itFeat++)
182 (*itFeat)->x = usingROI ? aux(i, 0) + ROI.
xMin : aux(i, 0);
183 (*itFeat)->y = usingROI ? aux(i, 1) + ROI.
yMin : aux(i, 1);
184 (*itFeat)->orientation = aux(i, 2);
185 (*itFeat)->scale = aux(i, 3);
186 (*itFeat)->ID = init_ID + i;
189 aux.extractRow(i, (*itFeat)->descriptors.SIFT, 4);
195 "Unfortunately, this SIFT Implementation only runs in Windows " 196 "OS, try Hess implementation");
205 #ifdef MRPT_OS_WINDOWS 207 "Usage of Vedaldi Binary not implemented yet, please, try " 211 "Unfortunately, this SIFT Implementation only runs in Windows " 212 "OS, try Hess implementation");
221 #ifdef MRPT_OS_WINDOWS 222 char filImg[2000], filOut[2000];
227 GetTempPathA(1000, filOut);
229 GetTempPathA(1000, filImg);
234 bool valid = img_grayscale.
saveToFile(filImg);
237 "An error occurred when saving input image into a .pgm " 244 format(
"cmd /C gmic.exe %s -o %s -quiet", filImg, filImg)
251 "[extractFeaturesSIFT] Could not launch external " 252 "process... (gmic.exe)");
257 os::strcpy(paramImg, 1000,
"cmd /C siftWin32.exe <");
266 "[extractFeaturesSIFT] Could not launch external " 267 "process... (siftWin32.exe)");
272 unsigned int dLen, nFeats;
276 "Error in extract SIFT with Lowe binary, output file not " 282 for (
size_t i = 0; i < nFeats; i++)
287 feat->ID = init_ID + i;
292 float fx, fy, fo, fs;
293 fscanf(f,
"%f %f %f %f", &fy, &fx, &fo, &fs);
295 feat->x = usingROI ? fx + ROI.
xMin : fx;
296 feat->y = usingROI ? fy + ROI.
yMin : fy;
297 feat->orientation = fo;
301 feat->descriptors.SIFT.resize(dLen);
303 for (
unsigned int k = 0; k < dLen; k++)
306 feat->descriptors.SIFT[k] = (
unsigned char)
c;
316 "Unfortunately, this SIFT Implementation only runs in Windows " 317 "OS, try Hess implementation");
326 #if !MRPT_HAS_SIFT_HESS 328 "Method not available since MRPT has been compiled without " 329 "Hess' SIFT library")
330 #elif MRPT_HAS_OPENCV // OK, we have Hess' sift: 332 IplImage ***gauss_pyr, ***dog_pyr;
333 CvMemStorage* storage;
342 const IplImage* ipl_im = img_grayscale.
getAs<IplImage>();
344 octvs = log((
float)(
MIN(init_img->width, init_img->height))) /
349 dog_pyr = build_dog_pyr(gauss_pyr, octvs,
SIFT_INTVLS);
350 storage = cvCreateMemStorage(0);
351 features = scale_space_extrema(
353 options.SIFTOptions.threshold,
354 options.SIFTOptions.edgeThreshold,
358 calc_feature_oris(features, gauss_pyr);
363 cvSeqSort(features, (CvCmpFunc)feature_cmp,
nullptr);
366 if (nDesiredFeatures > 0)
368 if (nDesiredFeatures < (
unsigned int)features->total)
370 features,
nullptr, features->total - nDesiredFeatures);
372 cout <<
"[Warning] Detected less features than the " 374 << features->total <<
" vs " << nDesiredFeatures
379 convertCvSeqInCFeatureList(features, feats, init_ID, ROI);
382 cvClearSeq(features);
383 cvReleaseMemStorage(&storage);
384 cvReleaseImage(&init_img);
389 "Method not available since MRPT has been compiled without " 391 #endif // MRPT_HAS_OPENCV 399 #if defined(HAVE_OPENCV_NONFREE) || \ 400 defined(HAVE_OPENCV_XFEATURES2D) // MRPT_HAS_OPENCV_NONFREE 402 #if MRPT_OPENCV_VERSION_NUM >= 0x211 && MRPT_OPENCV_VERSION_NUM < 0x300 404 SiftFeatureDetector SIFTDetector(
412 SiftDescriptorExtractor SIFTDescriptor;
414 vector<KeyPoint> cv_feats;
416 const IplImage* cGrey = img_grayscale.
getAs<IplImage>();
418 Mat theImg = cvarrToMat(cGrey);
419 SIFTDetector.detect(theImg, cv_feats);
422 SIFTDescriptor.compute(theImg, cv_feats, desc);
426 const size_t N = cv_feats.size();
427 unsigned int nMax = nDesiredFeatures != 0 && N > nDesiredFeatures
430 const int offset = (int)this->options.patchSize / 2 + 1;
431 const size_t size_2 = options.patchSize / 2;
432 const size_t imgH =
img.getHeight();
433 const size_t imgW =
img.getWidth();
435 unsigned int cont = 0;
438 while (cont != nMax && i != N)
440 const int xBorderInf = (int)floor(cv_feats[i].pt.x - size_2);
441 const int xBorderSup = (int)floor(cv_feats[i].pt.x + size_2);
442 const int yBorderInf = (int)floor(cv_feats[i].pt.y - size_2);
443 const int yBorderSup = (int)floor(cv_feats[i].pt.y + size_2);
445 if (options.patchSize == 0 ||
446 ((xBorderSup < (
int)imgW) && (xBorderInf > 0) &&
447 (yBorderSup < (int)imgH) && (yBorderInf > 0)))
452 ft->x = cv_feats[i].pt.x;
453 ft->y = cv_feats[i].pt.y;
454 ft->response = cv_feats[i].response;
455 ft->orientation = cv_feats[i].angle;
456 ft->scale = cv_feats[i].size;
459 ft->descriptors.SIFT.resize(128);
461 &(ft->descriptors.SIFT[0]), &desc.data[128 * i],
463 sizeof(ft->descriptors.SIFT[0]));
465 if (options.patchSize > 0)
482 vector<KeyPoint> cv_feats;
484 cv::Ptr<cv::xfeatures2d::SIFT> sift = cv::xfeatures2d::SIFT::create(
485 nDesiredFeatures, 3, options.SIFTOptions.threshold,
486 options.SIFTOptions.edgeThreshold, 1.6);
487 const IplImage* cGrey = img_grayscale.
getAs<IplImage>();
488 Mat theImg = cvarrToMat(cGrey);
490 sift->detect(theImg, cv_feats);
493 sift->compute(theImg, cv_feats, desc);
497 const size_t N = cv_feats.size();
498 unsigned int nMax = nDesiredFeatures != 0 && N > nDesiredFeatures
501 const int offset = (int)this->options.patchSize / 2 + 1;
502 const size_t size_2 = options.patchSize / 2;
503 const size_t imgH =
img.getHeight();
504 const size_t imgW =
img.getWidth();
506 unsigned int cont = 0;
510 while (cont != nMax && i != N)
512 const int xBorderInf = (int)floor(cv_feats[i].pt.x - size_2);
513 const int xBorderSup = (int)floor(cv_feats[i].pt.x + size_2);
514 const int yBorderInf = (int)floor(cv_feats[i].pt.y - size_2);
515 const int yBorderSup = (int)floor(cv_feats[i].pt.y + size_2);
517 if (options.patchSize == 0 ||
518 ((xBorderSup < (
int)imgW) && (xBorderInf > 0) &&
519 (yBorderSup < (int)imgH) && (yBorderInf > 0)))
524 ft->x = cv_feats[i].pt.x;
525 ft->y = cv_feats[i].pt.y;
526 ft->response = cv_feats[i].response;
527 ft->orientation = cv_feats[i].angle;
528 ft->scale = cv_feats[i].size;
531 ft->descriptors.SIFT.resize(128);
533 &(ft->descriptors.SIFT[0]), &desc.data[128 * i],
535 sizeof(ft->descriptors.SIFT[0]));
537 if (options.patchSize > 0)
554 "This method requires OpenCV >= 2.1.1 with nonfree module")
574 switch (options.SIFTOptions.implementation)
578 #ifdef MRPT_OS_WINDOWS 579 char filImg[2000], filOut[2000], filFeat[2000];
585 GetTempPathA(1000, filImg);
587 GetTempPathA(1000, filOut);
589 GetTempPathA(1000, filFeat);
590 os::strcat(filFeat, 1000,
"temp_KLT_feats.txt");
594 for (feat = in_features.
begin(); feat != in_features.
end(); feat++)
595 os::fprintf(fout,
"%.6f %.6f\n", (*feat)->x, (*feat)->y);
606 os::strcpy(paramImg, 1000,
"extractSIFT.exe -i");
617 "[extractFeaturesSIFT] Could not launch external " 618 "process... (extractSIFT.exe)");
623 aux.loadFromTextFile(filOut);
624 size_t nRows = aux.getRowCount();
626 std::cout <<
"[computeSiftFeatures1] " << nRows <<
" features.\n";
632 feat = in_features.
begin();
634 for (i = 0; i < nRows; i++)
636 if (aux(i, 0) != lx ||
640 (*feat)->orientation = aux(i, 2);
641 (*feat)->scale = aux(i, 3);
644 aux.extractRow(i, (*feat)->descriptors.SIFT, 4);
661 #if !MRPT_HAS_SIFT_HESS 663 "Method not available since MRPT has been compiled without " 664 "Hess' SIFT library")
665 #elif MRPT_HAS_OPENCV // OK, we have Hess' sift: 667 IplImage ***gauss_pyr, ***dog_pyr;
668 CvMemStorage* storage;
678 const IplImage* ipl_im = img_grayscale.getAs<IplImage>();
681 octvs = log((
float)(
MIN(init_img->width, init_img->height))) /
686 dog_pyr = build_dog_pyr(gauss_pyr, octvs,
SIFT_INTVLS);
688 storage = cvCreateMemStorage(0);
689 features =
static_cast<CvSeq*
>(
690 my_scale_space_extrema(
692 options.SIFTOptions.threshold,
693 options.SIFTOptions.edgeThreshold,
697 calc_feature_oris(features, gauss_pyr);
702 insertCvSeqInCFeatureList(features, in_features);
705 cvClearSeq(features);
708 cvReleaseMemStorage(&storage);
709 cvReleaseImage(&init_img);
747 "Method not available since MRPT has been compiled without " 749 #endif // MRPT_HAS_OPENCV 754 cout <<
"SIFT Extraction method not supported for features with " 755 "already known image coordinates" 767 void* features_,
CFeatureList& list,
unsigned int init_ID,
770 #if MRPT_HAS_OPENCV && MRPT_HAS_SIFT_HESS 771 CvSeq* features =
reinterpret_cast<CvSeq*
>(features_);
774 bool usingROI =
false;
778 int n = features->total;
783 for (
int k = 0; k <
n; k++)
785 thisFeat = (
feature*)cvGetSeqElem(features, k);
788 feat->
x = usingROI ? thisFeat->
x + ROI.
xMin : thisFeat->
x;
789 feat->y = usingROI ? thisFeat->
y + ROI.
yMin : thisFeat->
y;
791 feat->orientation = thisFeat->
ori;
792 feat->scale = thisFeat->
scl;
793 feat->descriptors.SIFT.resize(thisFeat->
d);
794 for (
int i = 0; i < thisFeat->
d; i++)
795 feat->descriptors.SIFT[i] = (
unsigned char)thisFeat->
descr[i];
801 "Method not available since MRPT has been compiled without OpenCV")
802 #endif // MRPT_HAS_OPENCV 808 void* features_,
CFeatureList& list,
unsigned int init_ID)
const 810 #if MRPT_HAS_OPENCV && MRPT_HAS_SIFT_HESS 811 CvSeq* features =
reinterpret_cast<CvSeq*
>(features_);
813 int n = features->total;
819 for (itFeat = list.
begin(), k = 0; itFeat != list.
end() && k <
n; k++)
821 thisFeat = (
feature*)cvGetSeqElem(features, k);
822 if ((*itFeat)->x == thisFeat->
x && (*itFeat)->y == thisFeat->
y)
825 (*itFeat)->orientation = thisFeat->
ori;
826 (*itFeat)->scale = thisFeat->
scl;
827 (*itFeat)->descriptors.SIFT.resize(thisFeat->
d);
828 for (
int i = 0; i < thisFeat->
d; i++)
829 (*itFeat)->descriptors.SIFT[i] =
830 (
unsigned char)thisFeat->
descr[i];
837 "Method not available since MRPT has been compiled without OpenCV")
838 #endif // MRPT_HAS_OPENCV 849 #if MRPT_HAS_OPENCV && MRPT_HAS_SIFT_HESS 850 CvSeq* features =
reinterpret_cast<CvSeq*
>(features_);
855 for (i = 0; i <
n; i++)
857 feat = CV_GET_SEQ_ELEM(
struct feature, features, i);
862 "Method not available since MRPT has been compiled without OpenCV")
863 #endif // MRPT_HAS_OPENCV 870 CFeatureList& featList,
void* dog_pyr_,
int octvs,
int intvls,
871 double contr_thr,
int curv_thr,
void* storage_)
const 875 #if MRPT_HAS_OPENCV && MRPT_HAS_SIFT_HESS 876 CvMemStorage* storage =
reinterpret_cast<CvMemStorage*
>(storage_);
877 IplImage*** dog_pyr =
reinterpret_cast<IplImage***
>(dog_pyr_);
887 features = cvCreateSeq(0,
sizeof(CvSeq),
sizeof(
struct feature), storage);
888 for (itFeats = featList.
begin(); itFeats != featList.
end(); itFeats++)
893 float gr = 0.0, gc = 0.0;
895 if ((*itFeats)->y < 0 || (*itFeats)->x < 0)
900 for (o = 0; o < octvs; o++)
902 float r = (*itFeats)->y / pow(2.0, o);
903 float c = (*itFeats)->x / pow(2.0, o);
905 for (i = 1; i <= intvls; i++)
908 double val =
s * getLaplacianValue(dog_pyr, o, i,
r,
c);
932 feat = new_feature();
936 feat->
img_pt.y = feat->
y = (*itFeats)->y;
943 cvSeqPush(features, feat);
949 "Method not available since MRPT has been compiled without OpenCV")
950 #endif // MRPT_HAS_OPENCV 957 void* dog_pyr_,
int octv,
int intvl,
float row,
float col)
const 959 #if MRPT_HAS_OPENCV && MRPT_HAS_SIFT_HESS 960 IplImage*** dog_pyr =
reinterpret_cast<IplImage***
>(dog_pyr_);
964 for (j = -1; j <= 1; j++)
965 for (k = -1; k <= 1; k++)
971 if (k == 0 && j == 0)
982 "Method not available since MRPT has been compiled without OpenCV")
983 #endif // MRPT_HAS_OPENCV 992 void* dog_pyr_,
int octv,
int intvl,
float row,
float col,
993 unsigned int& nMin,
unsigned int& nMax)
const 995 #if MRPT_HAS_OPENCV && MRPT_HAS_SIFT_HESS 996 IplImage*** dog_pyr =
reinterpret_cast<IplImage***
>(dog_pyr_);
1005 for (i = -1; i <= 1; i++)
1006 for (j = -1; j <= 1; j++)
1007 for (k = -1; k <= 1; k++)
1022 "Method not available since MRPT has been compiled without OpenCV")
1023 #endif // MRPT_HAS_OPENCV std::shared_ptr< CFeature > Ptr
double scl
scale of a Lowe-style feature
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
This namespace provides a OS-independent interface to many useful functions: filenames manipulation...
int void fclose(FILE *f)
An OS-independent version of fclose.
A class for storing images as grayscale or RGB bitmaps.
static __inline float pixval32f(IplImage *img, int r, int c)
A function to get a pixel value from a 32-bit floating-point image.
#define THROW_EXCEPTION(msg)
#define SIFT_DESCR_HIST_BINS
default number of bins per histogram in descriptor array
CvPoint2D64f img_pt
location in image
double ori
orientation of a Lowe-style feature
const T * getAs() const
Returns a pointer to a const T* containing the image - the idea is to call like "img.getAs<IplImage>()" so we can avoid here including OpenCV's headers.
float yMin
Y coordinate limits [0,imageHeight)
A structure for defining a ROI within an image.
This base provides a set of functions for maths stuff.
size_t getWidth() const override
Returns the width of the image in pixels.
#define MRPT_UNUSED_PARAM(a)
Can be used to avoid "not used parameters" warnings from the compiler.
Scale Invariant Feature Transform [LOWE'04].
size_t getHeight() const override
Returns the height of the image in pixels.
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
Classes for computer vision, detectors, features, etc.
#define SIFT_DESCR_WIDTH
default width of descriptor histogram array
uint64_t TFeatureID
Definition of a feature ID.
holds feature data relevant to detection
void swap(CImage &o)
Very efficient swap of two images (just swap the internal pointers)
A list of visual features, to be used as output by detectors, as input/output by trackers, etc.
#define feat_detection_data(f)
double descr[FEATURE_MAX_D]
descriptor
float xMin
X coordinate limits [0,imageWidth)
int fprintf(FILE *fil, const char *format,...) noexcept MRPT_printf_format_check(2
An OS-independent version of fprintf.
void saveToTextFile(const std::string &fileName, bool APPEND=false)
Save feature list to a text file.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
GLdouble GLdouble GLdouble r
char * strcat(char *dest, size_t destSize, const char *source) noexcept
An OS-independent version of strcat.
Structure to represent an affine invariant image feature.
#define SIFT_INTVLS
default number of sampled intervals per octave
GLenum GLenum GLvoid * row
void extract_patch(CImage &patch, const unsigned int col=0, const unsigned int row=0, const unsigned int width=1, const unsigned int height=1) const
Extract a patch from this image, saveing it into "patch" (its previous contents will be overwritten)...
int round(const T value)
Returns the closer integer (int) to x.
bool saveToFile(const std::string &fileName, int jpeg_quality=95) const
Save the image to a file, whose format is determined from the extension (internally uses OpenCV)...
TInternalFeatList::iterator iterator
FILE * fopen(const char *fileName, const char *mode) noexcept
An OS-independent version of fopen.
GLsizei const GLfloat * value
#define SIFT_SIGMA
default sigma for initial gaussian smoothing
#define SIFT_IMG_DBL
default threshold on keypoint contrast |D(x)|
char * strcpy(char *dest, size_t destSize, const char *source) noexcept
An OS-independent version of strcpy.
This class is a "CSerializable" wrapper for "CMatrixFloat".
bool launchProcess(const std::string &command)
Executes the given command (which may contain a program + arguments), and waits until it finishes...
fixed floating point 'f'
void push_back(const CFeature::Ptr &f)
void memcpy(void *dest, size_t destSize, const void *src, size_t copyCount) noexcept
An OS and compiler independent version of "memcpy".