21 #ifndef otbImageToSURFKeyPointSetFilter_hxx
22 #define otbImageToSURFKeyPointSetFilter_hxx
25 #include "itkCenteredRigid2DTransform.h"
32 template <
class TInputImage,
class TOutputPo
intSet>
55 m_DifferentSamplePoints = 0;
56 m_DoHThreshold = 0.03;
57 m_DetHessianFilter = ImageToDetHessianImageType::New();
64 template <
class TInputImage,
class TOutputPo
intSet>
72 template <
class TInputImage,
class TOutputPo
intSet>
80 OutputPointSetPointerType outputPointSet = this->GetOutput();
85 if (m_ScalesNumber > 1)
86 k = (double)std::pow(2.0, (
double)(1 / (double)(m_ScalesNumber - 1)));
92 for (
int i = 0; i < m_OctavesNumber; ++i)
96 m_ImageList = ImageListType::New();
97 spacing = this->GetInput()->GetSignedSpacing();
105 m_ResampleFilter = ResampleFilterType::New();
106 m_ResampleFilter->SetInput(this->GetInput());
108 SizeType size = this->GetInput()->GetLargestPossibleRegion().GetSize();
109 for (
int l = 0; l < 2; ++l)
110 size[l] = (
unsigned int)floor(size[l] / std::pow(2.0, i));
111 m_ResampleFilter->SetSize(size);
114 for (
int l = 0; l < 2; ++l)
115 spacing[l] = (spacing[l] * std::pow(2.0, i));
116 m_ResampleFilter->SetOutputSpacing(spacing);
118 m_ResampleFilter->SetOutputOrigin(this->GetInput()->GetOrigin());
120 m_ResampleFilter->SetDefaultPixelValue(0);
121 m_ResampleFilter->Update();
122 m_determinantImage = m_ResampleFilter->GetOutput();
125 << m_determinantImage->GetLargestPossibleRegion().GetSize());
128 for (
int j = 0; j < m_ScalesNumber; ++j)
135 if ((i != 0 && j != 0) || (i == 0 && (i + j != 0)) || (m_ScalesNumber == 1 && i != 0))
143 m_DetHessianFilter = ImageToDetHessianImageType::New();
146 m_DetHessianFilter->SetInput(this->GetInput());
148 m_DetHessianFilter->SetInput(m_determinantImage);
150 m_DetHessianFilter->SetSigma(sigma_in);
151 m_DetHessianFilter->Update();
152 m_determinantImage = m_DetHessianFilter->GetOutput();
157 << m_determinantImage->GetLargestPossibleRegion().GetSize());
161 m_ImageList->PushBack(m_determinantImage);
168 for (
int jj = 1; jj < (int)(m_ImageList->Size() - 1); jj++)
170 m_ImageCurrent = m_ImageList->GetNthElement(jj);
171 m_ImageMovedPrev = m_ImageList->GetNthElement(jj - 1);
172 m_ImageMovedNext = m_ImageList->GetNthElement(jj + 1);
176 NeighborhoodIteratorType it(radius, m_ImageCurrent, m_ImageCurrent->GetLargestPossibleRegion());
181 NeighborhoodIteratorType itNeighPrev(radius, m_ImageMovedPrev, m_ImageMovedPrev->GetLargestPossibleRegion());
182 itNeighPrev.GoToBegin();
184 NeighborhoodIteratorType itNeighNext(radius, m_ImageMovedNext, m_ImageMovedNext->GetLargestPossibleRegion());
185 itNeighNext.GoToBegin();
187 while (!it.IsAtEnd())
193 if (IsLocalExtremum(it.GetNeighborhood()) && IsLocalExtremumAround(itNeighPrev.GetNeighborhood(), m_ImageCurrent->GetPixel(it.GetIndex())) &&
194 IsLocalExtremumAround(itNeighNext.GetNeighborhood(), m_ImageCurrent->GetPixel(it.GetIndex())))
196 OutputPointType keyPoint;
197 itNeighPrev.SetLocation(it.GetIndex());
198 itNeighNext.SetLocation(it.GetIndex());
199 VectorPointType lTranslation(PixelValue(0));
203 NeighborhoodIteratorType neighborCurrentScale(it);
204 NeighborhoodIteratorType neighborPreviousScale(itNeighPrev);
205 NeighborhoodIteratorType neighborNextScale(itNeighNext);
206 bool accepted =
false;
208 accepted = RefineLocationKeyPoint(neighborCurrentScale, neighborPreviousScale, neighborNextScale, lTranslation);
210 OffsetType lTranslateOffset = {{0, 0}};
213 lTranslateOffset[0] +=
static_cast<int>(lTranslation[0] > 0.5);
214 lTranslateOffset[0] += -
static_cast<int>(lTranslation[0] < -0.5);
216 lTranslateOffset[1] +=
static_cast<int>(lTranslation[1] > 0.5);
217 lTranslateOffset[1] += -
static_cast<int>(lTranslation[1] < -0.5);
219 NeighborhoodIteratorType moveIterator = neighborCurrentScale + lTranslateOffset;
221 if (moveIterator.InBounds())
224 neighborCurrentScale += lTranslateOffset;
225 neighborPreviousScale += lTranslateOffset;
226 neighborNextScale += lTranslateOffset;
227 lTranslation[0] -= lTranslateOffset[0];
228 lTranslation[1] -= lTranslateOffset[1];
232 lTranslation[0] = 0.0;
233 lTranslation[1] = 0.0;
236 if (accepted ==
false)
245 typename InputImageType::IndexType indexKeyPoint;
246 indexKeyPoint[0] = neighborCurrentScale.GetIndex()[0];
247 indexKeyPoint[1] = neighborCurrentScale.GetIndex()[1];
249 double sigmaDetected = sigma_in / pow(k, (
double)jj) * pow(2., (
double)i);
251 radius.Fill(GetMin((
int)(this->GetInput()->GetLargestPossibleRegion().GetSize()[0] - indexKeyPoint[0]),
252 (
int)(this->GetInput()->GetLargestPossibleRegion().GetSize()[1] - indexKeyPoint[1]), (
int)(6 * sigmaDetected)));
257 NeighborhoodIteratorType itNeighOrientation(radius, this->GetInput(), this->GetInput()->GetLargestPossibleRegion());
259 itNeighOrientation.SetLocation(neighborCurrentScale.GetIndex());
261 double orientationDetected = AssignOrientation(itNeighOrientation.GetNeighborhood(), sigmaDetected);
264 typename InputImageType::PointType physicalKeyPoint;
265 m_ImageCurrent->TransformIndexToPhysicalPoint(neighborCurrentScale.GetIndex(), keyPoint);
267 physicalKeyPoint[0] = keyPoint[0] + spacing[0] * lTranslation[0];
268 physicalKeyPoint[1] = keyPoint[1] + spacing[1] * lTranslation[1];
270 outputPointSet->SetPoint(m_NumberOfPoints, physicalKeyPoint);
276 radius.Fill(GetMin((
int)(this->GetInput()->GetLargestPossibleRegion().GetSize()[0] - indexKeyPoint[0]),
277 (
int)(this->GetInput()->GetLargestPossibleRegion().GetSize()[1] - indexKeyPoint[1]),
278 (
int)(10 * sigmaDetected)));
280 NeighborhoodIteratorType itNeighDescriptor(radius, this->GetInput(), this->GetInput()->GetLargestPossibleRegion());
282 itNeighDescriptor.SetLocation(neighborCurrentScale.GetIndex());
284 descriptor.resize(64);
286 descriptor = ComputeDescriptor(itNeighDescriptor.GetNeighborhood(), orientationDetected, sigmaDetected);
289 OutputPixelType data;
292 unsigned int IndDescriptor = 0;
294 typename std::vector<double>::const_iterator itDescriptor = descriptor.begin();
296 while (itDescriptor != descriptor.end())
298 data.SetElement(IndDescriptor, *itDescriptor);
302 outputPointSet->SetPointData(m_NumberOfPoints, data);
314 m_ImageList->Clear();
322 template <
class TInputImage,
class TOutputPo
intSet>
325 return std::min(a, std::min(b, c));
331 template <
class TInputImage,
class TOutputPo
intSet>
334 int centerIndex = neigh.GetCenterNeighborhoodIndex(), i = 0;
335 double centerValue = neigh[centerIndex];
336 bool max =
false, min =
false;
337 int flag_min = 0, flag_max = 0;
339 while (i != (
int)neigh.Size())
341 if (i != centerIndex)
343 if (centerValue > neigh[i] && flag_max == 0)
351 if (centerValue < neigh[i] && flag_min == 0 && centerValue < 0)
368 template <
class TInputImage,
class TOutputPo
intSet>
373 bool max =
false, min =
false;
374 int flag_min = 0, flag_max = 0;
376 while (i != (
int)neigh.Size())
379 if (CenterValue > neigh[i] && flag_max == 0)
387 if (CenterValue < neigh[i] && flag_min == 0)
405 template <
class TInputImage,
class TOutputPo
intSet>
407 const NeighborhoodIteratorType& previousScale,
408 const NeighborhoodIteratorType& nextScale, VectorPointType& solution)
410 bool accepted =
true;
411 solution = VectorPointType(PixelValue(0));
414 PixelValue dx = 0.5 * (currentScale.GetPixel(m_Offsets[6]) - currentScale.GetPixel(m_Offsets[1]));
416 PixelValue dy = 0.5 * (currentScale.GetPixel(m_Offsets[4]) - currentScale.GetPixel(m_Offsets[3]));
418 PixelValue ds = 0.5 * (nextScale.GetCenterPixel() - previousScale.GetCenterPixel());
420 PixelValue dxx = currentScale.GetPixel(m_Offsets[6]) - 2 * currentScale.GetCenterPixel() + currentScale.GetPixel(m_Offsets[1]);
422 PixelValue dyy = currentScale.GetPixel(m_Offsets[3]) - 2 * currentScale.GetCenterPixel() + currentScale.GetPixel(m_Offsets[4]);
424 PixelValue dss = previousScale.GetCenterPixel() - 2 * currentScale.GetCenterPixel() + nextScale.GetCenterPixel();
426 PixelValue dxy = 0.25 * (currentScale.GetPixel(m_Offsets[7]) + currentScale.GetPixel(m_Offsets[0]) - currentScale.GetPixel(m_Offsets[2]) -
427 currentScale.GetPixel(m_Offsets[5]));
429 PixelValue dxs = 0.25 * (nextScale.GetPixel(m_Offsets[6]) + previousScale.GetPixel(m_Offsets[1]) - nextScale.GetPixel(m_Offsets[1]) -
430 previousScale.GetPixel(m_Offsets[6]));
432 PixelValue dys = 0.25 * (nextScale.GetPixel(m_Offsets[4]) + previousScale.GetPixel(m_Offsets[3]) - nextScale.GetPixel(m_Offsets[3]) -
433 previousScale.GetPixel(m_Offsets[4]));
437 PixelValue curr = currentScale.GetCenterPixel();
438 PixelValue prev = previousScale.GetCenterPixel();
439 PixelValue next = nextScale.GetCenterPixel();
440 if ((prev < curr && curr < next) || (next < curr && curr < prev))
450 double det = dxx * (dyy * dss - dys * dys) - dxy * (dxy * dss - dxs * dys) + dxs * (dxy * dys - dxs * dyy);
453 solution[0] = -dx * (dyy * dss - dys * dys) - dy * (dxs * dys - dxy * dss) - ds * (dxy * dys - dyy * dxs);
454 solution[1] = -dx * (dys * dxs - dss * dxy) - dy * (dxx * dss - dxs * dxs) - ds * (dxs * dxy - dxx * dys);
455 solution[2] = -dx * (dxy * dys - dxs * dyy) - dy * (dxy * dxs - dxx * dys) - ds * (dxx * dyy - dxy * dxy);
458 PixelValue lDoHInterpolated = det * currentScale.GetCenterPixel() + 0.5 * (dx * solution[0] + dy * solution[1] + ds * solution[2]);
461 accepted = std::abs(lDoHInterpolated) > std::abs(det * m_DoHThreshold);
477 if (std::abs(
static_cast<double>(solution[0])) > 1.0 || std::abs(
static_cast<double>(solution[1])) > 1.0 || std::abs(
static_cast<double>(solution[2])) > 1.0)
490 template <
class TInputImage,
class TOutputPo
intSet>
495 int pas = ((i + S) - (
int)(i + S) > 0.5) ? ((int)S + 1) : (int)S;
496 int Largeur = 2 * neigh.GetRadius()[0] + 1;
497 int rayon = neigh.GetRadius()[0];
509 int NbBins = (2 * Pi / LengthBin);
510 std::vector<double> tab(NbBins * 2, 0.);
512 while (i < (
int)neigh.Size())
514 col = i % Largeur - rayon;
515 raw = i / Largeur - rayon;
516 dist = std::sqrt(
static_cast<double>(col * col + raw * raw));
523 if ((col > pas && col < Largeur - pas) && (raw > pas && raw < Largeur - pas))
526 w = std::exp(-((col - rayon) * (col - rayon) + (raw - rayon) * (raw - rayon)) / (2 * 2.5 * 2.5 * S * S));
527 pt[0] = (neigh[(col + pas) + raw * Largeur] - neigh[(col - pas) + raw * Largeur]) * w;
528 pt[1] = (neigh[col + (raw + pas) * Largeur] - neigh[col + (raw - pas) * Largeur]) * w;
530 if (pt[0] + pt[1] != 0)
536 bin = (int)(angle / LengthBin);
538 if (bin <= NbBins - 1 || bin >= 0)
540 tab[2 * bin] += pt[0];
541 tab[2 * bin + 1] += pt[1];
555 for (
int ii = 0; ii < NbBins * 2; ii = ii + 2)
557 length = std::sqrt(tab[ii] * tab[ii] + tab[ii + 1] * tab[ii + 1]);
565 return (indice + 0.5) * LengthBin;
572 template <
class TInputImage,
class TOutputPo
intSet>
577 typedef itk::CenteredRigid2DTransform<double> TransformType;
578 TransformType::Pointer eulerTransform = TransformType::New();
579 TransformType::ParametersType ParamVec(5);
580 PointImageType pSrc, pDst;
583 int i = 0, col, raw, Nbin, pas = 1;
584 double xx = 0, yy = 0;
586 int Largeur = 2 * neigh.GetRadius()[0] + 1;
587 double rayon =
static_cast<double>(Largeur) / 4.;
588 double r = neigh.GetRadius()[0];
590 double x0 = neigh.GetCenterNeighborhoodIndex() % Largeur;
591 double y0 = neigh.GetCenterNeighborhoodIndex() / Largeur;
596 descriptorVector.resize(64);
604 eulerTransform->SetParameters(ParamVec);
606 while (i < (
int)neigh.Size())
611 if ((col > pas && col < Largeur - pas) && (raw > pas && raw < Largeur - pas))
613 double distanceX = (raw - r);
614 double distanceY = (col - r);
615 dist = std::sqrt(distanceX * distanceX + distanceY * distanceY);
622 pSrc = eulerTransform->TransformPoint(pDst);
625 col =
static_cast<int>(std::floor(pSrc[0]));
626 raw =
static_cast<int>(std::floor(pSrc[1]));
634 xx =
static_cast<int>(pSrc[1] / rayon);
635 yy =
static_cast<int>(pSrc[0] / rayon);
636 Nbin =
static_cast<int>(xx + 4 * yy);
640 double distanceXcompensee_2 = (pSrc[0] - r) * (pSrc[0] - r);
641 double distanceYcompensee_2 = (pSrc[1] - r) * (pSrc[1] - r);
643 w = std::exp(-(distanceXcompensee_2 + distanceYcompensee_2) / (2 * 3.3 * 3.3 * S * S));
645 dx = 0.5 * (neigh[(col + pas) + raw * Largeur] - neigh[(col - pas) + raw * Largeur]) * w;
646 dy = 0.5 * (neigh[col + (raw + pas) * Largeur] - neigh[col + (raw - pas) * Largeur]) * w;
648 descriptorVector[4 * Nbin] += dx;
649 descriptorVector[4 * Nbin + 1] += dy;
650 descriptorVector[4 * Nbin + 2] += std::abs(dx);
651 descriptorVector[4 * Nbin + 3] += std::abs(dy);
659 for (
int ii = 0; ii < 64; ++ii)
660 accu += descriptorVector[ii] * descriptorVector[ii];
662 for (
int jj = 0; jj < 64; ++jj)
663 descriptorVector[jj] /= std::sqrt(accu);
665 return descriptorVector;
671 template <
class TInputImage,
class TOutputPo
intSet>
674 Superclass::PrintSelf(os, indent);
675 os << indent <<
"Number of Key Points " << m_NumberOfPoints << std::endl;