Skip to content

Commit

Permalink
ENH: MIP image filter for DRR image calculation
Browse files Browse the repository at this point in the history
MIPForwardProjectionImageFilter is derived from
JosephForwardProjectionImageFilter and computes maximum
intensity step along the ray casting on the projection
  • Loading branch information
Mikhail Polkovnikov committed Jan 31, 2024
1 parent c32c1e9 commit d91969e
Show file tree
Hide file tree
Showing 2 changed files with 386 additions and 3 deletions.
135 changes: 132 additions & 3 deletions include/rtkJosephForwardProjectionImageFilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,56 @@ class ITK_TEMPLATE_EXPORT SumAlongRay
return !(*this != other);
}

inline TOutput
virtual inline TOutput
operator()(const ThreadIdType itkNotUsed(threadId), const TInput volumeValue, const VectorType & itkNotUsed(stepInMM))
{
return volumeValue;
}
};

/** \class MIPAlongRay
* \brief Function to compute the maximum intensity (MIP) value along the ray projection.
*
* \author Mikhail Polkovnikov
*
* \ingroup RTK Functions
*/
template <class TInput, class TOutput>
class ITK_TEMPLATE_EXPORT MIPAlongRay : public SumAlongRay< TInput, TOutput >
{
public:
using VectorType = itk::Vector<double, 3>;

MIPAlongRay() = default;
~MIPAlongRay() = default;
bool
operator!=(const MIPAlongRay &) const
{
return false;
}
bool
operator==(const MIPAlongRay & other) const
{
return !(*this != other);
}

inline TOutput
operator()(const ThreadIdType itkNotUsed(threadId), const TInput volumeValue, const VectorType & itkNotUsed(stepInMM)) override
{
return volumeValue;
}

inline void
operator()(const ThreadIdType itkNotUsed(threadId), TOutput& mipValue, const TInput volumeValue, const VectorType & itkNotUsed(stepInMM))
{
TOutput tmp = static_cast<TOutput>(volumeValue);
if (tmp > mipValue)
{
mipValue = tmp;
}
}
};

/** \class ProjectedValueAccumulation
* \brief Function to accumulate the ray casting on the projection.
*
Expand All @@ -126,7 +169,7 @@ class ITK_TEMPLATE_EXPORT ProjectedValueAccumulation
return !(*this != other);
}

inline void
virtual inline void
operator()(const ThreadIdType itkNotUsed(threadId),
const TInput & input,
TOutput & output,
Expand All @@ -141,6 +184,46 @@ class ITK_TEMPLATE_EXPORT ProjectedValueAccumulation
}
};

/** \class MIPProjectedValueAccumulation
* \brief Function to calculate maximum intensity projection (MIP) or
* minimum intensity projection (MinIP) the ray casting on the projection.
*
* \author Simon Rit
*
* \ingroup RTK Functions
*/
template <class TInput, class TOutput>
class ITK_TEMPLATE_EXPORT MIPProjectedValueAccumulation : public ProjectedValueAccumulation< TInput, TOutput >
{
public:
using VectorType = itk::Vector<double, 3>;

bool
operator!=(const MIPProjectedValueAccumulation &) const
{
return false;
}
bool
operator==(const MIPProjectedValueAccumulation & other) const
{
return !(*this != other);
}

inline void
operator()(const ThreadIdType itkNotUsed(threadId),
const TInput & itkNotUsed(input),
TOutput & output,
const TOutput & rayCastValue,
const VectorType & stepInMM,
const VectorType & itkNotUsed(source),
const VectorType & itkNotUsed(sourceToPixel),
const VectorType & itkNotUsed(nearestPoint),
const VectorType & itkNotUsed(farthestPoint)) const override
{
output = rayCastValue * stepInMM.GetNorm();
}
};

} // end namespace Functor


Expand Down Expand Up @@ -342,7 +425,7 @@ class ITK_TEMPLATE_EXPORT JosephForwardProjectionImageFilter
const double maxx,
const double maxy);

private:
protected:
// Functors
TInterpolationWeightMultiplication m_InterpolationWeightMultiplication;
TProjectedValueAccumulation m_ProjectedValueAccumulation;
Expand All @@ -351,6 +434,52 @@ class ITK_TEMPLATE_EXPORT JosephForwardProjectionImageFilter
double m_SuperiorClip{ 1. };
};

template <class TInputImage,
class TOutputImage,
class TInterpolationWeightMultiplication = Functor::InterpolationWeightMultiplication<
typename TInputImage::PixelType,
typename itk::PixelTraits<typename TInputImage::PixelType>::ValueType>,
class TProjectedValueAccumulation =
Functor::MIPProjectedValueAccumulation<typename TInputImage::PixelType, typename TOutputImage::PixelType>,
class TSumAlongRay = Functor::MIPAlongRay<typename TInputImage::PixelType, typename TOutputImage::PixelType>>
class ITK_TEMPLATE_EXPORT MIPForwardProjectionImageFilter
: public JosephForwardProjectionImageFilter<TInputImage, TOutputImage, TInterpolationWeightMultiplication, TProjectedValueAccumulation, TSumAlongRay>
{
public:
ITK_DISALLOW_COPY_AND_MOVE(MIPForwardProjectionImageFilter);

/** Standard class type alias. */
using Self = MIPForwardProjectionImageFilter;
using Superclass = JosephForwardProjectionImageFilter<TInputImage, TOutputImage, TInterpolationWeightMultiplication, TProjectedValueAccumulation, TSumAlongRay>;
using Pointer = itk::SmartPointer<Self>;
using ConstPointer = itk::SmartPointer<const Self>;
using InputPixelType = typename TInputImage::PixelType;
using OutputPixelType = typename TOutputImage::PixelType;
using OutputImageRegionType = typename TOutputImage::RegionType;
using CoordRepType = double;
using VectorType = itk::Vector<CoordRepType, TInputImage::ImageDimension>;
using TClipImageType = itk::Image<double, TOutputImage::ImageDimension>;
using TClipImagePointer = typename TClipImageType::Pointer;

/** Method for creation through the object factory. */
itkNewMacro(Self);

/** Run-time type information (and related methods). */
#ifdef itkOverrideGetNameOfClassMacro
itkOverrideGetNameOfClassMacro(MIPForwardProjectionImageFilter);
#else
itkTypeMacro(MIPForwardProjectionImageFilter, JosephForwardProjectionImageFilter);
#endif

protected:
MIPForwardProjectionImageFilter() = default;
~MIPForwardProjectionImageFilter() override = default;

void
ThreadedGenerateData(const OutputImageRegionType & outputRegionForThread, ThreadIdType threadId) override;

};

} // end namespace rtk

#ifndef ITK_MANUAL_INSTANTIATION
Expand Down
Loading

0 comments on commit d91969e

Please sign in to comment.