32 #include <mrpt/otherlibs/do_opencv_includes.h>
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]));
103 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][
n]
228 qTable[m1][m2][m3][
n].second);
238 vID.resize(featsToCompareMap.size());
241 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());
265 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());
301 ->multiOrientations[k1][k3] -
302 (*it)->multiOrientations[0][k4]) >
324 int(baseFeat->descriptors
325 .multiSIFTDescriptors[k1][k3]
329 float(baseFeat->descriptors
330 .multiSIFTDescriptors
335 .multiSIFTDescriptors[0][k4]
362 minBaseFeat = baseIdx;
411 const vector<int>& idx)
416 size_t sz = idx.size();
420 for (
int k = 0; k < (int)sz; ++k)
424 baseList[k]->nTimesNotSeen++;
425 baseList[k]->nTimesLastSeen++;
429 baseList[k]->nTimesSeen++;
430 baseList[k]->nTimesLastSeen = 0;
433 dp[k] = fabs(baseList[k]->
depth - currentList[idx[k]]->
depth);
442 cout <<
"mean&std: " << m_dp <<
"," << std_dp << endl;
444 for (
int k = 0; k < (int)idx.size(); ++k)
449 if (dp[k] < (m_dp + std_dp))
451 baseList[k]->x = currentList[idx[k]]->x;
452 baseList[k]->y = currentList[idx[k]]->y;
453 baseList[k]->p3D = currentList[idx[k]]->p3D;
479 for (itBase = baseList.begin(); itBase != baseList.end(); ++m)
490 itBase = baseList.erase(itBase);
514 cout <<
"Left feature " << m <<
" found in scale 0!"
520 currentImage, currentList[tidx], itBase->first,
true,
523 itBase->first->descriptors.hasDescriptorMultiSIFT());
525 cout <<
"LF LOWSCALES Out of bounds!!" << endl;
530 size_t nscales = itBase->first->multiScales.size() - 1;
534 cout <<
"Left feature " << m <<
" found in last scale!"
537 currentImage, currentList[tidx], itBase->first,
540 cout <<
"LF HIGHSCALES Out of bounds!!" << endl;
559 const CImage&
image,
const unsigned int x,
const unsigned int y,
560 double& mag,
double& ori)
562 if (
x > 0 &&
x <
image.getWidth() - 1 &&
y > 0 &&
y <
image.getHeight() - 1)
578 mag = sqrt(d1 * d1 + d2 * d2);
584 cout <<
"[computeGradient]: Out of bounds in " <<
x <<
"," <<
y
585 <<
" with image: " <<
image.getWidth() <<
"x" <<
image.getHeight()
599 const CImage&
image,
const unsigned int x,
const unsigned int y,
600 const unsigned int patchSize, std::vector<double>& orientations,
606 orientations.clear();
609 const unsigned int NBINS = 36;
610 const int hPatchSize = patchSize / 2;
612 vector<double> oris(NBINS, 0.0);
613 int mx = (int)
x, my = (
int)
y;
616 if (mx - (hPatchSize + 1) < 0 || my - (hPatchSize + 1) < 0 ||
617 mx + (hPatchSize + 1) > (int)(
image.getWidth() - 1) ||
618 my + (hPatchSize + 1) > (int)(
image.getHeight() - 1))
627 double exp_denom = 2.0 * sigma * sigma;
628 double bin_size =
M_2PI / NBINS;
630 for (
int ii = -hPatchSize; ii <= hPatchSize; ++ii)
631 for (
int jj = -hPatchSize; jj <= hPatchSize; ++jj)
636 double w = mag * exp(-(ii * ii + jj * jj) / exp_denom);
639 ((int)(floor(ori / bin_size))) % NBINS;
640 double bin_center = bin * bin_size;
641 double dif = ori - bin_center;
650 nxbin = bin == 0 ? NBINS - 1 : bin - 1;
654 double nbin_center = nxbin * bin_size;
655 double dif2 = ori - nbin_center;
657 oris[bin] +=
w * fabs(dif2) / bin_size;
660 oris[nxbin] +=
w * fabs(dif) / bin_size;
669 for (
unsigned int k = 0; k < oris.size(); ++k)
678 double hist_mag_th = 0.8 * mxori;
679 for (
unsigned int k = 0; k < oris.size(); ++k)
681 double pv = k == 0 ? oris[oris.size() - 1]
683 double nv = k == oris.size() - 1
687 if (oris[k] > pv && oris[k] > nv &&
688 oris[k] > hist_mag_th)
698 0.5 * (pv - nv) / (pv - 2.0 * oris[k] + nv);
699 int_bin = (int_bin < 0)
701 : (int_bin >= NBINS) ? int_bin - NBINS : int_bin;
704 orientations.push_back(int_ori);
717 vector<double>& oris,
const double& cbin,
const double& rbin,
718 const double& obin,
const double& mag,
const int d,
const int n)
728 double ncbin = cbin + d / 2. - 0.5;
729 double nrbin = rbin + d / 2. - 0.5;
731 int ncbin_i = floor(ncbin);
732 int nrbin_i = floor(nrbin);
733 int nobin_i = floor(obin);
735 double d_c = ncbin_i - ncbin;
736 double d_r = nrbin_i - nrbin;
737 double d_o = nobin_i - obin;
739 for (
int k = 0; k < 2; ++k)
740 for (
int m = 0; m < 2; ++m)
741 for (
int l = 0; l < 2; ++l)
742 if (ncbin_i + k >= 0 && ncbin_i + k < d && nrbin_i + m >= 0 &&
745 int idx = ((nobin_i + l) %
n) +
n * (ncbin_i + k) +
746 n * d * (nrbin_i + m);
747 oris[idx] += mag * (1 - fabs(d_c + k)) *
748 (1 - fabs(d_r + m)) * (1 - fabs(d_o + l));
820 const CImage&
image,
const unsigned int x,
const unsigned int y,
821 const unsigned int patchSize,
const double& orientation,
823 vector<int32_t>& hashCoeffs)
834 double cos_t = cos(orientation);
835 double sin_t = sin(orientation);
836 double bins_per_rad =
n /
M_2PI;
837 double exp_denom = opts.
sg3 * opts.
sg3 * 2;
838 int radius = 0.5 * patchSize;
839 vector<double> oris(Bp * Bp *
n, 0.0);
846 thePatch,
x - radius,
y - radius, patchSize, patchSize);
864 double cbin, rbin, obin;
865 double c1 = 0.0, c2 = 0.0, c3 = 0.0;
879 for (
int c = -radius;
c <= radius; ++
c)
880 for (
int r = -radius;
r <= radius; ++
r)
882 cbin = kp *
c * cos_t - kp *
r * sin_t;
883 rbin = kp *
c * sin_t + kp *
r * cos_t;
885 if (cbin > -2.5 && cbin < 2.5 && rbin > -2.5 && rbin < 2.5)
887 tlogger.enter(
"computeGradient");
890 tlogger.leave(
"computeGradient");
894 while (ori < 0.0) ori +=
M_2PI;
897 obin = ori * bins_per_rad;
898 w = exp(-(
c *
c +
r *
r) / exp_denom);
899 tlogger.enter(
"interpolate");
901 oris, cbin, rbin, obin, mag, Bp,
n);
902 tlogger.leave(
"interpolate");
947 if ((cbin < 0 && rbin < 0) || (cbin > 0 && rbin > 0))
981 hashCoeffs.resize(3);
982 hashCoeffs[0] =
round(c1);
983 hashCoeffs[1] =
round(c2);
984 hashCoeffs[2] =
round(c3);
990 tlogger.enter(
"normalize");
992 for (
unsigned int ii = 0; ii < oris.size(); ++ii)
993 sum += oris[ii] * oris[ii];
995 for (
unsigned int ii = 0; ii < oris.size(); ++ii) oris[ii] *=
sum;
998 for (
unsigned int ii = 0; ii < oris.size(); ++ii)
1002 for (
unsigned int ii = 0; ii < oris.size(); ++ii)
1003 sum += oris[ii] * oris[ii];
1005 for (
unsigned int ii = 0; ii < oris.size(); ++ii) oris[ii] *=
sum;
1008 descriptor.resize(oris.size());
1009 for (
unsigned int ii = 0; ii < descriptor.size(); ++ii)
1010 descriptor[ii] = (
int)(255.0f * oris[ii]);
1012 tlogger.leave(
"normalize");
1063 int imageW = rightImage.
getWidth();
1065 int leftFeatCounter = 0;
1066 int rightFeatCounter = 0;
1077 for (leftFeatCounter = 0, it1 = list1.
begin(); it1 != list1.
end();
1078 ++it1, ++leftFeatCounter)
1080 if (!(*it1)->descriptors.hasDescriptorMultiSIFT())
continue;
1083 max((*it1)->x -
min((hWindow + 2 * (*it1)->nTimesLastSeen), mxsize),
1086 min((*it1)->x +
min((hWindow + 2 * (*it1)->nTimesLastSeen), mxsize),
1089 max((*it1)->y -
min((hWindow + 2 * (*it1)->nTimesLastSeen), mxsize),
1092 min((*it1)->y +
min((hWindow + 2 * (*it1)->nTimesLastSeen), mxsize),
1101 for (rightFeatCounter = 0, it2 = list2.
begin(); it2 != list2.
end();
1102 ++it2, ++rightFeatCounter)
1112 if ((*it2)->x < sRegionX0 || (*it2)->x > sRegionX1 ||
1113 (*it2)->y < sRegionY0 || (*it2)->y > sRegionY1)
1130 vector<double> thisOris;
1132 rightImage, (*it2)->x, (*it2)->y, patchSize, thisOris,
1146 int firstScale, lastScale;
1151 firstScale = max(0, (
int)matchOpts.
lowScl1);
1153 min((
int)(*it1)->multiScales.size() - 1,
1165 for (
int k1 = firstScale; k1 <= lastScale; ++k1)
1166 for (
int k2 = 0; k2 < (int)(*it1)->multiOrientations[k1].size();
1168 for (
int k3 = 0; k3 < (int)thisOris.size();
1171 (*it1)->multiOrientations[k1][k2] -
1175 (*it1)->multiOrientations[k1][k2] -
1186 if (list2.
size() >= 8)
1188 std::vector<size_t> out_idx;
1189 std::vector<float> out_dist_sqr;
1190 maxResponse = (*it2)->response;
1193 (*it2)->x, (*it2)->y, 8, out_idx,
1195 for (
size_t kdcounter = 0;
1196 kdcounter < out_idx.size(); ++kdcounter)
1198 if (out_dist_sqr[kdcounter] > 1.4142)
1201 if (list2[out_idx[kdcounter]]->response >
1205 list2[out_idx[kdcounter]]->response;
1214 cout <<
"NO ES MAX" << endl;
1234 if ((*it2)->multiScales.size() == 0)
1236 (*it2)->multiScales.resize(1);
1237 (*it2)->multiScales[0] = 1.0;
1238 (*it2)->multiOrientations.resize(1);
1239 (*it2)->descriptors.multiSIFTDescriptors.resize(
1241 (*it2)->multiHashCoeffs.resize(1);
1245 bool oriFound =
false;
1248 co < (int)(*it2)->multiOrientations[0].size();
1250 if ((*it2)->multiOrientations[0][co] ==
1272 (*it2)->multiOrientations[0].push_back(
1275 vector<int32_t> thisDesc, thisHash;
1277 rightImage, (*it2)->x, (*it2)->y, patchSize,
1278 thisOris[k3], thisDesc, computeOpts,
1283 ->descriptors.multiSIFTDescriptors[0]
1284 .push_back(thisDesc);
1286 (*it2)->multiHashCoeffs[0].push_back(thisHash);
1288 for (
int n = 0;
n < int(thisDesc.size());
n++)
1292 .multiSIFTDescriptors[k1][k2][
n] -
1308 .multiSIFTDescriptors[0][wh]
1314 .multiSIFTDescriptors[k1][k2][
n] -
1317 .multiSIFTDescriptors[0][wh][
n]);
1331 ridx = rightFeatCounter;
1332 maxResponse = (*it2)->response;
1456 ASSERT_(mList1.size() > 0 && mList2.size() > 0);
1464 vector<int> scales1, scales2;
1470 baseList1, auxList1, leftImage, matchOpts, computeOpts);
1472 baseList1, auxList1,
1495 baseList2, auxList2, rightImage, matchOpts, computeOpts);
1497 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 ,
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");
A class for storing images as grayscale or RGB bitmaps.
void loadFromIplImage(void *iplImage)
Reads the image from a OpenCV IplImage object (making a COPY).
size_t getHeight() const override
Returns the height of the image in pixels.
const T * getAs() const
Returns a pointer to a const T* containing the image - the idea is to call like "img....
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).
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,...
size_t getWidth() const override
Returns the width of the image in pixels.
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.
Column vector, like Eigen::MatrixX*, but automatically initialized to zeros since construction.
A versatile "profiler" that logs the time spent within each pair of calls to enter(X)-leave(X),...
std::shared_ptr< CFeature > Ptr
A list of visual features, to be used as output by detectors, as input/output by trackers,...
CFeature::Ptr getByID(const TFeatureID &ID) const
Get a reference to a Feature from its ID.
TInternalFeatList::const_iterator const_iterator
TInternalFeatList::iterator iterator
void getBothFeatureLists(CFeatureList &list1, CFeatureList &list2)
Returns the matching features as two separate CFeatureLists.
const Scalar * const_iterator
#define ASSERT_(f)
Defines an assertion mechanism.
#define THROW_EXCEPTION(msg)
GLint GLint GLsizei GLsizei GLsizei depth
GLubyte GLubyte GLubyte GLubyte w
GLenum GLsizei GLenum GLenum const GLvoid * image
GLdouble GLdouble GLdouble r
GLubyte GLubyte GLubyte a
int round(const T value)
Returns the closer integer (int) to x.
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...
int void fclose(FILE *f)
An OS-independent version of fclose.
void memcpy(void *dest, size_t destSize, const void *src, size_t copyCount) noexcept
An OS and compiler independent version of "memcpy".
FILE * fopen(const char *fileName, const char *mode) noexcept
An OS-independent version of fopen.
int fprintf(FILE *fil, const char *format,...) noexcept MRPT_printf_format_check(2
An OS-independent version of fprintf.
uint64_t TFeatureID
Definition of a feature ID.
void normalizeImage(const mrpt::img::CImage &image, mrpt::img::CImage &nimage)
Normalizes the brigthness and contrast of an image by setting its mean value to zero and its standard...
std::map< int, std::map< int, std::map< int, std::deque< std::pair< TFeatureID, double > >> >> TQuantizationTable
bool computeMainOrientations(const mrpt::img::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...
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...
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...
void computeMultiResolutionDescriptors(const mrpt::img::CImage &imageLeft, const mrpt::img::CImage &imageRight, CMatchedFeatureList &matchedFeats, const TMultiResDescOptions &opts)
Computes the multi-resolution SIFT-like descriptor of a set of matched features.
void computeHistogramOfOrientations(const mrpt::img::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,...
void saveQTableToFile(const TQuantizationTable &qTable, const std::string &filename)
void updateBaseList(CFeatureList &baseList, const CFeatureList ¤tList, const std::vector< int > &idx)
int computeMoreDescriptors(const mrpt::img::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.
bool computeGradient(const mrpt::img::CImage &image, const unsigned int x, const unsigned int y, double &mag, double &ori)
Computes the gradient of certain pixel within the image.
void checkScalesAndFindMore(CMatchedFeatureList &baseList, const CFeatureList ¤tList, const mrpt::img::CImage ¤tImage, const TMultiResMatchingOutput &output, const TMultiResDescOptions &computeOpts, const TMultiResDescMatchOptions &matchOpts)
TMultiResMatchingOutput matchMultiResolutionFeatures(const CFeatureList &list1, CFeatureList &list2, const mrpt::img::CImage &rightImage, const TMultiResDescMatchOptions &matchOpts, const TMultiResDescOptions &computeOpts)
Matches two CFeatureList containing mulit-resolution descriptors.
TMultiResMatchingOutput relocalizeMultiDesc(const mrpt::img::CImage &image, CFeatureList &baseList, CFeatureList ¤tList, TQuantizationTable &qTable, const TMultiResDescOptions &desc_opts, const TMultiResDescMatchOptions &match_opts)
void insertHashCoeffs(const CFeature::Ptr &feat, TQuantizationTable &qTable)
void computeMultiOrientations(const mrpt::img::CImage &image, CFeatureList &list, const TMultiResDescOptions &opts)
Computes the multi-resolution SIFT-like descriptor of a list of features.
This base provides a set of functions for maths stuff.
CONTAINER::Scalar sum(const CONTAINER &v)
Computes the sum of all the elements.
void meanAndStd(const VECTORLIKE &v, double &out_mean, double &out_std, bool unbiased=true)
Computes the standard deviation of a vector.
Classes for computer vision, detectors, features, etc.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
T square(const T x)
Inline function for the square of a number.
double DEG2RAD(const double x)
Degrees to radians.
Struct containing the options when matching multi-resolution SIFT-like descriptors.
bool useDepthFilter
Whether or not use the filter based on the depth test.
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.
uint32_t highScl1
The highest scales in the two features to be taken into account in the matching process.
double matchingThreshold
The absolute threshold in descriptor distance for considering a match.
double oriThreshold
The threshold for the orientation test.
uint32_t lowScl1
The lowest scales in the two features to be taken into account in the matching process.
uint32_t searchAreaSize
Size of the squared area where to search for a match.
Struct containing the options when computing the multi-resolution SIFT-like descriptors.
uint32_t basePSize
The size of the base patch.
bool computeHashCoeffs
Whether or not compute the coefficients for mantaining a HASH table of descriptors (for relocalizatio...
bool computeDepth
Whether or not to compute the depth of the feature.
double cropValue
The SIFT-like descriptor is cropped at this value during normalization.
bool blurImage
Whether or not to blur the image previously to compute the descriptors.
std::vector< double > scales
The set of scales relatives to the base patch.
double fx
Intrinsic stereo pair parameters for computing the depth of the feature.
double sg1
The sigmas for the Gaussian kernels.
Struct containing the output after matching multi-resolution SIFT-like descriptors.
std::vector< double > firstListDistance
Contains the distances between the descriptors.
std::vector< int > firstListCorrespondences
Contains the indexes within the second list corresponding to the first one.
std::vector< int > firstListFoundScales
Contains the scales of the first list where the correspondence was found.
std::vector< int > secondListCorrespondences
Contains the indexes within the first list corresponding to the second one.