Commit 44ac5827 authored by Christian Schulte zu Berge's avatar Christian Schulte zu Berge
Browse files

Introducing ItkWatershedFilter processor to ITK module

parent 79f58d99
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2013, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universität München
// Boltzmannstr. 3, 85748 Garching b. München, Germany
//
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
//
// ================================================================================================
#include "itkwatershedfilter.h"
#include "tgt/glmath.h"
#include "tgt/logmanager.h"
#include "modules/itk/core/genericimagerepresentationitk.h"
#include <itkIntTypes.h>
#include <itkGradientMagnitudeImageFilter.h>
#include <itkWatershedImageFilter.h>
#include <itkCastImageFilter.h>
#include "core/datastructures/imagedata.h"
#include "core/datastructures/genericimagerepresentationlocal.h"
// In this class we want to use various ITK filters. Each filter needs the same ITK boilerplate
// code to be written before and after calling the filter. Futhermore, we need to distinguish
// between the different input base types, since ITK doesn't know runtime type inference.
// Hence, we define various handy macros that will assemble the necessary C++ code for using the
// corresponding ITK filters within this processor. Good luck!
/**
* Executes the specified filter on the data specified filter.
* \param MA_baseType base type of input image
* \param MA_returnType base type of ouput image
* \param MA_numChannels number of channels of input image
* \param MA_dimensionality dimensionality of images
* \param MD_filterBody additional stuff to execute between filter definition and execution
*/
#define PERFORM_ITK_FILTER_WATERSHED(MA_baseType, MA_returnType, MA_numChannels, MA_dimensionality, MD_filterBody) \
{ \
GenericImageRepresentationItk<MA_baseType, MA_numChannels, MA_dimensionality>::ScopedRepresentation itkRep(data, p_sourceImageID.getValue()); \
if (itkRep != 0) { \
typedef GenericImageRepresentationItk<MA_baseType, MA_numChannels, MA_dimensionality>::ItkImageType InputImageType; \
typedef GenericImageRepresentationItk<float, MA_numChannels, MA_dimensionality>::ItkImageType FloatImageType; \
typedef itk::Image<itk::IdentifierType, MA_dimensionality> LabelImageType; \
typedef GenericImageRepresentationItk<uint16_t, MA_numChannels, MA_dimensionality>::ItkImageType OutputImageType; \
\
itk::GradientMagnitudeImageFilter<InputImageType, FloatImageType>::Pointer gradientMagnitudeImageFilter = itk::GradientMagnitudeImageFilter<InputImageType, FloatImageType>::New(); \
gradientMagnitudeImageFilter->SetInput(itkRep->getItkImage()); \
gradientMagnitudeImageFilter->Update(); \
\
itk::WatershedImageFilter<FloatImageType>::Pointer filter = itk::WatershedImageFilter<FloatImageType>::New(); \
MD_filterBody \
filter->SetInput(gradientMagnitudeImageFilter->GetOutput()); \
filter->Update(); \
\
itk::CastImageFilter<LabelImageType, OutputImageType>::Pointer caster = itk::CastImageFilter<LabelImageType, OutputImageType>::New(); \
caster->SetInput(filter->GetOutput()); \
caster->Update(); \
\
GenericImageRepresentationItk<uint16_t, MA_numChannels, MA_dimensionality>::create(id, caster->GetOutput()); \
} \
}
#define DISPATCH_ITK_FILTER_BRD(MA_WTP, MA_baseType, MA_returnType, MA_dimensionality, MD_filterBody) \
tgtAssert(MA_WTP._numChannels == 1, "ItkWatershedFilter only supports single-channel images.") \
PERFORM_ITK_FILTER_WATERSHED(MA_baseType, MA_returnType, 1, MA_dimensionality, MD_filterBody)
#define DISPATCH_ITK_FILTER_D(MA_WTP, MA_dimensionality, MD_filterBody) \
switch (MA_WTP._baseType) { \
case WeaklyTypedPointer::UINT8: \
DISPATCH_ITK_FILTER_BRD(MA_WTP, uint8_t, uint8_t, MA_dimensionality, MD_filterBody) \
break; \
case WeaklyTypedPointer::INT8: \
DISPATCH_ITK_FILTER_BRD(MA_WTP, int8_t, int8_t, MA_dimensionality, MD_filterBody) \
break; \
case WeaklyTypedPointer::UINT16: \
DISPATCH_ITK_FILTER_BRD(MA_WTP, uint16_t, uint16_t, MA_dimensionality, MD_filterBody) \
break; \
case WeaklyTypedPointer::INT16: \
DISPATCH_ITK_FILTER_BRD(MA_WTP, int16_t, int16_t, MA_dimensionality, MD_filterBody) \
break; \
case WeaklyTypedPointer::UINT32: \
DISPATCH_ITK_FILTER_BRD(MA_WTP, uint32_t, uint32_t, MA_dimensionality, MD_filterBody) \
break; \
case WeaklyTypedPointer::INT32: \
DISPATCH_ITK_FILTER_BRD(MA_WTP, int32_t, int32_t, MA_dimensionality, MD_filterBody) \
break; \
case WeaklyTypedPointer::FLOAT: \
DISPATCH_ITK_FILTER_BRD(MA_WTP, float, float, MA_dimensionality, MD_filterBody) \
break; \
default: \
tgtAssert(false, "Should not reach this - wrong base type in WeaklyTypedPointer!"); \
} \
/**
* Dispatches the execution for the ITK filter \a MA_filterType for the image \a MA_localRep.
* \param MA_localRep local representation of the image to apply the filter to
* \param MA_filterType type name if the ITK filter to use (within itk:: namespace)
* \param MD_filterBody additional stuff to execute between filter definition and execution
*/
#define DISPATCH_ITK_FILTER(MA_localRep, MD_filterBody) \
do { \
WeaklyTypedPointer wtp = MA_localRep->getWeaklyTypedPointer(); \
switch (MA_localRep->getDimensionality()) { \
case 2: DISPATCH_ITK_FILTER_D(wtp, 2, MD_filterBody) break; \
case 3: DISPATCH_ITK_FILTER_D(wtp, 3, MD_filterBody) break; \
default: tgtAssert(false, "Unsupported dimensionality!"); break; \
} \
} while (0)
// ================================================================================================
// = Macros defined, let the party begin! =
// ================================================================================================
namespace campvis {
const std::string ItkWatershedFilter::loggerCat_ = "CAMPVis.modules.classification.ItkWatershedFilter";
ItkWatershedFilter::ItkWatershedFilter()
: AbstractProcessor()
, p_sourceImageID("InputVolume", "Input Volume ID", "volume", DataNameProperty::READ)
, p_targetImageID("OutputGradients", "Output Gradient Volume ID", "gradients", DataNameProperty::WRITE)
, p_threshold("Threshold", "Threshold", .005f, .001f, 1.f, .01f)
, p_level("Level", "Level", .5f, .1f, 10.f, 1.f)
{
addProperty(&p_sourceImageID);
addProperty(&p_targetImageID);
addProperty(&p_threshold);
addProperty(&p_level);
}
ItkWatershedFilter::~ItkWatershedFilter() {
}
void ItkWatershedFilter::updateResult(DataContainer& data) {
ImageRepresentationLocal::ScopedRepresentation input(data, p_sourceImageID.getValue());
if (input != 0 && input->getParent()->getNumChannels() == 1) {
ImageData* id = new ImageData(input->getDimensionality(), input->getSize(), 1);
DISPATCH_ITK_FILTER(input, \
filter->SetLevel(p_level.getValue()); \
filter->SetThreshold(p_threshold.getValue()); \
);
data.addData(p_targetImageID.getValue(), id);
}
else {
LDEBUG("No suitable input image found.");
}
validate(INVALID_RESULT);
}
}
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2013, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universität München
// Boltzmannstr. 3, 85748 Garching b. München, Germany
//
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
//
// ================================================================================================
#ifndef ITKWATERSHEDFILTER_H__
#define ITKWATERSHEDFILTER_H__
#include <string>
#include "core/pipeline/visualizationprocessor.h"
#include "core/properties/datanameproperty.h"
#include "core/properties/genericproperty.h"
#include "core/properties/floatingpointproperty.h"
#include "core/properties/optionproperty.h"
#include "modules/preprocessing/tools/abstractimagefilter.h"
namespace campvis {
/**
* Performs watershed image filter on input image using ITK.
*/
class ItkWatershedFilter : public AbstractProcessor {
public:
/**
* Constructs a new ItkWatershedFilter Processor
**/
ItkWatershedFilter();
/**
* Destructor
**/
virtual ~ItkWatershedFilter();
/// \see AbstractProcessor::getName()
virtual const std::string getName() const { return "ItkWatershedFilter"; };
/// \see AbstractProcessor::getDescription()
virtual const std::string getDescription() const { return "Performs watershed image filter on input image using ITK."; };
/// \see AbstractProcessor::getAuthor()
virtual const std::string getAuthor() const { return "Christian Schulte zu Berge <christian.szb@in.tum.de>"; };
/// \see AbstractProcessor::getProcessorState()
virtual ProcessorState getProcessorState() const { return AbstractProcessor::TESTING; };
DataNameProperty p_sourceImageID; ///< ID for input volume
DataNameProperty p_targetImageID; ///< ID for output gradient volume
FloatProperty p_threshold;
FloatProperty p_level;
protected:
/// \see AbstractProcessor::updateResult
virtual void updateResult(DataContainer& dataContainer);
static const std::string loggerCat_;
};
}
#endif // ITKWATERSHEDFILTER_H__
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment