32 #include <mrpt/otherlibs/do_opencv_includes.h> 42 #ifdef MRPT_OS_WINDOWS 59 for (
int k = 0; k < int(feat->multiScales.size()); ++k)
61 for (
int m = 0; m < int(feat->multiOrientations[k].size()); ++m)
63 int key1 = feat->multiHashCoeffs[k][m][0];
64 int key2 = feat->multiHashCoeffs[k][m][1];
65 int key3 = feat->multiHashCoeffs[k][m][2];
68 if (qTable.find(key1) != qTable.end() &&
69 qTable[key1].find(key2) != qTable[key1].end() &&
70 qTable[key1][key2].find(key3) != qTable[key1][key2].end())
74 for (
int n = 0;
n < int(qTable[key1][key2][key3].
size()); ++
n)
76 TFeatureID thisID = qTable[key1][key2][key3][
n].first;
77 double thisScale = qTable[key1][key2][key3][
n].second;
78 if (thisID == feat->ID && thisScale == feat->multiScales[k])
87 qTable[key1][key2][key3].push_back(
88 make_pair(feat->ID, feat->multiScales[k]));
102 typedef map<int, map<int, map<int, deque<pair<TFeatureID, double>>>>>
109 for (it1 = qTable.begin(); it1 != qTable.end(); ++it1)
110 for (it2 = it1->second.begin(); it2 != it1->second.end(); ++it2)
111 for (it3 = it2->second.begin(); it3 != it2->second.end(); ++it3)
114 f,
"%d\t%d\t%d\t", it1->first, it2->first, it3->first);
115 for (
int k = 0; k < int(it3->second.size()); ++k)
118 static_cast<long unsigned int>(it3->second[k].first),
119 it3->second[k].second);
135 const bool PARAR =
false;
146 map<int, map<int, deque<pair<TFeatureID, double>>>>
::iterator it2;
147 map<int, deque<pair<TFeatureID, double>>>
::iterator it3;
149 vector<TFeatureID> vID;
153 int h =
image.getHeight();
155 map<TFeatureID, vector<double>> featsToCompareMap;
159 for (it = currentList.
begin(); it != currentList.
end(); ++it, ++curCounter)
161 if (PARAR && (*it)->ID == 193)
163 for (
int i = 0; i < (int)(*it)->multiScales.size(); ++i)
164 cout << (*it)->multiScales[i] << endl;
166 ASSERT_((*it)->multiHashCoeffs.size() == (*it)->multiScales.size());
173 featsToCompareMap.clear();
174 if (!(*it)->descriptors.hasDescriptorMultiSIFT())
176 cout <<
"[relocalizeMultiDesc] Feature " << (*it)->ID
177 <<
" in currentList hasn't got any descriptor." << endl;
183 if ((*it)->x + hpSize > (
w - 1) || (*it)->y + hpSize > (h - 1) ||
184 (*it)->x - hpSize < 0 || (*it)->y - hpSize < 0)
186 cout <<
"[relocalizeMultiDesc] WARNING: Feature too close to " 187 "the border. MultiDescriptor computation skipped." 194 for (
int k = 0; k < int((*it)->multiOrientations[0].size()); ++k)
198 int c1mn = (*it)->multiHashCoeffs[0][k][0] - TH;
199 int c1mx = (*it)->multiHashCoeffs[0][k][0] + TH;
201 int c2mn = (*it)->multiHashCoeffs[0][k][1] - TH;
202 int c2mx = (*it)->multiHashCoeffs[0][k][1] + TH;
204 int c3mn = (*it)->multiHashCoeffs[0][k][2] - TH;
205 int c3mx = (*it)->multiHashCoeffs[0][k][2] + TH;
207 for (
int m1 = c1mn; m1 < c1mx; ++m1)
209 it1 = qTable.find(m1);
210 if (it1 != qTable.end())
212 for (
int m2 = c2mn; m2 < c2mx; ++m2)
214 it2 = it1->second.find(m2);
215 if (it2 != it1->second.end())
217 for (
int m3 = c3mn; m3 < c3mx; ++m3)
219 it3 = it2->second.find(m3);
220 if (it3 != it2->second.end())
222 for (
int n = 0;
n < int(it3->second.size());
225 featsToCompareMap[qTable[m1][m2][m3]
228 qTable[m1][m2][m3][
n].second);
238 vID.resize(featsToCompareMap.size());
241 nit = featsToCompareMap.begin();
242 nit != featsToCompareMap.end(); ++nit, ++counter)
245 std::sort(nit->second.begin(), nit->second.end());
248 vit = std::unique(nit->second.begin(), nit->second.end());
250 nit->second.resize(vit - nit->second.begin());
253 vID[counter] = nit->first;
265 nit = featsToCompareMap.begin();
266 nit != featsToCompareMap.end(); ++nit, ++counter)
278 for (
int k1 = 0; k1 < int(baseFeat->multiScales.size()); ++k1)
281 for (
int k2 = 0; k2 < int(nit->second.size()); ++k2)
283 if (baseFeat->multiScales[k1] ==
289 int(baseFeat->multiOrientations[k1].size());
295 int((*it)->multiOrientations[0].size());
300 baseFeat->multiOrientations[k1]
302 (*it)->multiOrientations[0][k4]) >
324 int(baseFeat->descriptors
325 .multiSIFTDescriptors[k1][k3]
330 baseFeat->descriptors
331 .multiSIFTDescriptors[k1]
337 .multiSIFTDescriptors[0][k4]
364 minBaseFeat = baseIdx;
413 const vector<int>& idx)
418 size_t sz = idx.size();
422 for (
int k = 0; k < (int)sz; ++k)
426 baseList[k]->nTimesNotSeen++;
427 baseList[k]->nTimesLastSeen++;
431 baseList[k]->nTimesSeen++;
432 baseList[k]->nTimesLastSeen = 0;
435 dp[k] = fabs(baseList[k]->
depth - currentList[idx[k]]->
depth);
444 cout <<
"mean&std: " << m_dp <<
"," << std_dp << endl;
446 for (
int k = 0; k < (int)idx.size(); ++k)
451 if (dp[k] < (m_dp + std_dp))
453 baseList[k]->x = currentList[idx[k]]->x;
454 baseList[k]->y = currentList[idx[k]]->y;
455 baseList[k]->p3D = currentList[idx[k]]->p3D;
481 for (itBase = baseList.begin(); itBase != baseList.end(); ++m)
492 itBase = baseList.erase(itBase);
516 cout <<
"Left feature " << m <<
" found in scale 0!" 522 currentImage, currentList[tidx], itBase->first,
true,
525 itBase->first->descriptors.hasDescriptorMultiSIFT());
527 cout <<
"LF LOWSCALES Out of bounds!!" << endl;
532 size_t nscales = itBase->first->multiScales.size() - 1;
536 cout <<
"Left feature " << m <<
" found in last scale!" 539 currentImage, currentList[tidx], itBase->first,
542 cout <<
"LF HIGHSCALES Out of bounds!!" << endl;
561 const CImage&
image,
const unsigned int x,
const unsigned int y,
562 double& mag,
double& ori)
564 if (
x > 0 &&
x <
image.getWidth() - 1 &&
y > 0 &&
y <
image.getHeight() - 1)
580 mag = sqrt(d1 * d1 + d2 * d2);
586 cout <<
"[computeGradient]: Out of bounds in " <<
x <<
"," <<
y 587 <<
" with image: " <<
image.getWidth() <<
"x" <<
image.getHeight()
601 const CImage&
image,
const unsigned int x,
const unsigned int y,
602 const unsigned int patchSize, std::vector<double>& orientations,
608 orientations.clear();
611 const unsigned int NBINS = 36;
612 const int hPatchSize = patchSize / 2;
614 vector<double> oris(NBINS, 0.0);
615 int mx = (int)
x, my = (
int)
y;
618 if (mx - (hPatchSize + 1) < 0 || my - (hPatchSize + 1) < 0 ||
619 mx + (hPatchSize + 1) > (int)(
image.getWidth() - 1) ||
620 my + (hPatchSize + 1) > (int)(
image.getHeight() - 1))
629 double exp_denom = 2.0 * sigma * sigma;
630 double bin_size =
M_2PI / NBINS;
632 for (
int ii = -hPatchSize; ii <= hPatchSize; ++ii)
633 for (
int jj = -hPatchSize; jj <= hPatchSize; ++jj)
638 double w = mag * exp(-(ii * ii + jj * jj) / exp_denom);
641 ((int)(floor(ori / bin_size))) % NBINS;
642 double bin_center = bin * bin_size;
643 double dif = ori - bin_center;
652 nxbin = bin == 0 ? NBINS - 1 : bin - 1;
656 double nbin_center = nxbin * bin_size;
657 double dif2 = ori - nbin_center;
659 oris[bin] +=
w * fabs(dif2) / bin_size;
662 oris[nxbin] +=
w * fabs(dif) / bin_size;
671 for (
unsigned int k = 0; k < oris.size(); ++k)
680 double hist_mag_th = 0.8 * mxori;
681 for (
unsigned int k = 0; k < oris.size(); ++k)
683 double pv = k == 0 ? oris[oris.size() - 1]
685 double nv = k == oris.size() - 1
689 if (oris[k] > pv && oris[k] > nv &&
690 oris[k] > hist_mag_th)
700 0.5 * (pv - nv) / (pv - 2.0 * oris[k] + nv);
701 int_bin = (int_bin < 0) ? NBINS + int_bin : (int_bin >= NBINS)
706 orientations.push_back(int_ori);
719 vector<double>& oris,
const double& cbin,
const double& rbin,
720 const double& obin,
const double& mag,
const int d,
const int n)
730 double ncbin = cbin + d / 2. - 0.5;
731 double nrbin = rbin + d / 2. - 0.5;
733 int ncbin_i = floor(ncbin);
734 int nrbin_i = floor(nrbin);
735 int nobin_i = floor(obin);
737 double d_c = ncbin_i - ncbin;
738 double d_r = nrbin_i - nrbin;
739 double d_o = nobin_i - obin;
741 for (
int k = 0; k < 2; ++k)
742 for (
int m = 0; m < 2; ++m)
743 for (
int l = 0; l < 2; ++l)
744 if (ncbin_i + k >= 0 && ncbin_i + k < d && nrbin_i + m >= 0 &&
747 int idx = ((nobin_i + l) %
n) +
n * (ncbin_i + k) +
748 n * d * (nrbin_i + m);
749 oris[idx] += mag * (1 - fabs(d_c + k)) *
750 (1 - fabs(d_r + m)) * (1 - fabs(d_o + l));
822 const CImage&
image,
const unsigned int x,
const unsigned int y,
823 const unsigned int patchSize,
const double& orientation,
825 vector<int32_t>& hashCoeffs)
836 double cos_t = cos(orientation);
837 double sin_t = sin(orientation);
838 double bins_per_rad =
n /
M_2PI;
839 double exp_denom = opts.
sg3 * opts.
sg3 * 2;
840 int radius = 0.5 * patchSize;
841 vector<double> oris(Bp * Bp *
n, 0.0);
848 thePatch,
x - radius,
y - radius, patchSize, patchSize);
866 double cbin, rbin, obin;
867 double c1 = 0.0, c2 = 0.0, c3 = 0.0;
881 for (
int c = -radius;
c <= radius; ++
c)
882 for (
int r = -radius;
r <= radius; ++
r)
884 cbin = kp *
c * cos_t - kp *
r * sin_t;
885 rbin = kp *
c * sin_t + kp *
r * cos_t;
887 if (cbin > -2.5 && cbin < 2.5 && rbin > -2.5 && rbin < 2.5)
889 tlogger.enter(
"computeGradient");
892 tlogger.leave(
"computeGradient");
896 while (ori < 0.0) ori +=
M_2PI;
899 obin = ori * bins_per_rad;
900 w = exp(-(
c *
c +
r *
r) / exp_denom);
901 tlogger.enter(
"interpolate");
903 oris, cbin, rbin, obin, mag, Bp,
n);
904 tlogger.leave(
"interpolate");
949 if ((cbin < 0 && rbin < 0) || (cbin > 0 && rbin > 0))
983 hashCoeffs.resize(3);
984 hashCoeffs[0] =
round(c1);
985 hashCoeffs[1] =
round(c2);
986 hashCoeffs[2] =
round(c3);
992 tlogger.enter(
"normalize");
994 for (
unsigned int ii = 0; ii < oris.size(); ++ii)
995 sum += oris[ii] * oris[ii];
997 for (
unsigned int ii = 0; ii < oris.size(); ++ii) oris[ii] *=
sum;
1000 for (
unsigned int ii = 0; ii < oris.size(); ++ii)
1004 for (
unsigned int ii = 0; ii < oris.size(); ++ii)
1005 sum += oris[ii] * oris[ii];
1007 for (
unsigned int ii = 0; ii < oris.size(); ++ii) oris[ii] *=
sum;
1010 descriptor.resize(oris.size());
1011 for (
unsigned int ii = 0; ii < descriptor.size(); ++ii)
1012 descriptor[ii] = (
int)(255.0f * oris[ii]);
1014 tlogger.leave(
"normalize");
1065 int imageW = rightImage.
getWidth();
1067 int leftFeatCounter = 0;
1068 int rightFeatCounter = 0;
1079 for (leftFeatCounter = 0, it1 = list1.
begin(); it1 != list1.
end();
1080 ++it1, ++leftFeatCounter)
1082 if (!(*it1)->descriptors.hasDescriptorMultiSIFT())
continue;
1085 max((*it1)->x -
min((hWindow + 2 * (*it1)->nTimesLastSeen), mxsize),
1088 min((*it1)->x +
min((hWindow + 2 * (*it1)->nTimesLastSeen), mxsize),
1091 max((*it1)->y -
min((hWindow + 2 * (*it1)->nTimesLastSeen), mxsize),
1094 min((*it1)->y +
min((hWindow + 2 * (*it1)->nTimesLastSeen), mxsize),
1103 for (rightFeatCounter = 0, it2 = list2.
begin(); it2 != list2.
end();
1104 ++it2, ++rightFeatCounter)
1114 if ((*it2)->x < sRegionX0 || (*it2)->x > sRegionX1 ||
1115 (*it2)->y < sRegionY0 || (*it2)->y > sRegionY1)
1132 vector<double> thisOris;
1134 rightImage, (*it2)->x, (*it2)->y, patchSize, thisOris,
1148 int firstScale, lastScale;
1153 firstScale = max(0, (
int)matchOpts.
lowScl1);
1155 min((
int)(*it1)->multiScales.size() - 1,
1167 for (
int k1 = firstScale; k1 <= lastScale; ++k1)
1168 for (
int k2 = 0; k2 < (int)(*it1)->multiOrientations[k1].size();
1170 for (
int k3 = 0; k3 < (int)thisOris.size();
1173 (*it1)->multiOrientations[k1][k2] -
1177 (*it1)->multiOrientations[k1][k2] -
1188 if (list2.
size() >= 8)
1190 std::vector<size_t> out_idx;
1191 std::vector<float> out_dist_sqr;
1192 maxResponse = (*it2)->response;
1195 (*it2)->x, (*it2)->y, 8, out_idx,
1197 for (
size_t kdcounter = 0;
1198 kdcounter < out_idx.size(); ++kdcounter)
1200 if (out_dist_sqr[kdcounter] > 1.4142)
1203 if (list2[out_idx[kdcounter]]->response >
1207 list2[out_idx[kdcounter]]->response;
1216 cout <<
"NO ES MAX" << endl;
1236 if ((*it2)->multiScales.size() == 0)
1238 (*it2)->multiScales.resize(1);
1239 (*it2)->multiScales[0] = 1.0;
1240 (*it2)->multiOrientations.resize(1);
1241 (*it2)->descriptors.multiSIFTDescriptors.resize(
1243 (*it2)->multiHashCoeffs.resize(1);
1247 bool oriFound =
false;
1250 co < (int)(*it2)->multiOrientations[0].size();
1252 if ((*it2)->multiOrientations[0][co] ==
1274 (*it2)->multiOrientations[0].push_back(
1277 vector<int32_t> thisDesc, thisHash;
1279 rightImage, (*it2)->x, (*it2)->y, patchSize,
1280 thisOris[k3], thisDesc, computeOpts,
1285 ->descriptors.multiSIFTDescriptors[0]
1286 .push_back(thisDesc);
1288 (*it2)->multiHashCoeffs[0].push_back(thisHash);
1290 for (
int n = 0;
n < int(thisDesc.size());
n++)
1294 .multiSIFTDescriptors[k1][k2][
n] -
1310 .multiSIFTDescriptors[0][wh]
1316 .multiSIFTDescriptors[k1][k2][
n] -
1319 .multiSIFTDescriptors[0][wh][
n]);
1333 ridx = rightFeatCounter;
1334 maxResponse = (*it2)->response;
1458 ASSERT_(mList1.size() > 0 && mList2.size() > 0);
1466 vector<int> scales1, scales2;
1472 baseList1, auxList1, leftImage, matchOpts, computeOpts);
1474 baseList1, auxList1,
1496 baseList2, auxList2, rightImage, matchOpts, computeOpts);
1498 baseList2, auxList2,
1517 cout <<
"Left matches: " << output1.
nMatches <<
" out of " 1518 << baseList1.size() <<
"," << auxList1.
size() << endl;
1519 cout <<
"Right matches: " << output2.
nMatches <<
" out of " 1520 << baseList2.size() <<
"," << auxList2.
size() << endl;
1521 cout <<
"Matched list: " << mList1.size() << endl;
1533 for (m = 0, itMatch = mList1.begin(); itMatch != mList1.end(); ++m)
1541 itMatch = mList1.erase(itMatch);
1550 if (scales1[m] == 0)
1552 cout <<
"Left feature " << m <<
" found in scale 0!" 1555 leftImage, auxList1[tidx], itMatch->first,
true,
1558 cout <<
"LF LOWSCALES Out of bounds!!" << endl;
1563 int nScales = (int)itMatch->first->multiScales.size();
1564 if (scales1[m] == nScales - 1)
1566 cout <<
"Left feature " << m <<
" found in last scale!" 1569 cout <<
"tidx=" << tidx << endl;
1571 leftImage, auxList1[tidx], itMatch->first,
false,
1574 cout <<
"LF HIGHSCALES Out of bounds!!" << endl;
1588 if (scales2[m] == 0)
1590 cout <<
"Right feature " << m <<
" found in scale 0!" 1594 rightImage, auxList2[tidx], itMatch->second,
true,
1597 cout <<
"RF LOWSCALES Out of bounds!!" << endl;
1602 int nScales = (int)itMatch->second->multiScales.size();
1603 if (scales2[m] == nScales - 1)
1605 cout <<
"Right feature " << m <<
" found in scale!" 1609 rightImage, auxList2[tidx], itMatch->second,
false,
1612 cout <<
"RF HIGHSCALES Out of bounds!!" << endl;
1621 return mList1.size();
1633 #if MRPT_HAS_OPENCV && MRPT_OPENCV_VERSION_NUM >= 0x211 1642 const cv::Mat inImg1 =
1643 cv::cvarrToMat(
image.getAs<IplImage>(),
false );
1646 inImg1, tempImg1, cvSize(0, 0), opts.
sg1 ,
1654 int largestSize = lowerScales ?
round(
a * 0.8) :
round(
a * 2.0);
1655 largestSize = largestSize % 2
1658 int hLargestSize = largestSize / 2;
1660 unsigned int npSize, hpSize;
1664 if (inputFeat->x + hLargestSize > smLeftImg.
getWidth() - 1 ||
1665 inputFeat->x - hLargestSize < 0 ||
1666 inputFeat->y + hLargestSize > smLeftImg.
getHeight() - 1 ||
1667 inputFeat->y - hLargestSize < 0)
1673 vector<double> thisScales(2);
1674 thisScales[0] = 0.5;
1675 thisScales[1] = 0.8;
1677 double baseScale = outputFeat->multiScales[0];
1680 outputFeat->multiScales.push_front(thisScales[1] * baseScale);
1681 outputFeat->multiScales.push_front(thisScales[0] * baseScale);
1686 for (
int k = 1; k >= 0; --k)
1688 npSize =
round(
a * thisScales[k]);
1692 hpSize = npSize / 2;
1698 tPatch, inputFeat->x - hpSize, inputFeat->y - hpSize,
1701 cv::Mat out_mat_patch;
1708 cv::cvarrToMat(tPatch.
getAs<IplImage>(),
false), out_mat_patch,
1709 cv::Size(
a + 2,
a + 2));
1710 IplImage aux_img = IplImage(out_mat_patch);
1711 CImage rsPatch(&aux_img);
1714 vector<double> auxOriVector;
1716 rsPatch,
a / 2 + 1,
a / 2 + 1,
a, auxOriVector, opts.
sg2))
1718 cout <<
"computeMainOrientations returned false" << endl;
1723 vector<vector<int32_t>> auxDescVector;
1724 vector<vector<int32_t>> auxHashCoeffs;
1725 auxDescVector.resize(auxOriVector.size());
1726 auxHashCoeffs.resize(auxOriVector.size());
1727 for (
unsigned int m = 0; m < auxOriVector.size(); ++m)
1732 rsPatch,
a / 2 + 1,
a / 2 + 1,
a, auxOriVector[m],
1733 auxDescVector[m], opts, auxHashCoeffs[m]);
1736 outputFeat->multiOrientations.push_front(auxOriVector);
1737 outputFeat->descriptors.multiSIFTDescriptors.push_front(
1739 outputFeat->multiHashCoeffs.push_front(auxHashCoeffs);
1745 vector<double> thisScales(4);
1746 thisScales[0] = 1.2;
1747 thisScales[1] = 1.5;
1748 thisScales[2] = 1.8;
1749 thisScales[3] = 2.0;
1751 size_t nCurrScales = outputFeat->multiScales.size();
1752 outputFeat->multiScales.push_back(
1753 thisScales[0] * outputFeat->multiScales[nCurrScales - 1]);
1754 outputFeat->multiScales.push_back(
1755 thisScales[1] * outputFeat->multiScales[nCurrScales - 1]);
1756 outputFeat->multiScales.push_back(
1757 thisScales[2] * outputFeat->multiScales[nCurrScales - 1]);
1758 outputFeat->multiScales.push_back(
1759 thisScales[3] * outputFeat->multiScales[nCurrScales - 1]);
1763 for (
int k = 0; k < (int)thisScales.size(); ++k)
1767 npSize =
round(
a * thisScales[k]);
1771 hpSize = npSize / 2;
1777 tPatch, inputFeat->x - hpSize, inputFeat->y - hpSize, npSize,
1780 cv::Mat out_mat_patch;
1787 cv::cvarrToMat(tPatch.
getAs<IplImage>(),
false), out_mat_patch,
1788 cv::Size(
a + 2,
a + 2));
1789 IplImage aux_img = IplImage(out_mat_patch);
1790 CImage rsPatch(&aux_img);
1794 vector<double> auxOriVector;
1796 rsPatch,
a / 2 + 1,
a / 2 + 1,
a, auxOriVector, opts.
sg2);
1800 vector<vector<int32_t>> auxDescVector;
1801 vector<vector<int32_t>> auxCoefVector;
1802 auxDescVector.resize(auxOriVector.size());
1803 auxCoefVector.resize(auxOriVector.size());
1804 for (
unsigned int m = 0; m < auxOriVector.size(); ++m)
1809 rsPatch,
a / 2 + 1,
a / 2 + 1,
a, auxOriVector[m],
1810 auxDescVector[m], opts, auxCoefVector[m]);
1813 outputFeat->multiOrientations.push_back(auxOriVector);
1814 outputFeat->descriptors.multiSIFTDescriptors.push_back(
1816 outputFeat->multiHashCoeffs.push_back(auxCoefVector);
1819 ASSERT_(outputFeat->descriptors.hasDescriptorMultiSIFT());
1841 int numScales = int(feat1->multiScales.size());
1851 lastScale = numScales - 1;
1855 (feat2->depth - 0.15 * feat1->initialDepth) / feat1->initialDepth;
1857 (feat2->depth + 0.15 * feat1->initialDepth) / feat1->initialDepth;
1859 if (smin <= feat1->multiScales[1])
1863 if (smin > feat1->multiScales[numScales - 2])
1864 firstScale = numScales - 2;
1867 for (
int k = 1; k <= numScales - 3; ++k)
1868 if (smin > feat1->multiScales[k]) firstScale = k;
1872 if (smax <= feat1->multiScales[1])
1876 if (smax > feat1->multiScales[numScales - 2])
1877 lastScale = numScales - 1;
1880 for (
int k = 1; k <= numScales - 3; ++k)
1881 if (smax <= feat1->multiScales[k])
1889 ASSERT_(firstScale >= 0 && lastScale < numScales && firstScale < lastScale);
1900 #if MRPT_HAS_OPENCV && MRPT_OPENCV_VERSION_NUM >= 0x211 1905 ASSERT_(matchedFeats.size() > 0);
1910 tlogger.enter(
"smooth");
1911 cv::Mat tempImg1, tempImg2;
1912 IplImage aux1, aux2;
1914 const cv::Mat inImg1 = cv::cvarrToMat(imageLeft.
getAs<IplImage>());
1915 const cv::Mat inImg2 = cv::cvarrToMat(imageRight.
getAs<IplImage>());
1918 inImg1, tempImg1, cvSize(0, 0), opts.
sg1 ,
1924 inImg2, tempImg2, cvSize(0, 0), opts.
sg1 ,
1927 CImage smRightImg(&aux2);
1928 tlogger.leave(
"smooth");
1932 unsigned int feat_counter = 0;
1933 unsigned int good_matches = 0;
1936 largestSize = largestSize % 2
1939 int hLargestSize = largestSize / 2;
1941 unsigned int npSize;
1942 unsigned int hpSize;
1945 itMatch != matchedFeats.end(); ++itMatch, ++feat_counter)
1949 if (itMatch->first->x + hLargestSize > smLeftImg.
getWidth() - 1 ||
1950 itMatch->first->x - hLargestSize < 0 ||
1951 itMatch->first->y + hLargestSize > smLeftImg.
getHeight() - 1 ||
1952 itMatch->first->y - hLargestSize < 0 ||
1953 itMatch->second->x + hLargestSize > smRightImg.
getWidth() - 1 ||
1954 itMatch->second->x - hLargestSize < 0 ||
1955 itMatch->second->y + hLargestSize > smRightImg.
getHeight() - 1 ||
1956 itMatch->second->y - hLargestSize < 0)
1961 tlogger.enter(
"compute depth");
1964 double disp = itMatch->first->x - itMatch->second->x;
1966 double x3D = (itMatch->first->x - opts.
cx) * aux;
1967 double y3D = (itMatch->first->y - opts.
cy) * aux;
1968 double z3D = opts.
fx * aux;
1970 itMatch->first->depth = sqrt(x3D * x3D + y3D * y3D + z3D * z3D);
1971 itMatch->second->depth = sqrt(
1975 tlogger.leave(
"compute depth");
1977 tlogger.enter(
"cp scales");
1978 itMatch->first->multiScales.resize(opts.
scales.size());
1979 itMatch->first->multiOrientations.resize(opts.
scales.size());
1980 itMatch->first->descriptors.multiSIFTDescriptors.resize(
1982 itMatch->first->multiHashCoeffs.resize(opts.
scales.size());
1984 itMatch->second->multiScales.resize(opts.
scales.size());
1985 itMatch->second->multiOrientations.resize(opts.
scales.size());
1986 itMatch->second->descriptors.multiSIFTDescriptors.resize(
1988 itMatch->second->multiHashCoeffs.resize(opts.
scales.size());
1992 &itMatch->first->multiScales[0], &opts.
scales[0],
1993 opts.
scales.size() *
sizeof(double));
1995 &itMatch->second->multiScales[0], &opts.
scales[0],
1996 opts.
scales.size() *
sizeof(double));
1997 tlogger.leave(
"cp scales");
2000 for (
unsigned int k = 0; k < opts.
scales.size(); ++k)
2006 hpSize = npSize / 2;
2011 tlogger.enter(
"extract & resize");
2013 tPatch, itMatch->first->x - hpSize, itMatch->first->y - hpSize,
2016 cv::Mat out_mat_patch;
2023 cv::cvarrToMat(tPatch.
getAs<IplImage>(),
false), out_mat_patch,
2024 cv::Size(
a + 2,
a + 2));
2025 IplImage aux_img = IplImage(out_mat_patch);
2026 CImage rsPatch(&aux_img);
2027 tlogger.leave(
"extract & resize");
2029 tlogger.enter(
"main orientations");
2038 rsPatch,
a / 2 + 1,
a / 2 + 1,
a,
2039 itMatch->first->multiOrientations[k], opts.
sg2);
2040 tlogger.leave(
"main orientations");
2042 size_t nMainOris = itMatch->first->multiOrientations[k].size();
2043 itMatch->first->descriptors.multiSIFTDescriptors[k].resize(
2045 for (
unsigned int m = 0; m < nMainOris; ++m)
2047 tlogger.enter(
"compute histogram");
2049 rsPatch,
a / 2 + 1,
a / 2 + 1,
a,
2050 itMatch->first->multiOrientations[k][m],
2051 itMatch->first->descriptors.multiSIFTDescriptors[k][m],
2052 opts, itMatch->first->multiHashCoeffs[k][m]);
2053 tlogger.leave(
"compute histogram");
2057 tlogger.enter(
"extract & resize");
2059 tPatch, itMatch->second->x - hpSize,
2060 itMatch->second->y - hpSize, npSize, npSize);
2063 cv::cvarrToMat(tPatch.
getAs<IplImage>(),
false), out_mat_patch,
2064 cv::Size(
a + 2,
a + 2));
2065 IplImage aux_img2 = IplImage(out_mat_patch);
2066 CImage rsPatch2(&aux_img2);
2067 tlogger.leave(
"extract & resize");
2069 tlogger.enter(
"main orientations");
2071 rsPatch2,
a / 2 + 1,
a / 2 + 1,
a,
2072 itMatch->second->multiOrientations[k], opts.
sg2);
2073 tlogger.leave(
"main orientations");
2075 nMainOris = itMatch->second->multiOrientations[k].size();
2076 itMatch->second->descriptors.multiSIFTDescriptors[k].resize(
2079 for (
unsigned int m = 0; m < nMainOris; ++m)
2081 tlogger.enter(
"compute histogram");
2083 rsPatch2,
a / 2 + 1,
a / 2 + 1,
a,
2084 itMatch->second->multiOrientations[k][m],
2085 itMatch->second->descriptors.multiSIFTDescriptors[k][m],
2086 opts, itMatch->second->multiHashCoeffs[k][m]);
2087 tlogger.leave(
"compute histogram");
2104 #if MRPT_HAS_OPENCV && MRPT_OPENCV_VERSION_NUM >= 0x211 2108 int maxScale = opts.
scales.size();
2109 int h =
image.getHeight();
2110 int w =
image.getWidth();
2113 int largestSize =
round(
a * opts.
scales[maxScale - 1]);
2114 largestSize = largestSize % 2
2117 int hLargestSize = largestSize / 2;
2119 if (feat->x + hLargestSize > (
w - 1) || feat->x - hLargestSize < 0 ||
2120 feat->y + hLargestSize > (h - 1) || feat->y - hLargestSize < 0)
2123 <<
"[computeMultiResolutionDescriptors] WARNING: Feature is too " 2124 "close to the border. MultiDescriptor computation skipped." 2129 feat->multiScales.resize(maxScale);
2130 feat->multiOrientations.resize(maxScale);
2131 feat->descriptors.multiSIFTDescriptors.resize(maxScale);
2136 for (
int k = 0; k < maxScale; ++k) feat->multiScales[k] = opts.
scales[k];
2139 for (
int k = 0; k < maxScale; ++k)
2142 npSize = npSize % 2 ? npSize
2144 hpSize = npSize / 2;
2146 CImage tPatch(npSize, npSize);
2156 image.extract_patch(
2157 tPatch, feat->x - hpSize, feat->y - hpSize, npSize, npSize);
2159 cv::Mat out_mat_patch;
2166 cv::cvarrToMat(tPatch.
getAs<IplImage>(),
false), out_mat_patch,
2167 cv::Size(
a + 2,
a + 2));
2168 IplImage aux_img = IplImage(out_mat_patch);
2169 CImage rsPatch(&aux_img);
2179 rsPatch,
a / 2 + 1,
a / 2 + 1,
a, feat->multiOrientations[k],
2182 size_t nMainOris = feat->multiOrientations[k].size();
2183 feat->descriptors.multiSIFTDescriptors[k].resize(nMainOris);
2186 for (
unsigned int m = 0; m < nMainOris; ++m)
2191 rsPatch,
a / 2 + 1,
a / 2 + 1,
a,
2192 feat->multiOrientations[k][m],
2193 feat->descriptors.multiSIFTDescriptors[k][m], opts,
2194 feat->multiHashCoeffs[k][m]);
2198 vector<int32_t> vec;
2200 rsPatch,
a / 2 + 1,
a / 2 + 1,
a,
2201 feat->multiOrientations[k][m],
2202 feat->descriptors.multiSIFTDescriptors[k][m], opts, vec);
2219 #if MRPT_HAS_OPENCV && MRPT_OPENCV_VERSION_NUM >= 0x211 2233 const cv::Mat inImg = cv::cvarrToMat(
image.getAs<IplImage>());
2236 inImg, tempImg, cvSize(0, 0), opts.
sg1 ,
2239 smLeftImg.loadFromIplImage(&aux);
2247 vector<bool> st(list.
size());
2265 #if MRPT_HAS_OPENCV && MRPT_OPENCV_VERSION_NUM >= 0x211 2274 tlogger.enter(
"smooth");
2278 const cv::Mat inImg1 = cv::cvarrToMat(
image.getAs<IplImage>(),
false);
2281 inImg1, tempImg1, cvSize(0, 0), opts.
sg1 ,
2290 largestSize = largestSize % 2
2293 int hLargestSize = largestSize / 2;
2295 unsigned int npSize;
2296 unsigned int hpSize;
2302 if ((*it)->x + hLargestSize > smLeftImg.
getWidth() - 1 ||
2303 (*it)->x - hLargestSize < 0 ||
2304 (*it)->y + hLargestSize > smLeftImg.
getHeight() - 1 ||
2305 (*it)->y - hLargestSize < 0)
2309 tlogger.enter(
"cp scales");
2310 (*it)->multiScales.resize(opts.
scales.size());
2311 (*it)->multiOrientations.resize(opts.
scales.size());
2315 &(*it)->multiScales[0], &opts.
scales[0],
2316 opts.
scales.size() *
sizeof(double));
2317 tlogger.leave(
"cp scales");
2320 for (
unsigned int k = 0; k < opts.
scales.size(); ++k)
2326 hpSize = npSize / 2;
2331 tlogger.enter(
"extract & resize");
2333 tPatch, (*it)->x - hpSize, (*it)->y - hpSize, npSize, npSize);
2335 cv::Mat out_mat_patch;
2342 cv::cvarrToMat(tPatch.
getAs<IplImage>(),
false), out_mat_patch,
2343 cv::Size(
a + 2,
a + 2));
2344 IplImage aux_img = IplImage(out_mat_patch);
2345 CImage rsPatch(&aux_img);
2346 tlogger.leave(
"extract & resize");
2348 tlogger.enter(
"main orientations");
2357 rsPatch,
a / 2 + 1,
a / 2 + 1,
a, (*it)->multiOrientations[k],
2359 tlogger.leave(
"main orientations");
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.
std::shared_ptr< CFeature > Ptr
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
bool 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 void fclose(FILE *f)
An OS-independent version of fclose.
A class for storing images as grayscale or RGB bitmaps.
void 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.
#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 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.
void setProperScales(const CFeature::Ptr &feat1, const CFeature::Ptr &feat2, int &firstScale, int &lastScale)
Computes the initial and final scales where to look when finding a match between multi-resolution fea...
GLenum GLsizei GLenum GLenum const GLvoid * image
for(ctr=DCTSIZE;ctr > 0;ctr--)
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
uint32_t highScl1
The highest scales in the two features to be taken into account in the matching process.
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 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.
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.
size_t getWidth() const override
Returns the width of the image in pixels.
uint32_t basePSize
The size of the base patch.
double sg1
The sigmas for the Gaussian kernels.
uint32_t timesSeenThreshold
The minimum number of frames for a certain feature to be considered stable.
int computeMoreDescriptors(const mrpt::utils::CImage &image, const CFeature::Ptr &inputFeat, CFeature::Ptr &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 lastSeenThreshold
The allowed number of frames since a certain feature was seen for the last time.
std::map< int, std::map< int, std::map< int, std::deque< std::pair< TFeatureID, double > > > > > TQuantizationTable
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.
size_t getHeight() const override
Returns the height of the image in pixels.
TMultiResMatchingOutput relocalizeMultiDesc(const mrpt::utils::CImage &image, CFeatureList &baseList, CFeatureList ¤tList, TQuantizationTable &qTable, const TMultiResDescOptions &desc_opts, const TMultiResDescMatchOptions &match_opts)
void 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.
void insertHashCoeffs(const CFeature::Ptr &feat, TQuantizationTable &qTable)
int fprintf(FILE *fil, const char *format,...) noexcept MRPT_printf_format_check(2
An OS-independent version of fprintf.
void pause(const std::string &msg=std::string("Press any key to continue...")) noexcept
Shows the message "Press any key to continue" (or other custom message) to the current standard outpu...
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.
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.
uint32_t lowScl1
The lowest scales in the two features to be taken into account in the matching process.
Struct containing the options when computing the multi-resolution SIFT-like descriptors.
void updateBaseList(CFeatureList &baseList, const CFeatureList ¤tList, const std::vector< int > &idx)
void saveQTableToFile(const TQuantizationTable &qTable, const std::string &filename)
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 checkScalesAndFindMore(CMatchedFeatureList &baseList, const CFeatureList ¤tList, const mrpt::utils::CImage ¤tImage, const TMultiResMatchingOutput &output, const TMultiResDescOptions &computeOpts, const TMultiResDescMatchOptions &matchOpts)
FILE * fopen(const char *fileName, const char *mode) noexcept
An OS-independent version of fopen.
double matchingThreshold
The absolute threshold in descriptor distance for considering a match.
void computeMultiOrientations(const mrpt::utils::CImage &image, CFeatureList &list, const TMultiResDescOptions &opts)
Computes the multi-resolution SIFT-like descriptor of a list of features.
bool blurImage
Whether or not to blur the image previously to compute the descriptors.
GLubyte GLubyte GLubyte a
void 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...
CFeature::Ptr getByID(const TFeatureID &ID) const
Get a reference to a Feature from its ID.
double fx
Intrinsic stereo pair parameters for computing the depth of the feature.
void memcpy(void *dest, size_t destSize, const void *src, size_t copyCount) noexcept
An OS and compiler independent version of "memcpy".
TMultiResMatchingOutput matchMultiResolutionFeatures(const CFeatureList &list1, CFeatureList &list2, const mrpt::utils::CImage &rightImage, const TMultiResDescMatchOptions &matchOpts, const TMultiResDescOptions &computeOpts)
Matches two CFeatureList containing mulit-resolution descriptors.