16 #if MRPT_HAS_OPENCV && MRPT_HAS_SIFT_HESS 24 #include <mrpt/otherlibs/do_opencv_includes.h> 25 #ifdef HAVE_OPENCV_NONFREE //MRPT_HAS_OPENCV_NONFREE 26 # include <opencv2/nonfree/nonfree.hpp> 28 #ifdef HAVE_OPENCV_FEATURES2D 29 # include <opencv2/features2d/features2d.hpp> 31 #ifdef HAVE_OPENCV_XFEATURES2D 32 # include <opencv2/xfeatures2d.hpp> 37 #ifdef MRPT_OS_WINDOWS 49 # if MRPT_OPENCV_VERSION_NUM>=0x211 55 #if MRPT_HAS_OPENCV && MRPT_HAS_SIFT_HESS 58 IplImage* create_init_img(
const IplImage*,
int,
double );
59 IplImage*** build_gauss_pyr( IplImage*,
int,
int,
double );
60 IplImage*** build_dog_pyr( IplImage***,
int,
int );
61 CvSeq* scale_space_extrema( IplImage***,
int,
int,
double,
int, CvMemStorage*);
62 int is_extremum( IplImage***,
int,
int,
int,
int );
63 struct feature* new_feature(
void );
64 void calc_feature_scales( CvSeq*,
double,
int );
65 void adjust_for_img_dbl( CvSeq* );
66 void calc_feature_oris( CvSeq*, IplImage*** );
67 void compute_descriptors( CvSeq*, IplImage***,
int,
int );
68 int feature_cmp(
void*,
void*,
void* );
69 void release_pyr( IplImage****,
int,
int );
71 #endif // MRPT_HAS_OPENCV 81 unsigned int nDesiredFeatures,
84 bool usingROI =
false;
97 img_grayscale.
swap(auximg);
100 switch( options.SIFTOptions.implementation )
108 #ifdef MRPT_OS_WINDOWS 110 char filImg[2000],filOut[2000],filFeat[2000];
113 GetTempPathA(1000,filOut);
os::strcat(filOut,1000,
"temp_out.txt");
114 GetTempPathA(1000,filImg);
os::strcat(filImg,1000,
"temp_img.bmp");
116 bool onlyDesc = feats.
size() > 0 ? true :
false;
120 GetTempPathA(1000,filFeat);
os::strcat(filFeat,1000,
"temp_feats.txt");
122 for (
size_t i= 0;i<feats.
size();i++)
124 listPoints(i,0) = feats[i]->x;
125 listPoints(i,1) = feats[i]->y;
147 THROW_EXCEPTION(
"[extractFeaturesSIFT] Could not launch external process... (extractSIFT.exe)" )
154 aux.loadFromTextFile( filOut );
155 std::cout <<
"[computeSiftFeatures] " << aux.getRowCount() <<
" features." << std::endl;
158 nFeats = feats.
size();
161 nFeats = aux.getRowCount();
166 itFeat != feats.
end();
170 (*itFeat)->x = usingROI ? aux(i,0) + ROI.
xMin : aux(i,0);
171 (*itFeat)->y = usingROI ? aux(i,1) + ROI.
yMin : aux(i,1);
172 (*itFeat)->orientation = aux(i,2);
173 (*itFeat)->scale = aux(i,3);
174 (*itFeat)->ID = init_ID + i;
177 aux.extractRow(i, (*itFeat)->descriptors.SIFT, 4);
182 THROW_EXCEPTION(
"Unfortunately, this SIFT Implementation only runs in Windows OS, try Hess implementation");
192 #ifdef MRPT_OS_WINDOWS 193 THROW_EXCEPTION(
"Usage of Vedaldi Binary not implemented yet, please, try another one");
195 THROW_EXCEPTION(
"Unfortunately, this SIFT Implementation only runs in Windows OS, try Hess implementation");
205 #ifdef MRPT_OS_WINDOWS 206 char filImg[2000],filOut[2000];
211 GetTempPathA(1000,filOut);
os::strcat(filOut,1000,
"temp_out.txt");
212 GetTempPathA(1000,filImg);
os::strcat(filImg,1000,
"temp_img.pgm");
214 bool valid = img_grayscale.
saveToFile( filImg );
216 THROW_EXCEPTION(
"An error occurred when saving input image into a .pgm file");
219 os::strcpy( paramImg,1000,
format(
"cmd /C gmic.exe %s -o %s -quiet", filImg, filImg ).c_str() );
224 THROW_EXCEPTION(
"[extractFeaturesSIFT] Could not launch external process... (gmic.exe)");
235 THROW_EXCEPTION(
"[extractFeaturesSIFT] Could not launch external process... (siftWin32.exe)");
240 unsigned int dLen, nFeats;
243 THROW_EXCEPTION(
"Error in extract SIFT with Lowe binary, output file not found!" );
244 fscanf( f,
"%u %u", &nFeats, &dLen);
246 for(
size_t i = 0; i < nFeats; i++ )
251 feat->ID = init_ID + i;
256 fscanf( f,
"%f %f %f %f", &fy, &fx, &fo, &fs );
258 feat->x = usingROI ? fx + ROI.
xMin : fx;
259 feat->y = usingROI ? fy + ROI.
yMin : fy;
260 feat->orientation = fo;
264 feat->descriptors.SIFT.resize( dLen );
266 for(
unsigned int k = 0; k < dLen; k++)
268 fscanf( f,
"%u", &
c );
269 feat->descriptors.SIFT[k] = (
unsigned char)
c;
278 THROW_EXCEPTION(
"Unfortunately, this SIFT Implementation only runs in Windows OS, try Hess implementation");
288 #if !MRPT_HAS_SIFT_HESS 289 THROW_EXCEPTION(
"Method not available since MRPT has been compiled without Hess' SIFT library")
290 #elif MRPT_HAS_OPENCV // OK, we have Hess' sift: 292 IplImage*** gauss_pyr, *** dog_pyr;
293 CvMemStorage* storage;
299 const IplImage* ipl_im = img_grayscale.
getAs<IplImage>();
301 octvs = log( (
float)(
MIN( init_img->width, init_img->height )) ) / log((
float)2) - 2;
303 dog_pyr = build_dog_pyr( gauss_pyr, octvs,
SIFT_INTVLS );
304 storage = cvCreateMemStorage( 0 );
305 features = scale_space_extrema( dog_pyr, octvs,
SIFT_INTVLS,
306 options.SIFTOptions.threshold,
307 options.SIFTOptions.edgeThreshold,
311 adjust_for_img_dbl( features );
312 calc_feature_oris( features, gauss_pyr );
316 cvSeqSort( features, (CvCmpFunc)feature_cmp, NULL );
319 if( nDesiredFeatures > 0 )
321 if( nDesiredFeatures < (
unsigned int)features->total )
322 cvSeqPopMulti( features, NULL, features->total - nDesiredFeatures );
324 cout <<
"[Warning] Detected less features than the requested " << features->total <<
" vs " << nDesiredFeatures << endl;
328 convertCvSeqInCFeatureList( features, feats, init_ID, ROI );
331 cvClearSeq( features );
332 cvReleaseMemStorage( &storage );
333 cvReleaseImage( &init_img );
337 THROW_EXCEPTION(
"Method not available since MRPT has been compiled without OpenCV")
338 #endif //MRPT_HAS_OPENCV 346 #if defined(HAVE_OPENCV_NONFREE) || defined(HAVE_OPENCV_XFEATURES2D) //MRPT_HAS_OPENCV_NONFREE 348 #if MRPT_OPENCV_VERSION_NUM >= 0x211 && MRPT_OPENCV_VERSION_NUM < 0x300 350 SiftFeatureDetector SIFTDetector(
351 options.SIFTOptions.threshold,
352 options.SIFTOptions.edgeThreshold
355 SiftDescriptorExtractor SIFTDescriptor;
357 vector<KeyPoint> cv_feats;
360 const IplImage* cGrey = img_grayscale.
getAs<IplImage>();
362 Mat theImg = cvarrToMat( cGrey );
363 SIFTDetector.detect( theImg, cv_feats );
366 SIFTDescriptor.compute( theImg, cv_feats, desc );
369 const size_t N = cv_feats.size();
370 unsigned int nMax = nDesiredFeatures != 0 && N > nDesiredFeatures ? nDesiredFeatures : N;
371 const int offset = (int)this->options.patchSize/2 + 1;
372 const size_t size_2 = options.patchSize/2;
373 const size_t imgH =
img.getHeight();
374 const size_t imgW =
img.getWidth();
376 unsigned int cont = 0;
379 while( cont != nMax && i != N )
381 const int xBorderInf = (int)floor( cv_feats[i].pt.x - size_2 );
382 const int xBorderSup = (int)floor( cv_feats[i].pt.x + size_2 );
383 const int yBorderInf = (int)floor( cv_feats[i].pt.y - size_2 );
384 const int yBorderSup = (int)floor( cv_feats[i].pt.y + size_2 );
386 if( options.patchSize==0 || ( (xBorderSup < (
int)imgW) && (xBorderInf > 0) && (yBorderSup < (int)imgH) && (yBorderInf > 0) ) )
391 ft->x = cv_feats[i].pt.x;
392 ft->y = cv_feats[i].pt.y;
393 ft->response = cv_feats[i].response;
394 ft->orientation = cv_feats[i].angle;
395 ft->scale = cv_feats[i].size;
396 ft->patchSize = options.patchSize;
397 ft->descriptors.SIFT.resize( 128 );
398 memcpy( &(ft->descriptors.SIFT[0]), &desc.data[128*i], 128*
sizeof(ft->descriptors.SIFT[0]) );
400 if( options.patchSize > 0 )
418 vector<KeyPoint> cv_feats;
420 cv::Ptr<cv::xfeatures2d::SIFT>sift = cv::xfeatures2d::SIFT::create(nDesiredFeatures,3, options.SIFTOptions.threshold, options.SIFTOptions.edgeThreshold,1.6 );
421 const IplImage* cGrey = img_grayscale.
getAs<IplImage>();
422 Mat theImg = cvarrToMat(cGrey);
424 sift->detect(theImg, cv_feats);
427 sift->compute(theImg, cv_feats, desc);
430 const size_t N = cv_feats.size();
431 unsigned int nMax = nDesiredFeatures != 0 && N > nDesiredFeatures ? nDesiredFeatures : N;
432 const int offset = (int)this->options.patchSize / 2 + 1;
433 const size_t size_2 = options.patchSize / 2;
434 const size_t imgH =
img.getHeight();
435 const size_t imgW =
img.getWidth();
437 unsigned int cont = 0;
442 while (cont != nMax && i != N)
444 const int xBorderInf = (int)floor(cv_feats[i].pt.x - size_2);
445 const int xBorderSup = (int)floor(cv_feats[i].pt.x + size_2);
446 const int yBorderInf = (int)floor(cv_feats[i].pt.y - size_2);
447 const int yBorderSup = (int)floor(cv_feats[i].pt.y + size_2);
449 if (options.patchSize == 0 || ((xBorderSup < (
int)imgW) && (xBorderInf > 0) && (yBorderSup < (int)imgH) && (yBorderInf > 0)))
454 ft->x = cv_feats[i].pt.x;
455 ft->y = cv_feats[i].pt.y;
456 ft->response = cv_feats[i].response;
457 ft->orientation = cv_feats[i].angle;
458 ft->scale = cv_feats[i].size;
459 ft->patchSize = options.patchSize;
460 ft->descriptors.SIFT.resize(128);
461 memcpy(&(ft->descriptors.SIFT[0]), &desc.data[128 * i], 128 *
sizeof(ft->descriptors.SIFT[0]));
463 if (options.patchSize > 0)
480 THROW_EXCEPTION(
"This method requires OpenCV >= 2.1.1 with nonfree module")
499 switch( options.SIFTOptions.implementation )
503 #ifdef MRPT_OS_WINDOWS 504 char filImg[2000],filOut[2000],filFeat[2000];
510 GetTempPathA(1000,filImg);
os::strcat( filImg, 1000,
"temp_img.bmp" );
511 GetTempPathA(1000,filOut);
os::strcat( filOut,1000,
"temp_feats.txt" );
512 GetTempPathA(1000,filFeat);
os::strcat( filFeat, 1000,
"temp_KLT_feats.txt" );
516 for(feat = in_features.
begin(); feat != in_features.
end(); feat++)
517 os::fprintf( fout,
"%.6f %.6f\n", (*feat)->x, (*feat)->y );
535 THROW_EXCEPTION(
"[extractFeaturesSIFT] Could not launch external process... (extractSIFT.exe)");
540 aux.loadFromTextFile( filOut );
541 size_t nRows = aux.getRowCount();
543 std::cout <<
"[computeSiftFeatures1] " << nRows <<
" features.\n";
549 feat = in_features.
begin();
551 for(i = 0; i < nRows; i++)
553 if( aux(i,0) != lx || aux(i,1) != ly )
556 (*feat)->orientation = aux(i,2);
557 (*feat)->scale = aux(i,3);
560 aux.extractRow(i, (*feat)->descriptors.SIFT, 4);
577 #if !MRPT_HAS_SIFT_HESS 578 THROW_EXCEPTION(
"Method not available since MRPT has been compiled without Hess' SIFT library")
579 #elif MRPT_HAS_OPENCV // OK, we have Hess' sift: 581 IplImage*** gauss_pyr, *** dog_pyr;
582 CvMemStorage* storage;
591 const IplImage* ipl_im = img_grayscale.getAs<IplImage>();
594 octvs = log( (
float)(
MIN( init_img->width, init_img->height )) ) / log((
float)2) - 2;
596 dog_pyr = build_dog_pyr( gauss_pyr, octvs,
SIFT_INTVLS );
598 storage = cvCreateMemStorage( 0 );
599 features =
static_cast<CvSeq*
>(my_scale_space_extrema( in_features, dog_pyr, octvs,
SIFT_INTVLS,
600 options.SIFTOptions.threshold,
601 options.SIFTOptions.edgeThreshold,
605 my_adjust_for_img_dbl( features );
606 calc_feature_oris( features, gauss_pyr );
610 insertCvSeqInCFeatureList( features, in_features );
613 cvClearSeq( features );
616 cvReleaseMemStorage( &storage );
617 cvReleaseImage( &init_img );
653 THROW_EXCEPTION(
"Method not available since MRPT has been compiled without OpenCV")
654 #endif //MRPT_HAS_OPENCV 659 cout <<
"SIFT Extraction method not supported for features with already known image coordinates" << endl;
672 #if MRPT_HAS_OPENCV && MRPT_HAS_SIFT_HESS 673 CvSeq* features =
reinterpret_cast<CvSeq*
>( features_ );
676 bool usingROI =
false;
680 int n = features->total;
685 for(
int k = 0; k <
n; k++ )
687 thisFeat = (
feature*)cvGetSeqElem( features, k );
690 feat->x = usingROI ? thisFeat->
x + ROI.
xMin : thisFeat->
x;
691 feat->y = usingROI ? thisFeat->
y + ROI.
yMin : thisFeat->
y;
693 feat->orientation = thisFeat->
ori;
694 feat->scale = thisFeat->
scl;
695 feat->descriptors.SIFT.resize( thisFeat->
d );
696 for(
int i = 0; i < thisFeat->
d; i++ )
697 feat->descriptors.SIFT[i] = (
unsigned char)thisFeat->
descr[i];
702 THROW_EXCEPTION(
"Method not available since MRPT has been compiled without OpenCV")
703 #endif //MRPT_HAS_OPENCV 710 #if MRPT_HAS_OPENCV && MRPT_HAS_SIFT_HESS 711 CvSeq* features =
reinterpret_cast<CvSeq*
>( features_ );
713 int n = features->total;
719 for( itFeat = list.
begin(), k = 0; itFeat != list.
end() && k <
n; k++ )
721 thisFeat = (
feature*)cvGetSeqElem( features, k );
722 if( (*itFeat)->x == thisFeat->
x && (*itFeat)->y == thisFeat->
y )
725 (*itFeat)->orientation = thisFeat->
ori;
726 (*itFeat)->scale = thisFeat->
scl;
727 (*itFeat)->descriptors.SIFT.resize( thisFeat->
d );
728 for(
int i = 0; i < thisFeat->
d; i++ )
729 (*itFeat)->descriptors.SIFT[i] = (
unsigned char)thisFeat->
descr[i];
735 THROW_EXCEPTION(
"Method not available since MRPT has been compiled without OpenCV")
736 #endif //MRPT_HAS_OPENCV 747 #if MRPT_HAS_OPENCV && MRPT_HAS_SIFT_HESS 748 CvSeq* features =
reinterpret_cast<CvSeq*
>( features_ );
753 for( i = 0; i <
n; i++ )
755 feat = CV_GET_SEQ_ELEM(
struct feature, features, i );
759 THROW_EXCEPTION(
"Method not available since MRPT has been compiled without OpenCV")
760 #endif //MRPT_HAS_OPENCV 768 int octvs,
int intvls,
double contr_thr,
int curv_thr,
769 void* storage_ )
const 772 #if MRPT_HAS_OPENCV && MRPT_HAS_SIFT_HESS 773 CvMemStorage* storage =
reinterpret_cast<CvMemStorage*
>( storage_ );
774 IplImage*** dog_pyr =
reinterpret_cast<IplImage***
>( dog_pyr_ );
784 features = cvCreateSeq( 0,
sizeof(CvSeq),
sizeof(
struct feature), storage );
785 for(itFeats = featList.
begin(); itFeats != featList.
end(); itFeats++)
790 float gr = 0.0, gc = 0.0;
792 if( (*itFeats)->y < 0 || (*itFeats)->x < 0 )
796 for( o = 0; o < octvs; o++ )
798 float r = (*itFeats)->y/pow(2.0,o);
799 float c = (*itFeats)->x/pow(2.0,o);
801 for( i = 1; i <= intvls; i++ )
804 double val =
s*getLaplacianValue( dog_pyr, o, i,
r,
c );
825 feat = new_feature();
827 feat->
img_pt.x = feat->
x = (*itFeats)->x;
828 feat->
img_pt.y = feat->
y = (*itFeats)->y;
835 cvSeqPush( features, feat );
840 THROW_EXCEPTION(
"Method not available since MRPT has been compiled without OpenCV")
841 #endif //MRPT_HAS_OPENCV 849 #if MRPT_HAS_OPENCV && MRPT_HAS_SIFT_HESS 850 IplImage*** dog_pyr =
reinterpret_cast<IplImage***
>( dog_pyr_ );
854 for( j = -1; j <= 1; j++ )
855 for( k = -1; k <= 1; k++ )
861 if( k == 0 && j == 0 )
868 THROW_EXCEPTION(
"Method not available since MRPT has been compiled without OpenCV")
869 #endif //MRPT_HAS_OPENCV 878 #if MRPT_HAS_OPENCV && MRPT_HAS_SIFT_HESS 879 IplImage*** dog_pyr =
reinterpret_cast<IplImage***
>( dog_pyr_ );
888 for( i = -1; i <= 1; i++ )
889 for( j = -1; j <= 1; j++ )
890 for( k = -1; k <= 1; k++ )
899 THROW_EXCEPTION(
"Method not available since MRPT has been compiled without OpenCV")
900 #endif //MRPT_HAS_OPENCV void BASE_IMPEXP memcpy(void *dest, size_t destSize, const void *src, size_t copyCount) MRPT_NO_THROWS
An OS and compiler independent version of "memcpy".
FILE BASE_IMPEXP * fopen(const char *fileName, const char *mode) MRPT_NO_THROWS
An OS-independent version of fopen.
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 BASE_IMPEXP void BASE_IMPEXP 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
int BASE_IMPEXP fprintf(FILE *fil, const char *format,...) MRPT_NO_THROWS MRPT_printf_format_check(2
An OS-independent version of fprintf.
char BASE_IMPEXP * strcpy(char *dest, size_t destSize, const char *source) MRPT_NO_THROWS
An OS-independent version of strcpy.
bool BASE_IMPEXP launchProcess(const std::string &command)
Executes the given command (which may contain a program + arguments), and waits until it finishes...
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.
#define MRPT_UNUSED_PARAM(a)
Can be used to avoid "not used parameters" warnings from the compiler.
Scale Invariant Feature Transform [LOWE'04].
std::string BASE_IMPEXP 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
void push_back(const CFeaturePtr &f)
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)
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
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)...
char BASE_IMPEXP * strcat(char *dest, size_t destSize, const char *source) MRPT_NO_THROWS
An OS-independent version of strcat.
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
static CFeaturePtr Create()
GLsizei const GLfloat * value
#define SIFT_SIGMA
default sigma for initial gaussian smoothing
#define SIFT_IMG_DBL
default threshold on keypoint contrast |D(x)|
This class is a "CSerializable" wrapper for "CMatrixFloat".
size_t getWidth() const MRPT_OVERRIDE
Returns the width of the image in pixels.
fixed floating point 'f'
size_t getHeight() const MRPT_OVERRIDE
Returns the height of the image in pixels.