Skip to content

Commit

Permalink
ENH: Added GetCenterPoint and SetCenterPoint to EllipseSpatialObject
Browse files Browse the repository at this point in the history
Wraps access to ellipseSpatialObject->GetObjectToWorldTransform()->m_Offset.

These new member functions allow simplifying the implementation, as well as
use cases of itk::HoughTransform2DCirclesImageFilter::GetCircles(). With this
commit, the implementation, test, and example of the HoughTransform2DCircles
filter are adapted to make use of them.

Note that this change silently breaks old ITK user code (ITK < 5.0) calling
HoughTransform2DCirclesImageFilter::GetCircles().

Triggered by comments from Tim Evain at ITK Discourse, starting at
https://discourse.itk.org/t/hough-transform-2d-circles-image-filter-getcircles-patch/350/46

Change-Id: I49a9f0504c0fc85aeefddd813fcabca309bd09e8
  • Loading branch information
N-Dekker committed Feb 19, 2018
1 parent ba72602 commit 1722d1e
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 21 deletions.
13 changes: 6 additions & 7 deletions Examples/Segmentation/HoughTransform2DCirclesImageFilter.cxx
Expand Up @@ -215,7 +215,7 @@ int main( int argc, char *argv[] )
while( itCircles != circles.end() )
{
std::cout << "Center: ";
std::cout << (*itCircles)->GetObjectToParentTransform()->GetOffset()
std::cout << (*itCircles)->GetCenterPoint()
<< std::endl;
std::cout << "Radius: " << (*itCircles)->GetRadius()[0] << std::endl;
// Software Guide : EndCodeSnippet
Expand All @@ -231,15 +231,14 @@ int main( int argc, char *argv[] )
angle <= itk::Math::twopi;
angle += itk::Math::pi/60.0 )
{
using TransformType = HoughTransformFilterType::CircleType::TransformType;
using OffsetType = TransformType::OutputVectorType;
const OffsetType offset =
(*itCircles)->GetObjectToParentTransform()->GetOffset();
const HoughTransformFilterType::CircleType::PointType centerPoint =
(*itCircles)->GetCenterPoint();
using IndexValueType = ImageType::IndexType::IndexValueType;
localIndex[0] =
itk::Math::Round<long int>(offset[0]
itk::Math::Round<IndexValueType>(centerPoint[0]
+ (*itCircles)->GetRadius()[0]*std::cos(angle));
localIndex[1] =
itk::Math::Round<long int>(offset[1]
itk::Math::Round<IndexValueType>(centerPoint[1]
+ (*itCircles)->GetRadius()[0]*std::sin(angle));
OutputImageType::RegionType outputRegion =
localOutputImage->GetLargestPossibleRegion();
Expand Down
7 changes: 7 additions & 0 deletions Modules/Core/SpatialObjects/include/itkEllipseSpatialObject.h
Expand Up @@ -68,6 +68,12 @@ class ITK_TEMPLATE_EXPORT EllipseSpatialObject:
/** Get radii via an array of radius values */
itkGetConstReferenceMacro(Radius, ArrayType);

/* Returns the center point (in world coordinates) of the ellipse */
PointType GetCenterPoint() const;

/* Set the center point (in world coordinates) of the ellipse */
void SetCenterPoint(const PointType& point);

/** Returns a degree of membership to the object.
* That's useful for fuzzy objects. */
bool ValueAt(const PointType & point, double & value,
Expand Down Expand Up @@ -109,6 +115,7 @@ class ITK_TEMPLATE_EXPORT EllipseSpatialObject:
/** Print the object informations in a stream. */
void PrintSelf(std::ostream & os, Indent indent) const override;
};

} // end namespace itk

#ifndef ITK_MANUAL_INSTANTIATION
Expand Down
21 changes: 21 additions & 0 deletions Modules/Core/SpatialObjects/include/itkEllipseSpatialObject.hxx
Expand Up @@ -51,6 +51,27 @@ EllipseSpatialObject< TDimension >
}
}

template< unsigned int TDimension >
auto
EllipseSpatialObject<TDimension>::GetCenterPoint() const
-> PointType
{
PointType originPoint;
originPoint.Fill(0);
// GetObjectToWorldTransform() never returns nullptr, no need to check.
return originPoint + this->GetObjectToWorldTransform()->GetOffset();
}

template< unsigned int TDimension >
void
EllipseSpatialObject<TDimension>::SetCenterPoint(const PointType& point)
{
PointType originPoint;
originPoint.Fill(0);
// GetModifiableObjectToWorldTransform() never returns nullptr, no need to check.
this->GetModifiableObjectToWorldTransform()->SetOffset(point - originPoint);
}

/** Test whether a point is inside or outside the object
* For computational speed purposes, it is faster if the method does not
* check the name of the class and the current depth */
Expand Down
Expand Up @@ -248,10 +248,10 @@ HoughTransform2DCirclesImageFilter< TInputPixelType, TOutputPixelType, TRadiusPi
Circle->SetId(static_cast<int>( circles ));
Circle->SetRadius( m_RadiusImage->GetPixel( indexOfMaximum ) );

CircleType::VectorType center;
CircleType::PointType center;
center[0] = indexOfMaximum[0];
center[1] = indexOfMaximum[1];
Circle->GetObjectToParentTransform()->SetOffset(center);
Circle->SetCenterPoint(center);
Circle->ComputeBoundingBox();

m_CirclesList.push_back(Circle);
Expand Down
Expand Up @@ -198,21 +198,14 @@ namespace
return false;
}

const CircleType::TransformType* const transform1 = circle1->GetObjectToParentTransform();
const CircleType::TransformType* const transform2 = circle2->GetObjectToParentTransform();

if ( (transform1 == nullptr) || (transform2 == nullptr) )
{
std::cout << "A GetObjectToParentTransform() call appears to be incorrect!" << std::endl;
return false;
}

bool success = true;

const itk::Vector<double, 2>& center1 = transform1->GetOffset();
const itk::Vector<double, 2>& center2 = transform2->GetOffset();
using PointType = CircleType::PointType;

const PointType& centerPoint1 = circle1->GetCenterPoint();
const PointType& centerPoint2 = circle2->GetCenterPoint();

if (center1 != center2)
if (centerPoint1 != centerPoint2)
{
// The choice of the radius image type should not affect the center estimation.
std::cout << "center1 and center2 should be equal, even while the radius image types differ!"
Expand Down

0 comments on commit 1722d1e

Please sign in to comment.