Skip to content

Commit

Permalink
PERF: Refactor RelabelComponentImageFilter
Browse files Browse the repository at this point in the history
Parallelized the computation of the label counting with parallel
reduction of the map. Parallelized applying the output production
step. Modernizes the use of STL data structures and
loops. Stream-lined cases. Save iterators used for searching to
exploit coherence in images.

Updated some type to avoid casts. The filter clearly maps input pixels
to output pixels, so those type are used. And the number of objects
type has been changed to SizeValueType.
  • Loading branch information
blowekamp committed Jan 25, 2020
1 parent bcd762e commit 234bbf3
Show file tree
Hide file tree
Showing 3 changed files with 216 additions and 151 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "itkInPlaceImageFilter.h"
#include "itkImage.h"
#include <vector>
#include <mutex>

namespace itk
{
Expand Down Expand Up @@ -131,14 +132,14 @@ class ITK_TEMPLATE_EXPORT RelabelComponentImageFilter : public InPlaceImageFilte
itkNewMacro(Self);

/** Type used as identifier for the different component labels. */
using LabelType = IdentifierType;
using LabelType = InputPixelType;

/** Type used to count number of pixels in objects. */
using ObjectSizeType = SizeValueType;

/** Get the number of objects in the image. This information is only
* valid after the filter has executed. */
itkGetConstMacro(NumberOfObjects, LabelType);
itkGetConstMacro(NumberOfObjects, SizeValueType);

using ObjectSizeInPixelsContainerType = std::vector<ObjectSizeType>;
using ObjectSizeInPhysicalUnitsContainerType = std::vector<float>;
Expand All @@ -148,12 +149,12 @@ class ITK_TEMPLATE_EXPORT RelabelComponentImageFilter : public InPlaceImageFilte
* the filter has executed. If the caller has not specified a
* minimum object size, OriginalNumberOfObjects is the same as
* NumberOfObjects. */
itkGetConstMacro(OriginalNumberOfObjects, LabelType);
itkGetConstMacro(OriginalNumberOfObjects, SizeValueType);

/** Get/Set the number of objects enumerated and described when the
* filter is printed. */
itkSetMacro(NumberOfObjectsToPrint, LabelType);
itkGetConstReferenceMacro(NumberOfObjectsToPrint, LabelType);
itkSetMacro(NumberOfObjectsToPrint, SizeValueType);
itkGetConstReferenceMacro(NumberOfObjectsToPrint, SizeValueType);

/** Set the minimum size in pixels for an object. All objects
* smaller than this size will be discarded and will not appear
Expand Down Expand Up @@ -254,6 +255,9 @@ class ITK_TEMPLATE_EXPORT RelabelComponentImageFilter : public InPlaceImageFilte
void
GenerateData() override;

void
ParallelComputeLabels(const RegionType & inputRegion);

/** RelabelComponentImageFilter needs the entire input. Therefore
* it must provide an implementation GenerateInputRequestedRegion().
* \sa ProcessObject::GenerateInputRequestedRegion(). */
Expand All @@ -266,46 +270,28 @@ class ITK_TEMPLATE_EXPORT RelabelComponentImageFilter : public InPlaceImageFilte

struct RelabelComponentObjectType
{
LabelType m_ObjectNumber;
ObjectSizeType m_SizeInPixels;
float m_SizeInPhysicalUnits;
};

// put the function objects here for sorting in descending order
class RelabelComponentSizeInPixelsComparator
{
public:
bool
operator()(const RelabelComponentObjectType & a, const RelabelComponentObjectType & b)
RelabelComponentObjectType &
operator+=(const RelabelComponentObjectType & other)
{
if (a.m_SizeInPixels > b.m_SizeInPixels)
{
return true;
}
else if (a.m_SizeInPixels < b.m_SizeInPixels)
{
return false;
}
// size in pixels and physical units are the same, sort based on
// original object number
else if (a.m_ObjectNumber < b.m_ObjectNumber)
{
return true;
}
else
{
return false;
}
this->m_SizeInPixels += other.m_SizeInPixels;
return *this;
}
};

private:
LabelType m_NumberOfObjects{ 0 };
LabelType m_NumberOfObjectsToPrint{ 10 };
LabelType m_OriginalNumberOfObjects{ 0 };
SizeValueType m_NumberOfObjects{ 0 };
SizeValueType m_NumberOfObjectsToPrint{ 10 };
SizeValueType m_OriginalNumberOfObjects{ 0 };
ObjectSizeType m_MinimumObjectSize{ 0 };
bool m_SortByObjectSize{ true };

std::mutex m_Mutex;

using MapType = std::map<LabelType, RelabelComponentObjectType>;
MapType m_SizeMap;

ObjectSizeInPixelsContainerType m_SizeOfObjectsInPixels;
ObjectSizeInPhysicalUnitsContainerType m_SizeOfObjectsInPhysicalUnits;
};
Expand Down
Loading

0 comments on commit 234bbf3

Please sign in to comment.