22 #ifndef otbShapeAttributesLabelMapFilter_hxx
23 #define otbShapeAttributesLabelMapFilter_hxx
26 #include "itkProgressReporter.h"
27 #include "itkConstNeighborhoodIterator.h"
28 #include "itkConstShapedNeighborhoodIterator.h"
29 #include "itkLabelMapToLabelImageFilter.h"
30 #include "itkConstantBoundaryCondition.h"
31 #include "itkGeometryUtilities.h"
32 #include "itkConnectedComponentAlgorithm.h"
33 #include "vnl/algo/vnl_real_eigensystem.h"
34 #include "vnl/algo/vnl_symmetric_eigensystem.h"
45 template <
class TLabelObject,
class TLabelImage>
47 : m_ComputeFeretDiameter(false), m_ComputePerimeter(false), m_ComputeFlusser(true), m_ComputePolygon(true), m_ReducedAttributeSet(true), m_LabelImage(nullptr)
52 template <
class TLabelObject,
class TLabelImage>
59 resp = resp && (m_ComputeFeretDiameter !=
self.m_ComputeFeretDiameter);
60 resp = resp && (m_ComputePerimeter !=
self.m_ComputePerimeter);
61 resp = resp && (m_ReducedAttributeSet !=
self.m_ReducedAttributeSet);
62 resp = resp && (m_LabelImage !=
self.m_LabelImage);
69 template <
class TLabelObject,
class TLabelImage>
73 return !(
this !=
self);
77 template <
class TLabelObject,
class TLabelImage>
80 m_ComputePerimeter = flag;
84 template <
class TLabelObject,
class TLabelImage>
87 return m_ComputePerimeter;
91 template <
class TLabelObject,
class TLabelImage>
94 m_ComputePolygon = flag;
98 template <
class TLabelObject,
class TLabelImage>
101 return m_ComputePolygon;
105 template <
class TLabelObject,
class TLabelImage>
108 m_ComputeFlusser = flag;
112 template <
class TLabelObject,
class TLabelImage>
115 return m_ComputeFlusser;
119 template <
class TLabelObject,
class TLabelImage>
122 m_ComputeFeretDiameter = flag;
126 template <
class TLabelObject,
class TLabelImage>
129 return m_ComputeFeretDiameter;
133 template <
class TLabelObject,
class TLabelImage>
136 m_ReducedAttributeSet = flag;
140 template <
class TLabelObject,
class TLabelImage>
143 return m_ReducedAttributeSet;
148 template <
class TLabelObject,
class TLabelImage>
151 m_LabelImage = image;
155 template <
class TLabelObject,
class TLabelImage>
165 template <
class TLabelObject,
class TLabelImage>
168 const typename LabelObjectType::LabelType& label = lo->GetLabel();
173 double sizePerPixel = 1;
174 for (
DimensionType i = 0; i < LabelObjectType::ImageDimension; ++i)
176 sizePerPixel *= std::abs(m_LabelImage->GetSignedSpacing()[i]);
179 typename std::vector<double> sizePerPixelPerDimension;
180 for (
DimensionType i = 0; i < LabelObjectType::ImageDimension; ++i)
182 sizePerPixelPerDimension.push_back(sizePerPixel / std::abs(m_LabelImage->GetSignedSpacing()[i]));
186 typename LabelObjectType::IndexType borderMin = m_LabelImage->GetLargestPossibleRegion().GetIndex();
187 typename LabelObjectType::IndexType borderMax = borderMin;
188 for (
DimensionType i = 0; i < LabelObjectType::ImageDimension; ++i)
190 borderMax[i] += borderMin[i] + m_LabelImage->GetLargestPossibleRegion().GetSize()[i] - 1;
194 unsigned long size = 0;
195 itk::ContinuousIndex<double, LabelObjectType::ImageDimension> centroid;
197 typename LabelObjectType::IndexType mins;
198 mins.Fill(itk::NumericTraits<long>::max());
199 typename LabelObjectType::IndexType maxs;
200 maxs.Fill(itk::NumericTraits<long>::NonpositiveMin());
201 unsigned long sizeOnBorder = 0;
202 double physicalSizeOnBorder = 0;
203 itk::Matrix<double, LabelObjectType::ImageDimension, LabelObjectType::ImageDimension> centralMoments;
204 centralMoments.Fill(0);
212 while (!lit.IsAtEnd())
215 const typename LabelObjectType::IndexType& idx = lit.GetLine().GetIndex();
216 unsigned long length = lit.GetLine().GetLength();
223 for (
DimensionType i = 1; i < LabelObjectType::ImageDimension; ++i)
225 centroid[i] += length * idx[i];
228 centroid[0] += idx[0] * length + (length * (length - 1)) / 2.0;
231 for (
DimensionType i = 0; i < LabelObjectType::ImageDimension; ++i)
233 if (idx[i] < mins[i])
237 if (idx[i] > maxs[i])
243 if (idx[0] + (
long)length > maxs[0])
245 maxs[0] = idx[0] + length - 1;
249 bool isOnBorder =
false;
250 for (
DimensionType i = 1; i < LabelObjectType::ImageDimension; ++i)
252 if (idx[i] == borderMin[i] || idx[i] == borderMax[i])
262 sizeOnBorder += length;
267 bool isOnBorder0 =
false;
268 if (idx[0] == borderMin[0])
274 if (!isOnBorder0 || length > 1)
277 if (idx[0] + (
long)length - 1 == borderMax[0])
287 if (idx[0] == borderMin[0])
290 physicalSizeOnBorder += sizePerPixelPerDimension[0];
292 if (idx[0] + (
long)length - 1 == borderMax[0])
295 physicalSizeOnBorder += sizePerPixelPerDimension[0];
298 for (
DimensionType i = 1; i < LabelObjectType::ImageDimension; ++i)
300 if (idx[i] == borderMin[i])
303 physicalSizeOnBorder += sizePerPixelPerDimension[i] * length;
305 if (idx[i] == borderMax[i])
308 physicalSizeOnBorder += sizePerPixelPerDimension[i] * length;
336 typename TLabelImage::PointType physicalPosition;
337 m_LabelImage->TransformIndexToPhysicalPoint(idx, physicalPosition);
338 const typename TLabelImage::SpacingType& spacing = m_LabelImage->GetSignedSpacing();
340 double sumX = length * (physicalPosition[0] + (spacing[0] * (length - 1)) / 2.0);
343 centralMoments[0][0] +=
344 length * (physicalPosition[0] * physicalPosition[0] + spacing[0] * (length - 1) * ((spacing[0] * (2 * length - 1)) / 6.0 + physicalPosition[0]));
346 for (
DimensionType i = 1; i < LabelObjectType::ImageDimension; ++i)
350 centralMoments[i][i] += length * physicalPosition[i] * physicalPosition[i];
352 for (
DimensionType j = i + 1; j < LabelObjectType::ImageDimension; ++j)
356 double cm = length * physicalPosition[i] * physicalPosition[j];
357 centralMoments[i][j] += cm;
358 centralMoments[j][i] += cm;
361 double cm = sumX * physicalPosition[i];
362 centralMoments[i][0] += cm;
363 centralMoments[0][i] += cm;
369 typename TLabelImage::SizeType regionSize;
370 double minSize = itk::NumericTraits<double>::max();
371 double maxSize = itk::NumericTraits<double>::NonpositiveMin();
372 for (
DimensionType i = 0; i < LabelObjectType::ImageDimension; ++i)
375 regionSize[i] = maxs[i] - mins[i] + 1;
376 double s = regionSize[i] * std::abs(m_LabelImage->GetSignedSpacing()[i]);
377 minSize = std::min(s, minSize);
378 maxSize = std::max(s, maxSize);
379 for (
DimensionType j = 0; j < LabelObjectType::ImageDimension; ++j)
381 centralMoments[i][j] /= size;
384 typename TLabelImage::RegionType region(mins, regionSize);
385 typename TLabelImage::PointType physicalCentroid;
386 m_LabelImage->TransformContinuousIndexToPhysicalPoint(centroid, physicalCentroid);
389 for (
DimensionType i = 0; i < LabelObjectType::ImageDimension; ++i)
391 for (
DimensionType j = 0; j < LabelObjectType::ImageDimension; ++j)
393 centralMoments[i][j] -= physicalCentroid[i] * physicalCentroid[j];
398 itk::Vector<double, LabelObjectType::ImageDimension> principalMoments;
399 vnl_symmetric_eigensystem<double> eigen(centralMoments.GetVnlMatrix());
400 vnl_diag_matrix<double> pm = eigen.D;
401 for (
unsigned int i = 0; i < LabelObjectType::ImageDimension; ++i)
404 principalMoments[i] = pm(i, i);
406 itk::Matrix<double, LabelObjectType::ImageDimension, LabelObjectType::ImageDimension> principalAxes = eigen.V.transpose();
410 vnl_real_eigensystem eigenrot(principalAxes.GetVnlMatrix());
411 vnl_diag_matrix<std::complex<double>> eigenval = eigenrot.D;
412 std::complex<double> det(1.0, 0.0);
414 for (
DimensionType i = 0; i < LabelObjectType::ImageDimension; ++i)
416 det *= eigenval(i, i);
419 for (
DimensionType i = 0; i < LabelObjectType::ImageDimension; ++i)
421 principalAxes[LabelObjectType::ImageDimension - 1][i] *= std::real(det);
424 double elongation = 0;
425 if (principalMoments[LabelObjectType::ImageDimension - 2] != 0)
427 elongation = std::sqrt(principalMoments[LabelObjectType::ImageDimension - 1] / principalMoments[LabelObjectType::ImageDimension - 2]);
430 double physicalSize = size * sizePerPixel;
431 double equivalentRadius = hyperSphereRadiusFromVolume(physicalSize);
432 double equivalentPerimeter = hyperSpherePerimeter(equivalentRadius);
435 itk::Vector<double, LabelObjectType::ImageDimension> ellipsoidSize;
437 for (
DimensionType i = 0; i < LabelObjectType::ImageDimension; ++i)
439 edet *= principalMoments[i];
441 edet = std::pow(edet, 1.0 / LabelObjectType::ImageDimension);
442 for (
DimensionType i = 0; i < LabelObjectType::ImageDimension; ++i)
444 ellipsoidSize[i] = 2.0 * equivalentRadius * std::sqrt(principalMoments[i] / edet);
448 if (m_ComputeFlusser)
451 if (LabelObjectType::ImageDimension == 2)
454 std::complex<double> c11, c20, c12, c21, c22, c30, c31, c40;
455 c11 = c20 = c12 = c21 = c22 = c30 = c31 = c40 = std::complex<double>(0, 0);
460 while (!lit.IsAtEnd())
462 const typename LabelObjectType::IndexType& idx = lit.GetLine().GetIndex();
463 unsigned long length = lit.GetLine().GetLength();
465 long endIdx0 = idx[0] + length;
466 for (
typename LabelObjectType::IndexType iidx = idx; iidx[0] < endIdx0; iidx[0]++)
468 typename TLabelImage::PointType cPP;
469 m_LabelImage->TransformIndexToPhysicalPoint(iidx, cPP);
470 cPP -= physicalCentroid.GetVectorFromOrigin();
471 std::complex<double> xpiy(cPP[0], cPP[1]);
472 std::complex<double> xmiy(cPP[0], -cPP[1]);
476 c12 += xpiy * xmiy * xmiy;
477 c21 += xpiy * xpiy * xmiy;
478 c30 += xpiy * xpiy * xpiy;
479 c22 += xpiy * xpiy * xmiy * xmiy;
480 c31 += xpiy * xpiy * xpiy * xmiy;
481 c40 += xpiy * xpiy * xpiy * xpiy;
487 c11 /= physicalSize * physicalSize;
488 c20 /= physicalSize * physicalSize;
489 c12 /= std::pow(physicalSize, 5.0 / 2);
490 c21 /= std::pow(physicalSize, 5.0 / 2);
491 c30 /= std::pow(physicalSize, 5.0 / 2);
492 c22 /= std::pow(physicalSize, 3);
493 c31 /= std::pow(physicalSize, 3);
494 c40 /= std::pow(physicalSize, 3);
496 lo->SetAttribute(
"SHAPE::Flusser01", c11.real());
497 lo->SetAttribute(
"SHAPE::Flusser02", (c21 * c12).real());
498 lo->SetAttribute(
"SHAPE::Flusser03", (c20 * std::pow(c12, 2)).real());
499 lo->SetAttribute(
"SHAPE::Flusser04", (c20 * std::pow(c12, 2)).imag());
500 lo->SetAttribute(
"SHAPE::Flusser05", (c30 * std::pow(c12, 3)).real());
501 lo->SetAttribute(
"SHAPE::Flusser06", (c30 * std::pow(c12, 3)).imag());
502 lo->SetAttribute(
"SHAPE::Flusser07", c22.real());
503 lo->SetAttribute(
"SHAPE::Flusser08", (c31 * std::pow(c12, 2)).real());
504 lo->SetAttribute(
"SHAPE::Flusser09", (c31 * std::pow(c12, 2)).imag());
505 lo->SetAttribute(
"SHAPE::Flusser10", (c40 * std::pow(c12, 4)).real());
506 lo->SetAttribute(
"SHAPE::Flusser11", (c40 * std::pow(c12, 4)).imag());
511 if (m_ComputePolygon)
515 polygonFunctor.
SetStartIndex(m_LabelImage->GetLargestPossibleRegion().GetIndex());
516 polygonFunctor.
SetOrigin(m_LabelImage->GetOrigin());
517 polygonFunctor.
SetSpacing(m_LabelImage->GetSignedSpacing());
518 typename PolygonType::Pointer polygon = simplifyFunctor(polygonFunctor(lo));
519 lo->SetPolygon(polygon);
523 lo->SetAttribute(
"SHAPE::PhysicalSize", physicalSize);
526 lo->SetAttribute(
"SHAPE::Elongation", elongation);
528 if (m_ComputeFeretDiameter)
531 unsigned long ssize = 0;
532 typedef typename std::deque<typename LabelObjectType::IndexType> IndexListType;
533 IndexListType idxList;
539 typedef typename itk::ConstNeighborhoodIterator<LabelImageType> NeighborIteratorType;
540 typename TLabelImage::SizeType neighborHoodRadius;
541 neighborHoodRadius.Fill(1);
542 NeighborIteratorType it(neighborHoodRadius, m_LabelImage, m_LabelImage->GetBufferedRegion());
543 itk::ConstantBoundaryCondition<LabelImageType> lcbc;
545 lcbc.SetConstant(label + 1);
546 it.OverrideBoundaryCondition(&lcbc);
550 while (!llit.IsAtEnd())
552 const typename LabelObjectType::IndexType& firstIdx = llit.GetLine().GetIndex();
553 unsigned long length = llit.GetLine().GetLength();
555 long endIdx0 = firstIdx[0] + length;
556 for (
typename LabelObjectType::IndexType idx = firstIdx; idx[0] < endIdx0; idx[0]++)
560 it += idx - it.GetIndex();
563 for (
unsigned i = 0; i < it.Size(); ++i)
565 if (it.GetPixel(i) != label)
567 idxList.push_back(idx);
577 double feretDiameter = 0;
578 for (
typename IndexListType::const_iterator iIt1 = idxList.begin(); iIt1 != idxList.end(); iIt1++)
580 typename IndexListType::const_iterator iIt2 = iIt1;
581 for (iIt2++; iIt2 != idxList.end(); iIt2++)
585 for (
DimensionType i = 0; i < LabelObjectType::ImageDimension; ++i)
587 length += std::pow((iIt1->operator[](i) - iIt2->operator[](i)) * m_LabelImage->GetSignedSpacing()[i], 2);
589 if (feretDiameter < length)
591 feretDiameter = length;
596 feretDiameter = std::sqrt(feretDiameter);
599 lo->SetAttribute(
"SHAPE::FeretDiameter", feretDiameter);
605 if (m_ComputePerimeter)
607 double perimeter = this->ComputePerimeter(lo, region);
609 lo->SetAttribute(
"SHAPE::Perimeter", perimeter);
610 lo->SetAttribute(
"SHAPE::Roundness", equivalentPerimeter / perimeter);
615 if (!m_ReducedAttributeSet)
617 lo->SetAttribute(
"SHAPE::Size", size);
618 std::ostringstream oss;
619 for (
unsigned int dim = 0; dim < LabelObjectType::ImageDimension; ++dim)
622 oss <<
"SHAPE::RegionIndex" << dim;
623 lo->SetAttribute(oss.str().c_str(), region.GetIndex()[dim]);
625 oss <<
"SHAPE::RegionSize" << dim;
626 lo->SetAttribute(oss.str().c_str(), region.GetSize()[dim]);
628 oss <<
"SHAPE::PhysicalCentroid" << dim;
629 lo->SetAttribute(oss.str().c_str(), physicalCentroid[dim]);
631 oss <<
"SHAPE::EquivalentEllipsoidRadius" << dim;
632 lo->SetAttribute(oss.str().c_str(), ellipsoidSize[dim]);
634 oss <<
"SHAPE::PrincipalMoments" << dim;
635 lo->SetAttribute(oss.str().c_str(), principalMoments[dim]);
637 for (
unsigned int dim2 = 0; dim2 < LabelObjectType::ImageDimension; ++dim2)
640 oss <<
"SHAPE::PrincipalAxis" << dim << dim2;
641 lo->SetAttribute(oss.str().c_str(), principalAxes(dim, dim2));
645 lo->SetAttribute(
"SHAPE::RegionElongation", maxSize / minSize);
646 lo->SetAttribute(
"SHAPE::RegionRatio", size / (
double)region.GetNumberOfPixels());
647 lo->SetAttribute(
"SHAPE::SizeOnBorder", sizeOnBorder);
648 lo->SetAttribute(
"SHAPE::PhysicalSizeOnBorder", physicalSizeOnBorder);
649 lo->SetAttribute(
"SHAPE::EquivalentPerimeter", equivalentPerimeter);
650 lo->SetAttribute(
"SHAPE::EquivalentRadius", equivalentRadius);
654 template <
class TLabelObject,
class TLabelImage>
658 typedef std::deque<typename LabelObjectType::LineType> VectorLineType;
659 typedef itk::Image<VectorLineType, ImageDimension - 1> LineImageType;
660 typename LineImageType::Pointer lineImage = LineImageType::New();
661 typename LineImageType::IndexType lIdx;
662 typename LineImageType::SizeType lSize;
666 lIdx[i] = boundingBox.GetIndex()[i + 1];
667 lSize[i] = boundingBox.GetSize()[i + 1];
669 typename LineImageType::RegionType lRegion;
670 lRegion.SetIndex(lIdx);
671 lRegion.SetSize(lSize);
673 typename LineImageType::RegionType elRegion(lRegion);
675 elRegion.PadByRadius(lSize);
678 lineImage->SetRegions(elRegion);
679 lineImage->Allocate();
680 lineImage->FillBuffer(VectorLineType());
685 typename LabelObjectType::ConstLineIterator lit(labelObject);
686 while (!lit.IsAtEnd())
688 const typename TLabelObject::IndexType& idx = lit.GetLine().GetIndex();
691 lIdx[i] = idx[i + 1];
693 lineImage->GetPixel(lIdx).push_back(lit.GetLine());
698 typedef typename std::map<OffsetType, itk::SizeValueType, typename OffsetType::LexicographicCompare> MapInterceptType;
699 MapInterceptType intercepts;
704 typedef itk::ConstShapedNeighborhoodIterator<LineImageType> LineImageIteratorType;
705 LineImageIteratorType lIt(lSize, lineImage, lRegion);
706 setConnectivity(&lIt,
true);
707 for (lIt.GoToBegin(); !lIt.IsAtEnd(); ++lIt)
709 const VectorLineType& ls = lIt.GetCenterPixel();
716 intercepts[no] += 2 * ls.size();
719 typename LineImageIteratorType::ConstIterator ci;
720 for (ci = lIt.Begin(); ci != lIt.End(); ci++)
724 const VectorLineType& ns = ci.Get();
726 typename LineImageType::OffsetType lno = ci.GetNeighborhoodOffset();
730 no[i + 1] = vnl_math_abs(lno[i]);
744 for (
typename VectorLineType::const_iterator li = ls.begin(); li != ls.end(); ++li)
747 const typename LabelObjectType::LineType& l = *li;
749 intercepts[no] += l.GetLength();
751 intercepts[dno] += l.GetLength() * 2;
759 typename VectorLineType::const_iterator li = ls.begin();
760 typename VectorLineType::const_iterator ni = ns.begin();
762 itk::IndexValueType lZero = 0;
763 itk::IndexValueType lMin = 0;
764 itk::IndexValueType lMax = 0;
766 itk::IndexValueType nMin = itk::NumericTraits<itk::IndexValueType>::NonpositiveMin() + 1;
767 itk::IndexValueType nMax = ni->GetIndex()[0] - 1;
769 while (li != ls.end())
772 lMin = li->GetIndex()[0];
773 lMax = lMin + li->GetLength() - 1;
776 intercepts[no] += vnl_math_max(lZero, vnl_math_min(lMax, nMax) - vnl_math_max(lMin, nMin) + 1);
784 intercepts[dno] += vnl_math_max(lZero, vnl_math_min(lMax, nMax + 1) - vnl_math_max(lMin, nMin + 1) + 1);
786 intercepts[dno] += vnl_math_max(lZero, vnl_math_min(lMax, nMax - 1) - vnl_math_max(lMin, nMin - 1) + 1);
792 nMin = ni->GetIndex()[0] + ni->GetLength();
797 nMax = ni->GetIndex()[0] - 1;
801 nMax = itk::NumericTraits<itk::IndexValueType>::max() - 1;
815 double perimeter = PerimeterFromInterceptCount(intercepts, m_LabelImage->GetSignedSpacing());
819 template <
class TLabelObject,
class TLabelImage>
820 template <
class TMapIntercept,
class TSpacing>
824 double perimeter = 0.0;
825 double pixelSize = 1.0;
826 int dim = TSpacing::GetVectorDimension();
827 for (
int i = 0; i < dim; i++)
829 pixelSize *= spacing[i];
832 for (
int i = 0; i < dim; i++)
838 perimeter += pixelSize / spacing[i] * intercepts[no] / 2.0;
842 perimeter *= itk::GeometryUtilities::HyperSphereVolume(dim, 1.0) / itk::GeometryUtilities::HyperSphereVolume(dim - 1, 1.0);
846 #if !defined(ITK_DO_NOT_USE_PERIMETER_SPECIALIZATION)
847 template <
class TLabelObject,
class TLabelImage>
851 double dx = spacing[0];
852 double dy = spacing[1];
862 double perimeter = 0.0;
863 perimeter += dy * intercepts[nx] / 2.0;
864 perimeter += dx * intercepts[ny] / 2.0;
865 perimeter += dx * dy / spacing.GetNorm() * intercepts[nxy] / 2.0;
866 perimeter *= itk::Math::pi / 4.0;
870 template <
class TLabelObject,
class TLabelImage>
874 double dx = spacing[0];
875 double dy = spacing[1];
876 double dz = spacing[2];
877 double dxy = std::sqrt(spacing[0] * spacing[0] + spacing[1] * spacing[1]);
878 double dxz = std::sqrt(spacing[0] * spacing[0] + spacing[2] * spacing[2]);
879 double dyz = std::sqrt(spacing[1] * spacing[1] + spacing[2] * spacing[2]);
880 double dxyz = std::sqrt(spacing[0] * spacing[0] + spacing[1] * spacing[1] + spacing[2] * spacing[2]);
881 double vol = spacing[0] * spacing[1] * spacing[2];
886 double c1 = 0.04577789120476 * 2;
887 double c2 = 0.04577789120476 * 2;
888 double c3 = 0.04577789120476 * 2;
889 double c4 = 0.03698062787608 * 2;
890 double c5 = 0.03698062787608 * 2;
891 double c6 = 0.03698062787608 * 2;
892 double c7 = 0.03519563978232 * 2;
911 double perimeter = 0.0;
912 perimeter += vol / dx * intercepts[nx] / 2.0 * c1;
913 perimeter += vol / dy * intercepts[ny] / 2.0 * c2;
914 perimeter += vol / dz * intercepts[nz] / 2.0 * c3;
915 perimeter += vol / dxy * intercepts[nxy] / 2.0 * c4;
916 perimeter += vol / dxz * intercepts[nxz] / 2.0 * c5;
917 perimeter += vol / dyz * intercepts[nyz] / 2.0 * c6;
918 perimeter += vol / dxyz * intercepts[nxyz] / 2.0 * c7;
925 template <
class TLabelObject,
class TLabelImage>
932 return n * factorial(n - 1);
937 template <
class TLabelObject,
class TLabelImage>
944 return n * doubleFactorial(n - 2);
949 template <
class TLabelObject,
class TLabelImage>
952 bool even = n % 2 == 0;
955 return factorial(n / 2);
965 template <
class TLabelObject,
class TLabelImage>
968 return std::pow(
otb::CONST_PI, LabelObjectType::ImageDimension / 2.0) * std::pow(radius, LabelObjectType::ImageDimension) /
969 gammaN2p1(LabelObjectType::ImageDimension);
973 template <
class TLabelObject,
class TLabelImage>
976 return LabelObjectType::ImageDimension * hyperSphereVolume(radius) / radius;
980 template <
class TLabelObject,
class TLabelImage>
983 return std::pow(volume * gammaN2p1(LabelObjectType::ImageDimension) / std::pow(
otb::CONST_PI, LabelObjectType::ImageDimension / 2.0),
984 1.0 / LabelObjectType::ImageDimension);
989 template <
class TImage,
class TLabelImage>
992 if (this->GetFunctor().GetComputeFeretDiameter() != flag)
999 template <
class TImage,
class TLabelImage>
1005 template <
class TImage,
class TLabelImage>
1008 if (this->GetFunctor().GetComputePerimeter() != flag)
1015 template <
class TImage,
class TLabelImage>
1021 template <
class TImage,
class TLabelImage>
1024 if (this->GetFunctor().GetComputePolygon() != flag)
1031 template <
class TImage,
class TLabelImage>
1037 template <
class TImage,
class TLabelImage>
1040 if (this->GetFunctor().GetComputeFlusser() != flag)
1047 template <
class TImage,
class TLabelImage>
1054 template <
class TImage,
class TLabelImage>
1057 if (this->GetFunctor().GetReducedAttributeSet() != flag)
1064 template <
class TImage,
class TLabelImage>
1070 template <
class TImage,
class TLabelImage>
1073 if (this->GetFunctor().GetLabelImage() != img)
1080 template <
class TImage,
class TLabelImage>
1086 template <
class TImage,
class TLabelImage>
1090 if (this->GetInPlace() && this->CanRunInPlace())
1095 ImagePointer inputAsOutput =
dynamic_cast<TImage*
>(
const_cast<TImage*
>(this->GetInput()));
1100 this->GraftOutput(inputAsOutput);
1101 this->GetOutput()->SetLargestPossibleRegion(this->GetOutput()->GetLargestPossibleRegion());
1102 this->GetOutput()->SetRequestedRegion(this->GetOutput()->GetRequestedRegion());
1103 this->GetOutput()->SetBufferedRegion(this->GetOutput()->GetBufferedRegion());
1107 for (
unsigned int i = 1; i < this->GetNumberOfOutputs(); ++i)
1111 outputPtr = this->GetOutput(i);
1112 outputPtr->SetBufferedRegion(outputPtr->GetRequestedRegion());
1113 outputPtr->Allocate();
1119 Superclass::AllocateOutputs();
1126 template <
class TImage,
class TLabelImage>
1129 itk::ImageToImageFilter<TImage, TImage>::GenerateInputRequestedRegion();
1133 template <
class TImage,
class TLabelImage>
1136 Superclass::BeforeThreadedGenerateData();
1137 if (!this->GetFunctor().GetLabelImage())
1140 typedef itk::LabelMapToLabelImageFilter<TImage, TLabelImage> LCI2IType;
1141 typename LCI2IType::Pointer lci2i = LCI2IType::New();
1142 lci2i->SetInput(this->GetInput());
1144 lci2i->SetNumberOfThreads(this->GetNumberOfThreads());
1146 this->GetFunctor().SetLabelImage(lci2i->GetOutput());
1159 template <
class TImage,
class TLabelImage>
1162 Superclass::PrintSelf(os, indent);
1164 os << indent <<
"ComputeFeretDiameter: " << this->GetFunctor().GetComputeFeretDiameter() << std::endl;
1165 os << indent <<
"ComputePerimeter: " << this->GetFunctor().GetComputePerimeter() << std::endl;