[ITK-users] Filter working on both itk::Image and itk::VectorImage
Cyril Mory
cyril.mory at creatis.insa-lyon.fr
Mon Feb 27 10:24:21 EST 2017
I found some help outside this mailing list, so again, I'm answering my
own question (I'll try not to make it a habit). There is a solution
using C++11, and features derived from "Substitution failure is not an
error". The following code does it. I've added quite a lot of comments,
so it should be understandable.
#include <itkImage.h>
#include <itkVectorImage.h>
#include <itkImageToImageFilter.h>
#include <itkImageFileReader.h>
#include <itkImageRegionConstIterator.h>
#include <itkImageRegionIterator.h>
#include <type_traits>
#include <typeinfo>
namespace itk
{
template <class TInputImage >
class ITK_EXPORT SFINAETestFilter :
public itk::ImageToImageFilter< TInputImage, TInputImage >
{
public:
/** Standard class typedefs. */
typedef SFINAETestFilter Self;
typedef itk::ImageToImageFilter<TInputImage, TInputImage> Superclass;
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
// Define the types that a slice can take, depending on whether
TInputImage is an itk::Image or and itk::VectorImage
typedef itk::Image<typename TInputImage::InternalPixelType,
TInputImage::ImageDimension - 1> ImageSliceType;
typedef itk::VectorImage<typename TInputImage::InternalPixelType,
TInputImage::ImageDimension - 1> VectorImageSliceType;
// Define SliceType
// std::is_same<T1, T2>::value is true is T1 and T2 are the same
type, and false otherwise
// std::conditional<B, T3, T4>::type is T3 if B is true, T4 otherwise
// The code checks if TInputImage::PixelType is an
itk::VariableLengthVector. If so, it uses VectorImageSliceType as SliceType
// Otherwise, it uses ImageSliceType as SliceType
typedef typename std::conditional<std::is_same<typename
TInputImage::PixelType,
itk::VariableLengthVector<typename TInputImage::InternalPixelType>
>::value,
VectorImageSliceType,
ImageSliceType>::type SliceType;
/** Method for creation through the object factory */
itkNewMacro(Self);
/** Run-time type information (and related methods). */
itkTypeMacro(SFINAETestFilter, ImageToImageFilter);
/** Superclass typedefs. */
typedef typename Superclass::OutputImageRegionType
OutputImageRegionType;
typedef typename Superclass::OutputImagePointer OutputImagePointer;
/** ImageDimension constants */
itkStaticConstMacro(InputImageDimension, unsigned int,
TInputImage::ImageDimension);
typename SliceType::Pointer GetSlice()
{
// Create the slice
typename SliceType::Pointer firstSlice = SliceType::New();
// Determine its size
typename TInputImage::RegionType largest =
this->GetInput()->GetLargestPossibleRegion();
typename SliceType::RegionType region;
typename SliceType::SizeType size;
typename SliceType::IndexType index;
for (unsigned int dim = 0; dim < SliceType::ImageDimension; dim++)
{
size[dim] = largest.GetSize()[dim];
index[dim] = largest.GetIndex()[dim];
}
region.SetSize(size);
region.SetIndex(index);
// Allocate
firstSlice->SetRegions(region);
firstSlice->SetNumberOfComponentsPerPixel(this->GetInput()->GetNumberOfComponentsPerPixel());
firstSlice->Allocate();
// Fill
itk::ImageRegionIterator<SliceType> sliceIt(firstSlice, region);
itk::ImageRegionConstIterator<TInputImage> inputIt(this->GetInput(),
largest);
while(!sliceIt.IsAtEnd())
{
sliceIt.Set(inputIt.Get());
++sliceIt;
++inputIt;
}
// Return
return firstSlice;
}
};
} /* end namespace itk */
int main(){
typedef itk::Image<float, 3> ImageType;
typedef itk::VectorImage<float, 3> VectorImageType;
// With the itk::Image template
typedef itk::SFINAETestFilter<ImageType> SFINAEWithImageType;
typename SFINAEWithImageType::Pointer withImageType =
SFINAEWithImageType::New();
typedef itk::ImageFileReader<ImageType> ImageReaderType;
ImageReaderType::Pointer imageReader = ImageReaderType::New();
imageReader->SetFileName("image.mha");
imageReader->Update();
withImageType->SetInput(imageReader->GetOutput());
withImageType->GetSlice()->Print(std::cout);
itk::Image<float, 2>::IndexType firstPixelIndex;
firstPixelIndex.Fill(0);
std::cout << withImageType->GetSlice()->GetPixel(firstPixelIndex) <<
std::endl;
// With the itk::VectorImage template
typedef itk::SFINAETestFilter<VectorImageType> SFINAEWithVectorImageType;
typename SFINAEWithVectorImageType::Pointer withVectorImageType =
SFINAEWithVectorImageType::New();
typedef itk::ImageFileReader<VectorImageType> VectorImageReaderType;
VectorImageReaderType::Pointer vectorImageReader =
VectorImageReaderType::New();
vectorImageReader->SetFileName("vectorImage.mha");
vectorImageReader->Update();
withVectorImageType->SetInput(vectorImageReader->GetOutput());
withVectorImageType->GetSlice()->Print(std::cout);
std::cout << withVectorImageType->GetSlice()->GetPixel(firstPixelIndex)
<< std::endl;
return EXIT_SUCCESS;
}
On 27/02/2017 12:09, Cyril Mory wrote:
> Hi,
>
> Still the same topic, but a different issue:
>
> I have a filter that is templated over its image input type, usually
> itk::Image<T, dim>. I want to modify it so that it also works when
> that type is itk::VectorImage<T, dim>.
>
> This filter internally defines SliceType =
> itk::Image<InputImageType::InternalPixelType, dim - 1>. But when
> processing an itk::VectorImage, I would like this SliceType to be
> itk::VectorImage<InputImageType::InternalPixelType, dim - 1>.
>
> I don't think there is a way in C++ to recover the itk::Image<> or the
> itk::VectorImage<> "un-templated", and define a type with whole new
> template arguments. But is there an ITK mechanism that would solve my
> problem ?
>
> Best regards,
>
> Cyril
>
> On 22/02/2017 17:39, Matt McCormick wrote:
>> Hi Cyril,
>>
>> Yes, this is a good approach. Thanks for sharing your investigation.
>>
>> Matt
>>
>> On Wed, Feb 22, 2017 at 5:52 AM, Cyril Mory
>> <cyril.mory at creatis.insa-lyon.fr> wrote:
>>> Answering my own question:
>>>
>>> I found a way to do what I needed using itk::NumericTraits<T> :
>>>
>>> OutputImagePixelType pix;
>>> itk::NumericTraits<OutputImagePixelType>::SetLength(pix,
>>> this->GetVectorLength());
>>> pix = itk::NumericTraits<OutputImagePixelType>::OneValue(pix) *
>>> value;
>>>
>>> It works for both cases with the same code. However, if there is a
>>> better
>>> way (cleaner, safer, more compact, ... whatever the wayin which it is
>>> better), I'd be happy to learn about it.
>>>
>>> Best regards,
>>> Cyril
>>>
>>>
>>> On 22/02/2017 10:38, Cyril Mory wrote:
>>>> Hi ITK users,
>>>>
>>>> I am writing an itk::ImageToImageFilter<T>, and I want the filter
>>>> to work
>>>> with T=itk::Image as well as with T=itk::VectorImage.
>>>>
>>>> To set/get the vectorLength of an image (which is 1 for an
>>>> itk::Image, and
>>>> varies for an itk::VectorImage), I have successfully used the
>>>> functions
>>>> Set/GetNumberOfComponentsPerPixel from the itk::ImageBase class,
>>>> which work
>>>> for both itk::Image and itk::VectorImage.
>>>>
>>>> But I cannot find a way to initialize one of the pixels to a given
>>>> value,
>>>> that would work for both cases, i.e. whether that pixel is a scalar
>>>> or a
>>>> variableLengthVector. For now, the best I could do is define a
>>>> function
>>>> FillPixel in my filter, like this:
>>>>
>>>> OutputImagePixelType FillPixel(OutputImageInternalPixelType value)
>>>> {return
>>>> value;}
>>>>
>>>> and write a template specialization when my filter is instantiated
>>>> with
>>>> itk::VectorImage<float, 3>, like this:
>>>>
>>>> template <>
>>>> itk::VariableLengthVector<float>
>>>> rtk::ConstantImageSource<itk::VectorImage<float, 3> >
>>>> ::FillPixel(float value)
>>>> {
>>>> itk::VariableLengthVector<float> vect;
>>>> vect.SetSize(this->GetVectorLength());
>>>> vect.Fill(value);
>>>> return (vect);
>>>> }
>>>>
>>>> Did I miss something ? Is there a better way of doing this in ITK ?
>>>>
>>>> Looking forward to reading you,
>>>> Cyril
>>>>
>>>> _____________________________________
>>>> Powered by www.kitware.com
>>>>
>>>> Visit other Kitware open-source projects at
>>>> http://www.kitware.com/opensource/opensource.html
>>>>
>>>> Kitware offers ITK Training Courses, for more information visit:
>>>> http://www.kitware.com/products/protraining.php
>>>>
>>>> Please keep messages on-topic and check the ITK FAQ at:
>>>> http://www.itk.org/Wiki/ITK_FAQ
>>>>
>>>> Follow this link to subscribe/unsubscribe:
>>>> http://public.kitware.com/mailman/listinfo/insight-users
>>>
>>> _____________________________________
>>> Powered by www.kitware.com
>>>
>>> Visit other Kitware open-source projects at
>>> http://www.kitware.com/opensource/opensource.html
>>>
>>> Kitware offers ITK Training Courses, for more information visit:
>>> http://www.kitware.com/products/protraining.php
>>>
>>> Please keep messages on-topic and check the ITK FAQ at:
>>> http://www.itk.org/Wiki/ITK_FAQ
>>>
>>> Follow this link to subscribe/unsubscribe:
>>> http://public.kitware.com/mailman/listinfo/insight-users
>
More information about the Insight-users
mailing list