32 #include <mrpt/otherlibs/do_opencv_includes.h> 42 #ifdef MRPT_OS_WINDOWS 56 const CFeaturePtr & feat,
60 for(
int k = 0; k < int(feat->multiScales.size()); ++k )
62 for(
int m = 0; m < int(feat->multiOrientations[k].size()); ++m )
64 int key1 = feat->multiHashCoeffs[k][m][0];
65 int key2 = feat->multiHashCoeffs[k][m][1];
66 int key3 = feat->multiHashCoeffs[k][m][2];
69 if( qTable.find(key1) != qTable.end() &&
70 qTable[key1].find(key2) != qTable[key1].end() &&
71 qTable[key1][key2].find(key3) != qTable[key1][key2].end() )
75 for(
int n = 0;
n < int(qTable[key1][key2][key3].
size()); ++
n )
77 TFeatureID thisID = qTable[key1][key2][key3][
n].first;
78 double thisScale = qTable[key1][key2][key3][
n].second;
79 if( thisID == feat->ID && thisScale == feat->multiScales[k] )
85 qTable[key1][key2][key3].push_back( make_pair(feat->ID,feat->multiScales[k]) );
98 typedef map<int,map<int,map<int,deque<pair<TFeatureID, double> > > > >
TQuantizationTable;
104 for( it1 = qTable.begin(); it1 != qTable.end(); ++it1 )
105 for( it2 = it1->second.begin(); it2 != it1->second.end(); ++it2 )
106 for( it3 = it2->second.begin(); it3 != it2->second.end(); ++it3 )
109 for(
int k = 0; k < int(it3->second.size()); ++k )
110 mrpt::system::os::fprintf( f,
"%lu\t%.2f\t",static_cast<long unsigned int>(it3->second[k].first), it3->second[k].second );
129 const bool PARAR =
false;
140 map<int,map<int,deque<pair<TFeatureID, double> > > >
::iterator it2;
141 map<int,deque<pair<TFeatureID, double> > >
::iterator it3;
143 vector<TFeatureID> vID;
147 int h =
image.getHeight();
149 map<TFeatureID, vector<double> > featsToCompareMap;
153 for( it = currentList.
begin(); it != currentList.
end(); ++it, ++curCounter )
155 if( PARAR && (*it)->ID == 193 )
157 for(
int i = 0; i < (int)(*it)->multiScales.size(); ++i )
158 cout << (*it)->multiScales[i] << endl;
160 ASSERT_( (*it)->multiHashCoeffs.size() == (*it)->multiScales.size() );
166 featsToCompareMap.clear();
167 if( !(*it)->descriptors.hasDescriptorMultiSIFT() )
169 cout <<
"[relocalizeMultiDesc] Feature " << (*it)->ID <<
" in currentList hasn't got any descriptor." << endl;
175 if( (*it)->x+hpSize > (
w-1) || (*it)->y+hpSize > (h-1) ||
176 (*it)->x-hpSize < 0 || (*it)->y-hpSize < 0 )
178 cout <<
"[relocalizeMultiDesc] WARNING: Feature too close to the border. MultiDescriptor computation skipped." << endl;
184 for(
int k = 0; k < int((*it)->multiOrientations[0].size()); ++k )
188 int c1mn = (*it)->multiHashCoeffs[0][k][0] - TH;
189 int c1mx = (*it)->multiHashCoeffs[0][k][0] + TH;
191 int c2mn = (*it)->multiHashCoeffs[0][k][1] - TH;
192 int c2mx = (*it)->multiHashCoeffs[0][k][1] + TH;
194 int c3mn = (*it)->multiHashCoeffs[0][k][2] - TH;
195 int c3mx = (*it)->multiHashCoeffs[0][k][2] + TH;
197 for(
int m1 = c1mn; m1 < c1mx; ++m1 )
199 it1 = qTable.find(m1);
200 if( it1 != qTable.end() )
202 for(
int m2 = c2mn; m2 < c2mx; ++m2 )
204 it2 = it1->second.find(m2);
205 if( it2 != it1->second.end() )
207 for(
int m3 = c3mn; m3 < c3mx; ++m3 )
209 it3 = it2->second.find(m3);
210 if( it3 != it2->second.end() )
212 for(
int n = 0;
n < int(it3->second.size()); ++
n )
214 featsToCompareMap[qTable[m1][m2][m3][
n].first].push_back( qTable[m1][m2][m3][
n].second );
224 vID.resize( featsToCompareMap.size() );
226 for( map<
TFeatureID, vector<double> >::
iterator nit = featsToCompareMap.begin(); nit != featsToCompareMap.end(); ++nit, ++
counter )
229 std::sort( nit->second.begin(), nit->second.end() );
232 vit = std::unique( nit->second.begin(), nit->second.end() );
234 nit->second.resize( vit - nit->second.begin() );
247 for( map<
TFeatureID, vector<double> >::
iterator nit = featsToCompareMap.begin(); nit != featsToCompareMap.end(); ++nit, ++
counter )
250 CFeaturePtr baseFeat = baseList.
getByID( nit->first, baseIdx );
256 for(
int k1 = 0; k1 < int(baseFeat->multiScales.size()); ++k1 )
259 for(
int k2 = 0; k2 < int(nit->second.size()); ++k2 )
261 if( baseFeat->multiScales[k1] == nit->second[k2] )
264 for(
int k3 = 0; k3 < int(baseFeat->multiOrientations[k1].size()); ++k3 )
267 for(
int k4 = 0; k4 < int((*it)->multiOrientations[0].size()); ++k4 )
270 if( fabs(baseFeat->multiOrientations[k1][k3]-(*it)->multiOrientations[0][k4]) >
DEG2RAD(10) )
277 for(
int d = 0; d < int(baseFeat->descriptors.multiSIFTDescriptors[k1][k3].size()); ++d )
278 dist += fabs(
float(baseFeat->descriptors.multiSIFTDescriptors[k1][k3][d]) - float((*it)->descriptors.multiSIFTDescriptors[0][k4][d]) );
284 minBaseFeat = baseIdx;
330 const vector<int> & idx )
335 size_t sz = idx.size();
339 for(
int k = 0; k < (int)sz; ++k )
343 baseList[k]->nTimesNotSeen++;
344 baseList[k]->nTimesLastSeen++;
348 baseList[k]->nTimesSeen++;
349 baseList[k]->nTimesLastSeen = 0;
352 dp[k] = fabs(baseList[k]->
depth-currentList[idx[k]]->
depth);
361 cout <<
"mean&std: " << m_dp <<
"," << std_dp << endl;
363 for(
int k = 0; k < (int)idx.size(); ++k )
368 if( dp[k] < (m_dp+std_dp) )
370 baseList[k]->x = currentList[idx[k]]->x;
371 baseList[k]->y = currentList[idx[k]]->y;
372 baseList[k]->p3D = currentList[idx[k]]->p3D;
389 const CImage & currentImage,
397 for( itBase = baseList.begin(); itBase!= baseList.end(); ++m )
406 itBase = baseList.erase( itBase );
426 cout <<
"Left feature " << m <<
" found in scale 0!" << endl;
430 ASSERT_( itBase->first->descriptors.hasDescriptorMultiSIFT() );
431 if(
res == 0) cout <<
"LF LOWSCALES Out of bounds!!" << endl;
436 size_t nscales = itBase->first->multiScales.size()-1;
440 cout <<
"Left feature " << m <<
" found in last scale!" << endl;
442 if(
res == 0) cout <<
"LF HIGHSCALES Out of bounds!!" << endl;
460 const unsigned int x,
461 const unsigned int y,
465 if(
x > 0 &&
x <
image.getWidth()-1 &&
y > 0 &&
y <
image.getHeight()-1 )
480 mag = sqrt( d1*d1 + d2*d2 );
481 ori = atan2( d2, d1 );
486 cout <<
"[computeGradient]: Out of bounds in " <<
x <<
"," <<
y <<
" with image: " <<
image.getWidth() <<
"x" <<
image.getHeight() << endl;
497 const unsigned int x,
498 const unsigned int y,
499 const unsigned int patchSize,
500 std::vector<double> & orientations,
501 const double & sigma )
506 orientations.clear();
509 const unsigned int NBINS = 36;
510 const int hPatchSize = patchSize/2;
512 vector<double> oris( NBINS, 0.0 );
513 int mx = (int)
x, my = (
int)
y;
516 if( mx-(hPatchSize+1) < 0 || my-(hPatchSize+1) < 0 || mx+(hPatchSize+1) > (int)(
image.getWidth()-1) || my+(hPatchSize+1) > (int)(
image.getHeight()-1) )
523 double exp_denom = 2.0 * sigma *sigma;
524 double bin_size =
M_2PI/NBINS;
526 for(
int ii = -hPatchSize; ii <= hPatchSize; ++ii )
527 for(
int jj = -hPatchSize; jj <= hPatchSize; ++jj )
532 double w = mag*exp( -( ii*ii + jj*jj ) / exp_denom );
534 int bin = ((int)(floor(ori/bin_size))) % NBINS;
535 double bin_center = bin*bin_size;
536 double dif = ori-bin_center;
539 nxbin = bin == NBINS-1 ? 0 : bin+1;
541 nxbin = bin == 0 ? NBINS-1 : bin-1;
543 double nbin_center = nxbin*bin_size;
544 double dif2 = ori-nbin_center;
546 oris[bin] +=
w*fabs(dif2)/bin_size;
547 oris[nxbin] +=
w*fabs(dif)/bin_size;
554 for(
unsigned int k = 0; k < oris.size(); ++k )
556 if( oris[k] > mxori )
563 double hist_mag_th = 0.8*mxori;
564 for(
unsigned int k = 0; k < oris.size(); ++k )
566 double pv = k == 0 ? oris[oris.size()-1] : oris[k-1];
567 double nv = k == oris.size()-1 ? 0 : oris[k+1];
569 if( oris[k] > pv && oris[k] > nv && oris[k] > hist_mag_th )
576 double int_bin = k + 0.5 * (pv-nv)/(pv-2.0*oris[k]+nv);
577 int_bin = ( int_bin < 0 ) ? NBINS + int_bin : ( int_bin >= NBINS ) ? int_bin - NBINS : int_bin;
578 double int_ori = ( (
M_2PI * int_bin ) / NBINS ) -
M_PI;
579 orientations.push_back( int_ori );
592 vector<double> & oris,
607 double ncbin = cbin + d/2. - 0.5;
608 double nrbin = rbin + d/2. - 0.5;
610 int ncbin_i = floor( ncbin );
611 int nrbin_i = floor( nrbin );
612 int nobin_i = floor( obin );
614 double d_c = ncbin_i - ncbin;
615 double d_r = nrbin_i - nrbin;
616 double d_o = nobin_i - obin;
618 for(
int k = 0; k < 2; ++k )
619 for(
int m = 0; m < 2; ++m )
620 for(
int l = 0; l < 2; ++l )
621 if( ncbin_i+k >= 0 && ncbin_i+k < d && nrbin_i+m >= 0 && nrbin_i+m < d )
623 int idx = ((nobin_i+l)%
n) +
n*(ncbin_i+k) +
n*d*(nrbin_i+m);
624 oris[idx] += mag*(1-fabs(d_c+k))*(1-fabs(d_r+m))*(1-fabs(d_o+l));
690 const unsigned int x,
691 const unsigned int y,
692 const unsigned int patchSize,
693 const double & orientation,
694 vector<int32_t> & descriptor,
696 vector<int32_t> & hashCoeffs )
706 double cos_t = cos( orientation );
707 double sin_t = sin( orientation );
708 double bins_per_rad =
n /
M_2PI;
709 double exp_denom = opts.
sg3*opts.
sg3*2;
710 int radius = 0.5*patchSize;
711 vector<double> oris( Bp*Bp*
n, 0.0 );
728 const double kp = double(Bp)/double(
w);
730 double cbin, rbin, obin;
731 double c1 = 0.0, c2 = 0.0, c3 = 0.0;
745 for(
int c = -radius;
c <= radius; ++
c )
746 for(
int r = -radius;
r <= radius; ++
r )
748 cbin = kp*
c*cos_t - kp*
r*sin_t;
749 rbin = kp*
c*sin_t + kp*
r*cos_t;
751 if( cbin > -2.5 && cbin < 2.5 && rbin > -2.5 && rbin < 2.5 )
753 tlogger.enter(
"computeGradient");
755 tlogger.leave(
"computeGradient");
761 while( ori >=
M_2PI )
764 obin = ori*bins_per_rad;
765 w = exp( -(
c*
c +
r*
r) / exp_denom );
766 tlogger.enter(
"interpolate");
768 tlogger.leave(
"interpolate");
803 if( (cbin < 0 && rbin < 0) || (cbin > 0 && rbin > 0) )
834 hashCoeffs.resize(3);
835 hashCoeffs[0] =
round(c1);
836 hashCoeffs[1] =
round(c2);
837 hashCoeffs[2] =
round(c3);
843 tlogger.enter(
"normalize");
845 for(
unsigned int ii = 0; ii < oris.size(); ++ii )
846 sum += oris[ii]*oris[ii];
848 for(
unsigned int ii = 0; ii < oris.size(); ++ii )
852 for(
unsigned int ii = 0; ii < oris.size(); ++ii )
856 for(
unsigned int ii = 0; ii < oris.size(); ++ii )
857 sum += oris[ii]*oris[ii];
859 for(
unsigned int ii = 0; ii < oris.size(); ++ii )
863 descriptor.resize( oris.size() );
864 for(
unsigned int ii = 0; ii < descriptor.size(); ++ii )
865 descriptor[ii] = (
int)(255.0f*oris[ii]);
867 tlogger.leave(
"normalize");
878 const CImage & rightImage,
914 int leftFeatCounter = 0;
915 int rightFeatCounter = 0;
926 for( leftFeatCounter = 0, it1 = list1.
begin(); it1 != list1.
end(); ++it1, ++leftFeatCounter )
928 if( !(*it1)->descriptors.hasDescriptorMultiSIFT() )
931 double sRegionX0 = max( (*it1)->x-
min((hWindow+2*(*it1)->nTimesLastSeen), mxsize), 0.0f);
932 double sRegionX1 =
min( (*it1)->x+
min((hWindow+2*(*it1)->nTimesLastSeen), mxsize), (
float)imageW );
933 double sRegionY0 = max( (*it1)->y-
min((hWindow+2*(*it1)->nTimesLastSeen), mxsize), 0.0f);
934 double sRegionY1 =
min( (*it1)->y+
min((hWindow+2*(*it1)->nTimesLastSeen), mxsize), (
float)imageH );
942 for( rightFeatCounter = 0, it2 = list2.
begin(); it2 != list2.
end(); ++it2, ++rightFeatCounter )
952 if( (*it2)->x < sRegionX0 || (*it2)->x > sRegionX1 || (*it2)->y < sRegionY0 || (*it2)->y > sRegionY1 )
969 vector<double> thisOris;
982 int firstScale, lastScale;
987 firstScale = max( 0, (
int)matchOpts.
lowScl1 );
988 lastScale =
min( (
int)(*it1)->multiScales.size()-1, (int)matchOpts.
highScl1 );
998 for(
int k1 = firstScale; k1 <= lastScale; ++k1 )
999 for(
int k2 = 0; k2 < (int)(*it1)->multiOrientations[k1].size(); ++k2 )
1000 for(
int k3 = 0; k3 < (int)thisOris.size(); ++k3 )
1001 if( fabs( (*it1)->multiOrientations[k1][k2] - thisOris[k3] ) < matchOpts.
oriThreshold ||
1002 fabs(
M_2PI - fabs( (*it1)->multiOrientations[k1][k2] - thisOris[k3] ) ) < matchOpts.
oriThreshold )
1010 if( list2.
size() >= 8 )
1012 std::vector< size_t > out_idx;
1013 std::vector< float > out_dist_sqr;
1014 maxResponse = (*it2)->response;
1017 for(
size_t kdcounter = 0; kdcounter < out_idx.size(); ++kdcounter )
1019 if( out_dist_sqr[kdcounter] > 1.4142 )
1022 if( list2[out_idx[kdcounter]]->response > maxResponse )
1024 maxResponse = list2[out_idx[kdcounter]]->response;
1033 cout <<
"NO ES MAX" << endl;
1047 if( (*it2)->multiScales.size() == 0 )
1049 (*it2)->multiScales.resize(1);
1050 (*it2)->multiScales[0] = 1.0;
1051 (*it2)->multiOrientations.resize(1);
1052 (*it2)->descriptors.multiSIFTDescriptors.resize(1);
1053 (*it2)->multiHashCoeffs.resize(1);
1057 bool oriFound =
false;
1059 for(
int co = 0; co < (int)(*it2)->multiOrientations[0].size(); ++co )
1060 if( (*it2)->multiOrientations[0][co] == thisOris[k3] )
1073 (*it2)->multiOrientations[0].push_back( thisOris[k3] );
1075 vector<int32_t> thisDesc, thisHash;
1078 (*it2)->x, (*it2)->y,
1086 (*it2)->descriptors.multiSIFTDescriptors[0].push_back( thisDesc );
1088 (*it2)->multiHashCoeffs[0].push_back( thisHash );
1090 for(
int n = 0;
n < int(thisDesc.size());
n++ )
1091 dist +=
square( (*it1)->descriptors.multiSIFTDescriptors[k1][k2][
n] - thisDesc[
n] );
1098 for(
int n = 0;
n < (int)(*it2)->descriptors.multiSIFTDescriptors[0][wh].size();
n++ )
1099 dist +=
square( (*it1)->descriptors.multiSIFTDescriptors[k1][k2][
n] - (*it2)->descriptors.multiSIFTDescriptors[0][wh][
n] );
1109 if( dist < minDist )
1112 ridx = rightFeatCounter;
1113 maxResponse = (*it2)->response;
1182 const CImage & leftImage,
1183 const CImage & rightImage,
1206 ASSERT_( mList1.size() > 0 && mList2.size() > 0 );
1214 vector<int> scales1, scales2;
1251 cout <<
"Left matches: " << output1.
nMatches <<
" out of " << baseList1.size() <<
"," << auxList1.
size() << endl;
1252 cout <<
"Right matches: " << output2.
nMatches <<
" out of " << baseList2.size() <<
"," << auxList2.
size() << endl;
1253 cout <<
"Matched list: " << mList1.size() << endl;
1265 for( m = 0, itMatch = mList1.begin(); itMatch != mList1.end(); ++m )
1273 itMatch = mList1.erase( itMatch );
1282 if( scales1[m] == 0 )
1284 cout <<
"Left feature " << m <<
" found in scale 0!" << endl;
1286 if(
res == 0) cout <<
"LF LOWSCALES Out of bounds!!" << endl;
1291 int nScales = (int)itMatch->first->multiScales.size();
1292 if( scales1[m] == nScales-1 )
1294 cout <<
"Left feature " << m <<
" found in last scale!" << endl;
1295 cout <<
"tidx=" << tidx << endl;
1297 if(
res == 0) cout <<
"LF HIGHSCALES Out of bounds!!" << endl;
1308 if( scales2[m] == 0 )
1310 cout <<
"Right feature " << m <<
" found in scale 0!" << endl;
1312 if(
res == 0) cout <<
"RF LOWSCALES Out of bounds!!" << endl;
1317 int nScales = (int)itMatch->second->multiScales.size();
1318 if( scales2[m] == nScales-1 )
1320 cout <<
"Right feature " << m <<
" found in scale!" << endl;
1322 if(
res == 0) cout <<
"RF HIGHSCALES Out of bounds!!" << endl;
1331 return mList1.size();
1340 const CFeaturePtr & inputFeat,
1341 CFeaturePtr & outputFeat,
1342 const bool & lowerScales,
1345 #if MRPT_HAS_OPENCV && MRPT_OPENCV_VERSION_NUM>=0x211 1354 const cv::Mat inImg1 = cv::cvarrToMat(
image.getAs<IplImage>(),
false );
1356 cv::GaussianBlur( inImg1, tempImg1, cvSize(0,0), opts.
sg1 , opts.
sg1 );
1358 CImage smLeftImg( &aux1 );
1363 int largestSize = lowerScales ?
round(
a*0.8) :
round(
a*2.0);
1364 largestSize = largestSize%2 ? largestSize : largestSize+1;
1365 int hLargestSize = largestSize/2;
1367 unsigned int npSize, hpSize;
1370 if( inputFeat->x+hLargestSize > smLeftImg.
getWidth()-1 || inputFeat->x-hLargestSize < 0 ||
1371 inputFeat->y+hLargestSize > smLeftImg.
getHeight()-1 || inputFeat->y-hLargestSize < 0 )
1377 vector<double> thisScales(2);
1378 thisScales[0] = 0.5;
1379 thisScales[1] = 0.8;
1381 double baseScale = outputFeat->multiScales[0];
1384 outputFeat->multiScales.push_front( thisScales[1]*baseScale );
1385 outputFeat->multiScales.push_front( thisScales[0]*baseScale );
1390 for(
int k = 1; k >= 0; --k )
1392 npSize =
round(
a*thisScales[k] );
1393 npSize = npSize%2 ? npSize : npSize+1;
1399 smLeftImg.
extract_patch( tPatch, inputFeat->x-hpSize, inputFeat->y-hpSize, npSize, npSize );
1401 cv::Mat out_mat_patch;
1404 cv::resize( cv::cvarrToMat(tPatch.
getAs<IplImage>(),
false ), out_mat_patch, cv::Size(
a+2,
a+2) );
1405 IplImage aux_img = IplImage(out_mat_patch);
1406 CImage rsPatch( &aux_img );
1409 vector<double> auxOriVector;
1412 cout <<
"computeMainOrientations returned false" << endl;
1417 vector< vector<int32_t> > auxDescVector;
1418 vector< vector<int32_t> > auxHashCoeffs;
1419 auxDescVector.resize( auxOriVector.size() );
1420 auxHashCoeffs.resize( auxOriVector.size() );
1421 for(
unsigned int m = 0; m < auxOriVector.size(); ++m )
1428 auxDescVector[m], opts,
1432 outputFeat->multiOrientations.push_front( auxOriVector );
1433 outputFeat->descriptors.multiSIFTDescriptors.push_front( auxDescVector );
1434 outputFeat->multiHashCoeffs.push_front( auxHashCoeffs );
1440 vector<double> thisScales(4);
1441 thisScales[0] = 1.2;
1442 thisScales[1] = 1.5;
1443 thisScales[2] = 1.8;
1444 thisScales[3] = 2.0;
1446 size_t nCurrScales = outputFeat->multiScales.size();
1447 outputFeat->multiScales.push_back( thisScales[0]*outputFeat->multiScales[nCurrScales-1] );
1448 outputFeat->multiScales.push_back( thisScales[1]*outputFeat->multiScales[nCurrScales-1] );
1449 outputFeat->multiScales.push_back( thisScales[2]*outputFeat->multiScales[nCurrScales-1] );
1450 outputFeat->multiScales.push_back( thisScales[3]*outputFeat->multiScales[nCurrScales-1] );
1453 for(
int k = 0; k < (int)thisScales.size(); ++k )
1457 npSize =
round(
a*thisScales[k] );
1458 npSize = npSize%2 ? npSize : npSize+1;
1464 smLeftImg.
extract_patch( tPatch, inputFeat->x-hpSize, inputFeat->y-hpSize, npSize, npSize );
1466 cv::Mat out_mat_patch;
1469 cv::resize( cv::cvarrToMat( tPatch.
getAs<IplImage>(),
false), out_mat_patch, cv::Size(
a+2,
a+2) );
1470 IplImage aux_img = IplImage(out_mat_patch);
1471 CImage rsPatch( &aux_img );
1475 vector<double> auxOriVector;
1477 rsPatch,
a/2+1,
a/2+1,
a,
1478 auxOriVector, opts.
sg2 );
1482 vector< vector<int32_t> > auxDescVector;
1483 vector< vector<int32_t> > auxCoefVector;
1484 auxDescVector.resize( auxOriVector.size() );
1485 auxCoefVector.resize( auxOriVector.size() );
1486 for(
unsigned int m = 0; m < auxOriVector.size(); ++m )
1493 auxDescVector[m], opts,
1497 outputFeat->multiOrientations.push_back( auxOriVector );
1498 outputFeat->descriptors.multiSIFTDescriptors.push_back( auxDescVector );
1499 outputFeat->multiHashCoeffs.push_back( auxCoefVector );
1502 ASSERT_( outputFeat->descriptors.hasDescriptorMultiSIFT() );
1515 const CFeaturePtr & feat1,
1516 const CFeaturePtr & feat2,
1524 int numScales = int(feat1->multiScales.size());
1534 lastScale = numScales-1;
1537 double smin = (feat2->depth-0.15*feat1->initialDepth)/feat1->initialDepth;
1538 double smax = (feat2->depth+0.15*feat1->initialDepth)/feat1->initialDepth;
1540 if( smin <= feat1->multiScales[1] )
1544 if( smin > feat1->multiScales[numScales-2] )
1545 firstScale = numScales-2;
1548 for(
int k = 1; k <= numScales-3; ++k )
1549 if( smin > feat1->multiScales[k] )
1554 if( smax <= feat1->multiScales[1] )
1558 if( smax > feat1->multiScales[numScales-2] )
1559 lastScale = numScales-1;
1562 for(
int k = 1; k <= numScales-3; ++k )
1563 if( smax <= feat1->multiScales[k] )
1571 ASSERT_( firstScale >= 0 && lastScale < numScales && firstScale < lastScale );
1579 const CImage & imageLeft,
1580 const CImage & imageRight,
1584 #if MRPT_HAS_OPENCV && MRPT_OPENCV_VERSION_NUM>=0x211 1589 ASSERT_( matchedFeats.size() > 0 );
1594 tlogger.enter(
"smooth");
1595 cv::Mat tempImg1, tempImg2;
1596 IplImage aux1, aux2;
1598 const cv::Mat inImg1 = cv::cvarrToMat(imageLeft.
getAs<IplImage>());
1599 const cv::Mat inImg2 = cv::cvarrToMat(imageRight.
getAs<IplImage>());
1601 cv::GaussianBlur( inImg1, tempImg1, cvSize(0,0), opts.
sg1 , opts.
sg1 );
1603 CImage smLeftImg( &aux1 );
1605 cv::GaussianBlur( inImg2, tempImg2, cvSize(0,0), opts.
sg1 , opts.
sg1 );
1607 CImage smRightImg( &aux2 );
1608 tlogger.leave(
"smooth");
1612 unsigned int feat_counter = 0;
1613 unsigned int good_matches = 0;
1616 largestSize = largestSize%2 ? largestSize : largestSize+1;
1617 int hLargestSize = largestSize/2;
1619 unsigned int npSize;
1620 unsigned int hpSize;
1625 if( itMatch->first->x+hLargestSize > smLeftImg.
getWidth()-1 || itMatch->first->x-hLargestSize < 0 ||
1626 itMatch->first->y+hLargestSize > smLeftImg.
getHeight()-1 || itMatch->first->y-hLargestSize < 0 ||
1627 itMatch->second->x+hLargestSize > smRightImg.
getWidth()-1 || itMatch->second->x-hLargestSize < 0 ||
1628 itMatch->second->y+hLargestSize > smRightImg.
getHeight()-1 || itMatch->second->y-hLargestSize < 0 )
1633 tlogger.enter(
"compute depth");
1636 double disp = itMatch->first->x - itMatch->second->x;
1638 double x3D = (itMatch->first->x-opts.
cx)*aux;
1639 double y3D = (itMatch->first->y-opts.
cy)*aux;
1640 double z3D = opts.
fx*aux;
1642 itMatch->first->depth = sqrt( x3D*x3D + y3D*y3D + z3D*z3D );
1643 itMatch->second->depth = sqrt( (x3D-opts.
baseline)*(x3D-opts.
baseline) + y3D*y3D + z3D*z3D );
1645 tlogger.leave(
"compute depth");
1647 tlogger.enter(
"cp scales");
1648 itMatch->first->multiScales.resize( opts.
scales.size() );
1649 itMatch->first->multiOrientations.resize( opts.
scales.size() );
1650 itMatch->first->descriptors.multiSIFTDescriptors.resize( opts.
scales.size() );
1651 itMatch->first->multiHashCoeffs.resize( opts.
scales.size() );
1653 itMatch->second->multiScales.resize( opts.
scales.size() );
1654 itMatch->second->multiOrientations.resize( opts.
scales.size() );
1655 itMatch->second->descriptors.multiSIFTDescriptors.resize( opts.
scales.size() );
1656 itMatch->second->multiHashCoeffs.resize( opts.
scales.size() );
1659 memcpy( &itMatch->first->multiScales[0], &opts.
scales[0], opts.
scales.size()*
sizeof(double) );
1660 memcpy( &itMatch->second->multiScales[0], &opts.
scales[0], opts.
scales.size()*
sizeof(double) );
1661 tlogger.leave(
"cp scales");
1664 for(
unsigned int k = 0; k < opts.
scales.size(); ++k )
1667 npSize = npSize%2 ? npSize : npSize+1;
1673 tlogger.enter(
"extract & resize");
1674 smLeftImg.
extract_patch( tPatch, itMatch->first->x-hpSize, itMatch->first->y-hpSize, npSize, npSize );
1676 cv::Mat out_mat_patch;
1679 cv::resize( cv::cvarrToMat( tPatch.
getAs<IplImage>(),
false ), out_mat_patch, cv::Size(
a+2,
a+2) );
1680 IplImage aux_img = IplImage(out_mat_patch);
1681 CImage rsPatch( &aux_img );
1682 tlogger.leave(
"extract & resize");
1684 tlogger.enter(
"main orientations");
1690 rsPatch,
a/2+1,
a/2+1,
a,
1691 itMatch->first->multiOrientations[k], opts.
sg2 );
1692 tlogger.leave(
"main orientations");
1694 size_t nMainOris = itMatch->first->multiOrientations[k].size();
1695 itMatch->first->descriptors.multiSIFTDescriptors[k].resize( nMainOris );
1696 for(
unsigned int m = 0; m < nMainOris; ++m )
1698 tlogger.enter(
"compute histogram");
1702 itMatch->first->multiOrientations[k][m],
1703 itMatch->first->descriptors.multiSIFTDescriptors[k][m], opts,
1704 itMatch->first->multiHashCoeffs[k][m] );
1705 tlogger.leave(
"compute histogram");
1709 tlogger.enter(
"extract & resize");
1710 imageRight.
extract_patch( tPatch, itMatch->second->x-hpSize, itMatch->second->y-hpSize, npSize, npSize );
1712 cv::resize( cv::cvarrToMat( tPatch.
getAs<IplImage>(),
false), out_mat_patch, cv::Size(
a+2,
a+2) );
1713 IplImage aux_img2 = IplImage(out_mat_patch);
1714 CImage rsPatch2( &aux_img2 );
1715 tlogger.leave(
"extract & resize");
1717 tlogger.enter(
"main orientations");
1719 rsPatch2,
a/2+1,
a/2+1,
a,
1720 itMatch->second->multiOrientations[k], opts.
sg2 );
1721 tlogger.leave(
"main orientations");
1723 nMainOris = itMatch->second->multiOrientations[k].size();
1724 itMatch->second->descriptors.multiSIFTDescriptors[k].resize( nMainOris );
1726 for(
unsigned int m = 0; m < nMainOris; ++m )
1728 tlogger.enter(
"compute histogram");
1732 itMatch->second->multiOrientations[k][m],
1733 itMatch->second->descriptors.multiSIFTDescriptors[k][m], opts,
1734 itMatch->second->multiHashCoeffs[k][m] );
1735 tlogger.leave(
"compute histogram");
1754 #if MRPT_HAS_OPENCV && MRPT_OPENCV_VERSION_NUM>=0x211 1758 int maxScale = opts.
scales.size();
1759 int h =
image.getHeight();
1760 int w =
image.getWidth();
1764 largestSize = largestSize%2 ? largestSize : largestSize+1;
1765 int hLargestSize = largestSize/2;
1767 if( feat->x+hLargestSize > (
w-1) || feat->x-hLargestSize < 0 ||
1768 feat->y+hLargestSize > (h-1) || feat->y-hLargestSize < 0 )
1770 cout << endl <<
"[computeMultiResolutionDescriptors] WARNING: Feature is too close to the border. MultiDescriptor computation skipped." << endl;
1774 feat->multiScales.resize( maxScale );
1775 feat->multiOrientations.resize( maxScale );
1776 feat->descriptors.multiSIFTDescriptors.resize( maxScale );
1779 feat->multiHashCoeffs.resize( maxScale );
1782 for(
int k = 0; k < maxScale; ++k )
1783 feat->multiScales[k] = opts.
scales[k];
1786 for(
int k = 0; k < maxScale; ++k )
1789 npSize = npSize%2 ? npSize : npSize+1;
1792 CImage tPatch(npSize,npSize);
1798 image.extract_patch( tPatch, feat->x-hpSize, feat->y-hpSize, npSize, npSize );
1800 cv::Mat out_mat_patch;
1803 cv::resize( cv::cvarrToMat(tPatch.
getAs<IplImage>(),
false), out_mat_patch, cv::Size(
a+2,
a+2) );
1804 IplImage aux_img = IplImage(out_mat_patch);
1805 CImage rsPatch( &aux_img );
1812 rsPatch,
a/2+1,
a/2+1,
a,
1813 feat->multiOrientations[k], opts.
sg2 );
1815 size_t nMainOris = feat->multiOrientations[k].size();
1816 feat->descriptors.multiSIFTDescriptors[k].resize( nMainOris );
1818 feat->multiHashCoeffs[k].resize( nMainOris );
1820 for(
unsigned int m = 0; m < nMainOris; ++m )
1827 feat->multiOrientations[k][m],
1828 feat->descriptors.multiSIFTDescriptors[k][m],
1830 feat->multiHashCoeffs[k][m] );
1834 vector<int32_t> vec;
1838 feat->multiOrientations[k][m],
1839 feat->descriptors.multiSIFTDescriptors[k][m],
1860 #if MRPT_HAS_OPENCV && MRPT_OPENCV_VERSION_NUM>=0x211 1874 const cv::Mat inImg = cv::cvarrToMat(
image.getAs<IplImage>());
1876 cv::GaussianBlur( inImg, tempImg, cvSize(0,0), opts.
sg1 , opts.
sg1 );
1878 smLeftImg.loadFromIplImage( &aux );
1886 vector<bool> st( list.
size() );
1906 #if MRPT_HAS_OPENCV && MRPT_OPENCV_VERSION_NUM>=0x211 1915 tlogger.enter(
"smooth");
1919 const cv::Mat inImg1 = cv::cvarrToMat(
image.getAs<IplImage>(),
false);
1921 cv::GaussianBlur( inImg1, tempImg1, cvSize(0,0), opts.
sg1 , opts.
sg1 );
1923 CImage smLeftImg( &aux1 );
1929 largestSize = largestSize%2 ? largestSize : largestSize+1;
1930 int hLargestSize = largestSize/2;
1932 unsigned int npSize;
1933 unsigned int hpSize;
1938 if( (*it)->x+hLargestSize > smLeftImg.
getWidth()-1 || (*it)->x-hLargestSize < 0 ||
1939 (*it)->y+hLargestSize > smLeftImg.
getHeight()-1 || (*it)->y-hLargestSize < 0 )
1943 tlogger.enter(
"cp scales");
1944 (*it)->multiScales.resize( opts.
scales.size() );
1945 (*it)->multiOrientations.resize( opts.
scales.size() );
1948 memcpy( &(*it)->multiScales[0], &opts.
scales[0], opts.
scales.size()*
sizeof(double) );
1949 tlogger.leave(
"cp scales");
1952 for(
unsigned int k = 0; k < opts.
scales.size(); ++k )
1955 npSize = npSize%2 ? npSize : npSize+1;
1961 tlogger.enter(
"extract & resize");
1962 smLeftImg.
extract_patch( tPatch, (*it)->x-hpSize, (*it)->y-hpSize, npSize, npSize );
1964 cv::Mat out_mat_patch;
1967 cv::resize( cv::cvarrToMat(tPatch.
getAs<IplImage>(),
false), out_mat_patch, cv::Size(
a+2,
a+2) );
1968 IplImage aux_img = IplImage(out_mat_patch);
1969 CImage rsPatch( &aux_img );
1970 tlogger.leave(
"extract & resize");
1972 tlogger.enter(
"main orientations");
1978 rsPatch,
a/2+1,
a/2+1,
a,
1979 (*it)->multiOrientations[k], opts.
sg2 );
1980 tlogger.leave(
"main orientations");
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".
float getAsFloat(unsigned int col, unsigned int row, unsigned int channel) const
Returns the contents of a given pixel at the desired channel, in float format: [0,255]->[0,1] The coordinate origin is pixel(0,0)=top-left corner of the image.
FILE BASE_IMPEXP * fopen(const char *fileName, const char *mode) MRPT_NO_THROWS
An OS-independent version of fopen.
void VISION_IMPEXP setProperScales(const CFeaturePtr &feat1, const CFeaturePtr &feat2, int &firstScale, int &lastScale)
Computes the initial and final scales where to look when finding a match between multi-resolution fea...
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
bool VISION_IMPEXP computeMainOrientations(const mrpt::utils::CImage &image, const unsigned int x, const unsigned int y, const unsigned int patchSize, std::vector< double > &orientations, const double &sigma)
Computes the main orientations (within 80% of the peak value of orientation histogram) of a certain p...
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.
void VISION_IMPEXP computeMultiResolutionDescriptors(const mrpt::utils::CImage &imageLeft, const mrpt::utils::CImage &imageRight, CMatchedFeatureList &matchedFeats, const TMultiResDescOptions &opts)
Computes the multi-resolution SIFT-like descriptor of a set of matched features.
void BASE_IMPEXP pause(const std::string &msg=std::string("Press any key to continue...")) MRPT_NO_THROWS
Shows the message "Press any key to continue" (or other custom message) to the current standard outpu...
#define THROW_EXCEPTION(msg)
Struct containing the output after matching multi-resolution SIFT-like descriptors.
Column vector, like Eigen::MatrixX*, but automatically initialized to zeros since construction...
bool VISION_IMPEXP computeGradient(const mrpt::utils::CImage &image, const unsigned int x, const unsigned int y, double &mag, double &ori)
Computes the gradient of certain pixel within the image.
int BASE_IMPEXP fprintf(FILE *fil, const char *format,...) MRPT_NO_THROWS MRPT_printf_format_check(2
An OS-independent version of fprintf.
GLenum GLsizei GLenum GLenum const GLvoid * image
TInternalFeatList::const_iterator const_iterator
GLint GLint GLsizei GLsizei GLsizei depth
std::vector< int > secondListCorrespondences
Contains the indexes within the first list corresponding to the second one.
const Scalar * const_iterator
void kdTreeNClosestPoint2DIdx(float x0, float y0, size_t knn, std::vector< size_t > &out_idx, std::vector< float > &out_dist_sqr) const
KD Tree-based search for the N closest point to some given 2D coordinates and returns their indexes...
std::vector< double > firstListDistance
Contains the distances between the descriptors.
GLubyte GLubyte GLubyte GLubyte w
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.
void VISION_IMPEXP computeHistogramOfOrientations(const mrpt::utils::CImage &image, const unsigned int x, const unsigned int y, const unsigned int patchSize, const double &orientation, std::vector< int32_t > &descriptor, const TMultiResDescOptions &opts, std::vector< int32_t > &hashCoeffs)
Computes the SIFT-like descriptor of a certain point within an image at the base scale, i.e.
T square(const T x)
Inline function for the square of a number.
double baseline
Intrinsic stereo pair parameters for computing the depth of the feature.
bool computeHashCoeffs
Whether or not compute the coefficients for mantaining a HASH table of descriptors (for relocalizatio...
std::vector< int > firstListFoundScales
Contains the scales of the first list where the correspondence was found.
void getBothFeatureLists(CFeatureList &list1, CFeatureList &list2)
Returns the matching features as two separate CFeatureLists.
This base provides a set of functions for maths stuff.
uint32_t basePSize
The size of the base patch.
uint32_t timesSeenThreshold
The minimum number of frames for a certain feature to be considered stable.
uint32_t lastSeenThreshold
The allowed number of frames since a certain feature was seen for the last time.
bool useDepthFilter
Whether or not use the filter based on the depth test.
CONTAINER::Scalar sum(const CONTAINER &v)
Computes the sum of all the elements.
TMultiResMatchingOutput VISION_IMPEXP relocalizeMultiDesc(const mrpt::utils::CImage &image, CFeatureList &baseList, CFeatureList ¤tList, TQuantizationTable &qTable, const TMultiResDescOptions &desc_opts, const TMultiResDescMatchOptions &match_opts)
double sg3
The sigmas for the Gaussian kernels.
void VISION_IMPEXP interpolateHistEntry(std::vector< double > &hist, const double &cbin, const double &rbin, const double &obin, const double &mag, const int d, const int n)
Inserts the orientation value of a certain pixel within the keypoint neighbourhood into the histogram...
Classes for computer vision, detectors, features, etc.
std::vector< int > firstListCorrespondences
Contains the indexes within the second list corresponding to the first one.
uint64_t TFeatureID
Definition of a feature ID.
double cropValue
The SIFT-like descriptor is cropped at this value during normalization.
A list of visual features, to be used as output by detectors, as input/output by trackers, etc.
int VISION_IMPEXP computeMoreDescriptors(const mrpt::utils::CImage &image, const CFeaturePtr &inputFeat, CFeaturePtr &outputFeat, const bool &lowerScales, const TMultiResDescOptions &opts)
Computes more multi-resolution SIFT-like descriptors for a feature using its position in a new image...
uint32_t searchAreaSize
Size of the squared area where to search for a match.
std::vector< double > scales
The set of scales relatives to the base patch.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
bool computeDepth
Whether or not to compute the depth of the feature.
void VISION_IMPEXP insertHashCoeffs(const CFeaturePtr &feat, TQuantizationTable &qTable)
double oriThreshold
The threshold for the orientation test.
GLdouble GLdouble GLdouble r
void meanAndStd(const VECTORLIKE &v, double &out_mean, double &out_std, bool unbiased=true)
Computes the standard deviation of a vector.
Struct containing the options when computing the multi-resolution SIFT-like descriptors.
void VISION_IMPEXP updateBaseList(CFeatureList &baseList, const CFeatureList ¤tList, const std::vector< int > &idx)
void VISION_IMPEXP saveQTableToFile(const TQuantizationTable &qTable, const std::string &filename)
std::map< int, std::map< int, std::map< int, std::deque< std::pair< TFeatureID, double > > > > > TQuantizationTable
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)...
A versatile "profiler" that logs the time spent within each pair of calls to enter(X)-leave(X), among other stats.
int round(const T value)
Returns the closer integer (int) to x.
Struct containing the options when matching multi-resolution SIFT-like descriptors.
TInternalFeatList::iterator iterator
void VISION_IMPEXP checkScalesAndFindMore(CMatchedFeatureList &baseList, const CFeatureList ¤tList, const mrpt::utils::CImage ¤tImage, const TMultiResMatchingOutput &output, const TMultiResDescOptions &computeOpts, const TMultiResDescMatchOptions &matchOpts)
double matchingThreshold
The absolute threshold in descriptor distance for considering a match.
void VISION_IMPEXP computeMultiOrientations(const mrpt::utils::CImage &image, CFeatureList &list, const TMultiResDescOptions &opts)
Computes the multi-resolution SIFT-like descriptor of a list of features.
CFeaturePtr getByID(const TFeatureID &ID) const
Get a reference to a Feature from its ID.
bool blurImage
Whether or not to blur the image previously to compute the descriptors.
GLubyte GLubyte GLubyte a
void VISION_IMPEXP normalizeImage(const mrpt::utils::CImage &image, mrpt::utils::CImage &nimage)
Normalizes the brigthness and contrast of an image by setting its mean value to zero and its standard...
size_t getWidth() const MRPT_OVERRIDE
Returns the width of the image in pixels.
size_t getHeight() const MRPT_OVERRIDE
Returns the height of the image in pixels.
TMultiResMatchingOutput VISION_IMPEXP matchMultiResolutionFeatures(const CFeatureList &list1, CFeatureList &list2, const mrpt::utils::CImage &rightImage, const TMultiResDescMatchOptions &matchOpts, const TMultiResDescOptions &computeOpts)
Matches two CFeatureList containing mulit-resolution descriptors.