Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 8 additions & 10 deletions Examples/Segmentation/HoughTransform2DCirclesImageFilter.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -215,9 +215,9 @@ int main( int argc, char *argv[] )
while( itCircles != circles.end() )
{
std::cout << "Center: ";
std::cout << (*itCircles)->GetObjectToParentTransform()->GetOffset()
std::cout << itCircles->GetCenter()
<< std::endl;
std::cout << "Radius: " << (*itCircles)->GetRadius()[0] << std::endl;
std::cout << "Radius: " << itCircles->GetRadius() << std::endl;
// Software Guide : EndCodeSnippet

// Software Guide : BeginLatex
Expand All @@ -231,16 +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::Circle::CenterType center = itCircles->GetCenter();
using IndexValueType = HoughTransformFilterType::IndexType::IndexValueType;
localIndex[0] =
itk::Math::Round<long int>(offset[0]
+ (*itCircles)->GetRadius()[0]*std::cos(angle));
itk::Math::Round<IndexValueType>(center[0]
+ itCircles->GetRadius()*std::cos(angle));
localIndex[1] =
itk::Math::Round<long int>(offset[1]
+ (*itCircles)->GetRadius()[0]*std::sin(angle));
itk::Math::Round<IndexValueType>(center[1]
+ itCircles->GetRadius()*std::sin(angle));
OutputImageType::RegionType outputRegion =
localOutputImage->GetLargestPossibleRegion();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@

#include "itkImageToImageFilter.h"
#include "itkEllipseSpatialObject.h"
#include "itkIndex.h"
#include <ostream>
#include <vector>

namespace itk
{
Expand Down Expand Up @@ -66,6 +69,42 @@ class ITK_TEMPLATE_EXPORT HoughTransform2DCirclesImageFilter:
{
public:

/**
* \class Circle
* \brief Represents a circle by its center and its radius.
*
* \ingroup ITKImageFeature
*/
class Circle
{
public:
using CenterType = Index<2>;
using RadiusType = TRadiusPixelType;

Circle();

Circle(const CenterType&, RadiusType);

RadiusType GetRadius() const;

void SetRadius(RadiusType);

CenterType GetCenter() const;

void SetCenter(const CenterType&);

void ToEllipseSpatialObject(EllipseSpatialObject<2>&) const;

private:
CenterType m_Center;
RadiusType m_Radius;

friend std::ostream & operator<<(std::ostream & os, const Circle & circle)
{
return os << circle.m_Center << ' ' << circle.m_Radius;
}
};

/** Standard class type aliases. */
using Self = HoughTransform2DCirclesImageFilter;
using Superclass = ImageToImageFilter< Image< TInputPixelType, 2 >,
Expand Down Expand Up @@ -96,9 +135,7 @@ class ITK_TEMPLATE_EXPORT HoughTransform2DCirclesImageFilter:
using OutputImageRegionType = typename InputImageType::RegionType;

/** Circle type alias. */
using CircleType = EllipseSpatialObject< 2 >;
using CirclePointer = typename CircleType::Pointer;
using CirclesListType = std::list< CirclePointer >;
using CirclesListType = std::vector< Circle >;

using CirclesListSizeType = typename CirclesListType::size_type;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,90 @@
#include "itkGaussianDerivativeImageFunction.h"
#include "itkMinimumMaximumImageCalculator.h"
#include "itkMath.h"
#include <cassert>

namespace itk
{
template< typename TInputPixelType, typename TOutputPixelType, typename TRadiusPixelType >
HoughTransform2DCirclesImageFilter< TInputPixelType, TOutputPixelType, TRadiusPixelType >
::Circle::Circle()
:
m_Center{},
m_Radius{}
{
}

template< typename TInputPixelType, typename TOutputPixelType, typename TRadiusPixelType >
HoughTransform2DCirclesImageFilter< TInputPixelType, TOutputPixelType, TRadiusPixelType >
::Circle::Circle(const CenterType& center, const RadiusType radius)
:
// Note: Use parentheses instead of curly braces to initialize m_Center, to avoid
// AppleClang 6.0.0.6000056 compilation error, "no viable conversion from
// 'const CenterType' (aka 'const Index<2>') to 'IndexValueType' (aka 'long').
m_Center( center ),
m_Radius{ radius }
{
assert(radius >= 0.0);
}

template< typename TInputPixelType, typename TOutputPixelType, typename TRadiusPixelType >
auto
HoughTransform2DCirclesImageFilter< TInputPixelType, TOutputPixelType, TRadiusPixelType >
::Circle::GetCenter() const
-> CenterType
{
return m_Center;
}

template< typename TInputPixelType, typename TOutputPixelType, typename TRadiusPixelType >
void
HoughTransform2DCirclesImageFilter< TInputPixelType, TOutputPixelType, TRadiusPixelType >
::Circle::SetCenter(const CenterType& center)
{
m_Center = center;
}

template< typename TInputPixelType, typename TOutputPixelType, typename TRadiusPixelType >
auto
HoughTransform2DCirclesImageFilter< TInputPixelType, TOutputPixelType, TRadiusPixelType >
::Circle::GetRadius() const
-> RadiusType
{
return m_Radius;
}

template< typename TInputPixelType, typename TOutputPixelType, typename TRadiusPixelType >
void
HoughTransform2DCirclesImageFilter< TInputPixelType, TOutputPixelType, TRadiusPixelType >
::Circle::SetRadius(const RadiusType radius)
{
assert(radius >= 0.0);
m_Radius = radius;
}

template< typename TInputPixelType, typename TOutputPixelType, typename TRadiusPixelType >
void
HoughTransform2DCirclesImageFilter< TInputPixelType, TOutputPixelType, TRadiusPixelType >
::Circle::ToEllipseSpatialObject(EllipseSpatialObject<2>& ellipseSpatialObject) const
{
auto* const transform = ellipseSpatialObject.GetObjectToParentTransform();

if (transform == nullptr)
{
assert(!"ellipseSpatialObject.GetObjectToParentTransform() should not return nullptr!");
}
else
{
EllipseSpatialObject<2>::TransformType::OffsetType offset;
offset[0] = m_Center[0];
offset[1] = m_Center[1];

transform->SetOffset(offset);
}
ellipseSpatialObject.SetRadius(m_Radius);
}


template< typename TInputPixelType, typename TOutputPixelType, typename TRadiusPixelType >
HoughTransform2DCirclesImageFilter< TInputPixelType, TOutputPixelType, TRadiusPixelType >
::HoughTransform2DCirclesImageFilter() :
Expand Down Expand Up @@ -223,8 +304,6 @@ HoughTransform2DCirclesImageFilter< TInputPixelType, TOutputPixelType, TRadiusPi

Index< 2 > index;

CirclesListSizeType circles = 0;

// Find maxima
// Break out of "forever loop" as soon as the requested number of circles is found.
for(;;)
Expand All @@ -243,26 +322,17 @@ HoughTransform2DCirclesImageFilter< TInputPixelType, TOutputPixelType, TRadiusPi

const InternalImageType::IndexType indexOfMaximum = minMaxCalculator->GetIndexOfMaximum();

// Create a Circle Spatial Object
CirclePointer Circle = CircleType::New();
Circle->SetId(static_cast<int>( circles ));
Circle->SetRadius( m_RadiusImage->GetPixel( indexOfMaximum ) );

CircleType::VectorType center;
center[0] = indexOfMaximum[0];
center[1] = indexOfMaximum[1];
Circle->GetObjectToParentTransform()->SetOffset(center);
Circle->ComputeBoundingBox();
// Create a Circle
const TRadiusPixelType radius = m_RadiusImage->GetPixel(indexOfMaximum);

m_CirclesList.push_back(Circle);
m_CirclesList.push_back(Circle{ indexOfMaximum, radius });

circles++;
if ( circles >= m_NumberOfCircles ) { break; }
if ( m_CirclesList.size() >= m_NumberOfCircles ) { break; }

// Remove a black disc from the Hough space domain
for ( double angle = 0; angle <= 2 * itk::Math::pi; angle += itk::Math::pi / 1000 )
{
for ( double length = 0; length < m_DiscRadiusRatio * Circle->GetRadius()[0]; length += 1 )
for ( double length = 0; length < m_DiscRadiusRatio * radius; length += 1 )
{
index[0] = Math::Round<IndexValueType>( indexOfMaximum[0] + length * std::cos(angle) );
index[1] = Math::Round<IndexValueType>( indexOfMaximum[1] + length * std::sin(angle) );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,10 +168,8 @@ namespace
return false;
}

using CirclesListType = FilterType1::CirclesListType;

const CirclesListType& circles1 = filter1->GetCircles();
const CirclesListType& circles2 = filter2->GetCircles();
const auto& circles1 = filter1->GetCircles();
const auto& circles2 = filter2->GetCircles();

if ( circles1.empty() || circles2.empty() )
{
Expand All @@ -187,30 +185,13 @@ namespace
return false;
}

using CircleType = FilterType1::CircleType;

const CircleType* const circle1 = circles1.front().GetPointer();
const CircleType* const circle2 = circles2.front().GetPointer();

if ( (circle1 == nullptr) || (circle2 == nullptr) )
{
std::cout << "A Circle pointer appears to be incorrect!" << std::endl;
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;
}
const auto circle1 = circles1.front();
const auto circle2 = circles2.front();

bool success = true;

const itk::Vector<double, 2>& center1 = transform1->GetOffset();
const itk::Vector<double, 2>& center2 = transform2->GetOffset();
const auto center1 = circle1.GetCenter();
const auto center2 = circle2.GetCenter();

if (center1 != center2)
{
Expand All @@ -220,8 +201,8 @@ namespace
success = false;
}

const double radius1 = circle1->GetRadius()[0];
const double radius2 = circle2->GetRadius()[0];
const double radius1 = circle1.GetRadius();
const double radius2 = circle2.GetRadius();

if ( radius2 < radius1 )
{
Expand Down Expand Up @@ -381,18 +362,18 @@ int itkHoughTransform2DCirclesImageTest( int, char* [] )
unsigned int i = 0;
while( it != circleList.end() )
{
if( !itk::Math::FloatAlmostEqual( (double)( it->GetPointer()->GetRadius()[0] ),
if( !itk::Math::FloatAlmostEqual( (double)( it->GetRadius() ),
radius[i], 10, radiusTolerance ) &&
!itk::Math::FloatAlmostEqual( (double)( it->GetPointer()->GetRadius()[0] ),
!itk::Math::FloatAlmostEqual( (double)( it->GetRadius() ),
radius[i] * discRadiusRatio, 10, radiusTolerance ) )
{
std::cout << "Failure for circle #" << i << std::endl;
std::cout << "Expected radius: " << radius[i] << ", found " << it->GetPointer()->GetRadius() << std::endl;
std::cout << "Expected radius: " << radius[i] << ", found " << it->GetRadius() << std::endl;
success = false;
}
else
{
std::cout << "Circle #" << i << " radius: " << it->GetPointer()->GetRadius() << std::endl;
std::cout << "Circle #" << i << " radius: " << it->GetRadius() << std::endl;
}
++it;
++i;
Expand Down