<div dir="ltr"><div><div><div>Hey Cyril,<br><br></div>This is a good idea. If you want to keep it compatible without requiring C++11, you might be able to do so using the "EnableIf" functions that are implemented in ITK, following the same paradigm (SFINAE) than you found.<br><br></div>hth,<br></div>Francois<br></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Feb 27, 2017 at 10:24 AM, Cyril Mory <span dir="ltr"><<a href="mailto:cyril.mory@creatis.insa-lyon.fr" target="_blank">cyril.mory@creatis.insa-lyon.fr</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">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.<br>
<br>
<br>
<br>
#include <itkImage.h><br>
#include <itkVectorImage.h><br>
#include <itkImageToImageFilter.h><br>
#include <itkImageFileReader.h><br>
#include <itkImageRegionConstIterator.h<wbr>><br>
#include <itkImageRegionIterator.h><br>
<br>
#include <type_traits><br>
#include <typeinfo><br>
<br>
namespace itk<br>
{<br>
<br>
template <class TInputImage ><br>
class ITK_EXPORT SFINAETestFilter :<br>
    public itk::ImageToImageFilter< TInputImage, TInputImage ><br>
{<br>
public:<br>
  /** Standard class typedefs. */<br>
  typedef SFINAETestFilter Self;<br>
  typedef itk::ImageToImageFilter<TInput<wbr>Image, TInputImage> Superclass;<br>
  typedef itk::SmartPointer<Self> Pointer;<br>
  typedef itk::SmartPointer<const Self> ConstPointer;<br>
<br>
  // Define the types that a slice can take, depending on whether TInputImage is an itk::Image or and itk::VectorImage<br>
  typedef itk::Image<typename TInputImage::InternalPixelType<wbr>, TInputImage::ImageDimension - 1>          ImageSliceType;<br>
  typedef itk::VectorImage<typename TInputImage::InternalPixelType<wbr>, TInputImage::ImageDimension - 1>    VectorImageSliceType;<br>
<br>
  // Define SliceType<br>
  // std::is_same<T1, T2>::value is true is T1 and T2 are the same type, and false otherwise<br>
  // std::conditional<B, T3, T4>::type is T3 if B is true, T4 otherwise<br>
  // The code checks if TInputImage::PixelType is an itk::VariableLengthVector. If so, it uses VectorImageSliceType as SliceType<br>
  // Otherwise, it uses ImageSliceType as SliceType<br>
  typedef typename std::conditional<std::is_same<<wbr>typename TInputImage::PixelType,<br>
itk::VariableLengthVector<type<wbr>name TInputImage::InternalPixelType<wbr>> >::value,<br>
                                    VectorImageSliceType,<br>
                                    ImageSliceType>::type SliceType;<br>
<br>
  /** Method for creation through the object factory */<br>
  itkNewMacro(Self);<br>
<br>
  /** Run-time type information (and related methods). */<br>
  itkTypeMacro(SFINAETestFilter, ImageToImageFilter);<br>
<br>
  /** Superclass typedefs. */<br>
  typedef typename Superclass::OutputImageRegionT<wbr>ype OutputImageRegionType;<br>
  typedef typename Superclass::OutputImagePointer OutputImagePointer;<br>
<br>
  /** ImageDimension constants */<br>
  itkStaticConstMacro(InputImage<wbr>Dimension, unsigned int,<br>
                      TInputImage::ImageDimension);<br>
<br>
  typename SliceType::Pointer GetSlice()<br>
  {<br>
  // Create the slice<br>
  typename SliceType::Pointer firstSlice = SliceType::New();<br>
<br>
  // Determine its size<br>
  typename TInputImage::RegionType largest = this->GetInput()->GetLargestPo<wbr>ssibleRegion();<br>
  typename SliceType::RegionType region;<br>
  typename SliceType::SizeType size;<br>
  typename SliceType::IndexType index;<br>
  for (unsigned int dim = 0; dim < SliceType::ImageDimension; dim++)<br>
    {<br>
    size[dim] = largest.GetSize()[dim];<br>
    index[dim] = largest.GetIndex()[dim];<br>
    }<br>
  region.SetSize(size);<br>
  region.SetIndex(index);<br>
<br>
  // Allocate<br>
  firstSlice->SetRegions(region)<wbr>;<br>
firstSlice->SetNumberOfCompone<wbr>ntsPerPixel(this->GetInput()-><wbr>GetNumberOfComponentsPerPixel(<wbr>)); <br>
  firstSlice->Allocate();<br>
<br>
  // Fill<br>
  itk::ImageRegionIterator<Slice<wbr>Type> sliceIt(firstSlice, region);<br>
  itk::ImageRegionConstIterator<<wbr>TInputImage> inputIt(this->GetInput(), largest);<br>
  while(!sliceIt.IsAtEnd())<br>
    {<br>
    sliceIt.Set(inputIt.Get());<br>
    ++sliceIt;<br>
    ++inputIt;<br>
    }<br>
<br>
  // Return<br>
  return firstSlice;<br>
  }<br>
<br>
};<br>
<br>
} /* end namespace itk */<br>
<br>
<br>
int main(){<br>
<br>
typedef itk::Image<float, 3> ImageType;<br>
typedef itk::VectorImage<float, 3> VectorImageType;<br>
<br>
// With the itk::Image template<br>
typedef itk::SFINAETestFilter<ImageTyp<wbr>e> SFINAEWithImageType;<br>
typename SFINAEWithImageType::Pointer withImageType = SFINAEWithImageType::New();<br>
typedef itk::ImageFileReader<ImageType<wbr>> ImageReaderType;<br>
ImageReaderType::Pointer imageReader = ImageReaderType::New();<br>
imageReader->SetFileName("imag<wbr>e.mha");<br>
imageReader->Update();<br>
withImageType->SetInput(imageR<wbr>eader->GetOutput());<br>
withImageType->GetSlice()->Pri<wbr>nt(std::cout);<br>
<br>
itk::Image<float, 2>::IndexType firstPixelIndex;<br>
firstPixelIndex.Fill(0);<br>
std::cout << withImageType->GetSlice()->Get<wbr>Pixel(firstPixelIndex) << std::endl;<br>
<br>
// With the itk::VectorImage template<br>
typedef itk::SFINAETestFilter<VectorIm<wbr>ageType> SFINAEWithVectorImageType;<br>
typename SFINAEWithVectorImageType::Poi<wbr>nter withVectorImageType = SFINAEWithVectorImageType::New<wbr>();<br>
typedef itk::ImageFileReader<VectorIma<wbr>geType> VectorImageReaderType;<br>
VectorImageReaderType::Pointer vectorImageReader = VectorImageReaderType::New();<br>
vectorImageReader->SetFileName<wbr>("vectorImage.mha");<br>
vectorImageReader->Update();<br>
withVectorImageType->SetInput(<wbr>vectorImageReader->GetOutput()<wbr>);<br>
withVectorImageType->GetSlice(<wbr>)->Print(std::cout);<br>
<br>
std::cout << withVectorImageType->GetSlice(<wbr>)->GetPixel(firstPixelIndex) << std::endl;<br>
<br>
return EXIT_SUCCESS;<div class="HOEnZb"><div class="h5"><br>
}<br>
<br>
<br>
<br>
On 27/02/2017 12:09, Cyril Mory wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hi,<br>
<br>
Still the same topic, but a different issue:<br>
<br>
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>.<br>
<br>
This filter internally defines SliceType = itk::Image<InputImageType::Int<wbr>ernalPixelType, dim - 1>. But when processing an itk::VectorImage, I would like this SliceType to be itk::VectorImage<InputImageTyp<wbr>e::InternalPixelType, dim - 1>.<br>
<br>
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 ?<br>
<br>
Best regards,<br>
<br>
Cyril<br>
<br>
On 22/02/2017 17:39, Matt McCormick wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hi Cyril,<br>
<br>
Yes, this is a good approach.  Thanks for sharing your investigation.<br>
<br>
Matt<br>
<br>
On Wed, Feb 22, 2017 at 5:52 AM, Cyril Mory<br>
<<a href="mailto:cyril.mory@creatis.insa-lyon.fr" target="_blank">cyril.mory@creatis.insa-lyon.<wbr>fr</a>> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Answering my own question:<br>
<br>
I found a way to do what I needed using itk::NumericTraits<T> :<br>
<br>
   OutputImagePixelType pix;<br>
itk::NumericTraits<OutputImage<wbr>PixelType>::SetLength(pix,<br>
this->GetVectorLength());<br>
   pix = itk::NumericTraits<OutputImage<wbr>PixelType>::OneValue(pix) * value;<br>
<br>
It works for both cases with the same code. However, if there is a better<br>
way (cleaner, safer, more compact, ... whatever the wayin which it is<br>
better), I'd be happy to learn about it.<br>
<br>
Best regards,<br>
Cyril<br>
<br>
<br>
On 22/02/2017 10:38, Cyril Mory wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hi ITK users,<br>
<br>
I am writing an itk::ImageToImageFilter<T>, and I want the filter to work<br>
with T=itk::Image as well as with T=itk::VectorImage.<br>
<br>
To set/get the vectorLength of an image (which is 1 for an itk::Image, and<br>
varies for an itk::VectorImage), I have successfully used the functions<br>
Set/GetNumberOfComponentsPerPi<wbr>xel from the itk::ImageBase class, which work<br>
for both itk::Image and itk::VectorImage.<br>
<br>
But I cannot find a way to initialize one of the pixels to a given value,<br>
that would work for both cases, i.e. whether that pixel is a scalar or a<br>
variableLengthVector. For now, the best I could do is define a function<br>
FillPixel in my filter, like this:<br>
<br>
OutputImagePixelType FillPixel(OutputImageInternalP<wbr>ixelType value) {return<br>
value;}<br>
<br>
and write a template specialization when my filter is instantiated with<br>
itk::VectorImage<float, 3>, like this:<br>
<br>
template <><br>
itk::VariableLengthVector<floa<wbr>t><br>
rtk::ConstantImageSource<itk::<wbr>VectorImage<float, 3> ><br>
::FillPixel(float value)<br>
{<br>
   itk::VariableLengthVector<flo<wbr>at> vect;<br>
   vect.SetSize(this->GetVectorL<wbr>ength());<br>
   vect.Fill(value);<br>
   return (vect);<br>
}<br>
<br>
Did I miss something ? Is there a better way of doing this in ITK ?<br>
<br>
Looking forward to reading you,<br>
Cyril<br>
<br>
______________________________<wbr>_______<br>
Powered by <a href="http://www.kitware.com" rel="noreferrer" target="_blank">www.kitware.com</a><br>
<br>
Visit other Kitware open-source projects at<br>
<a href="http://www.kitware.com/opensource/opensource.html" rel="noreferrer" target="_blank">http://www.kitware.com/opensou<wbr>rce/opensource.html</a><br>
<br>
Kitware offers ITK Training Courses, for more information visit:<br>
<a href="http://www.kitware.com/products/protraining.php" rel="noreferrer" target="_blank">http://www.kitware.com/product<wbr>s/protraining.php</a><br>
<br>
Please keep messages on-topic and check the ITK FAQ at:<br>
<a href="http://www.itk.org/Wiki/ITK_FAQ" rel="noreferrer" target="_blank">http://www.itk.org/Wiki/ITK_FA<wbr>Q</a><br>
<br>
Follow this link to subscribe/unsubscribe:<br>
<a href="http://public.kitware.com/mailman/listinfo/insight-users" rel="noreferrer" target="_blank">http://public.kitware.com/mail<wbr>man/listinfo/insight-users</a><br>
</blockquote>
<br>
______________________________<wbr>_______<br>
Powered by <a href="http://www.kitware.com" rel="noreferrer" target="_blank">www.kitware.com</a><br>
<br>
Visit other Kitware open-source projects at<br>
<a href="http://www.kitware.com/opensource/opensource.html" rel="noreferrer" target="_blank">http://www.kitware.com/opensou<wbr>rce/opensource.html</a><br>
<br>
Kitware offers ITK Training Courses, for more information visit:<br>
<a href="http://www.kitware.com/products/protraining.php" rel="noreferrer" target="_blank">http://www.kitware.com/product<wbr>s/protraining.php</a><br>
<br>
Please keep messages on-topic and check the ITK FAQ at:<br>
<a href="http://www.itk.org/Wiki/ITK_FAQ" rel="noreferrer" target="_blank">http://www.itk.org/Wiki/ITK_FA<wbr>Q</a><br>
<br>
Follow this link to subscribe/unsubscribe:<br>
<a href="http://public.kitware.com/mailman/listinfo/insight-users" rel="noreferrer" target="_blank">http://public.kitware.com/mail<wbr>man/listinfo/insight-users</a><br>
</blockquote></blockquote>
<br>
</blockquote>
<br>
______________________________<wbr>_______<br>
Powered by <a href="http://www.kitware.com" rel="noreferrer" target="_blank">www.kitware.com</a><br>
<br>
Visit other Kitware open-source projects at<br>
<a href="http://www.kitware.com/opensource/opensource.html" rel="noreferrer" target="_blank">http://www.kitware.com/opensou<wbr>rce/opensource.html</a><br>
<br>
Kitware offers ITK Training Courses, for more information visit:<br>
<a href="http://www.kitware.com/products/protraining.php" rel="noreferrer" target="_blank">http://www.kitware.com/product<wbr>s/protraining.php</a><br>
<br>
Please keep messages on-topic and check the ITK FAQ at:<br>
<a href="http://www.itk.org/Wiki/ITK_FAQ" rel="noreferrer" target="_blank">http://www.itk.org/Wiki/ITK_FA<wbr>Q</a><br>
<br>
Follow this link to subscribe/unsubscribe:<br>
<a href="http://public.kitware.com/mailman/listinfo/insight-users" rel="noreferrer" target="_blank">http://public.kitware.com/mail<wbr>man/listinfo/insight-users</a><br>
</div></div></blockquote></div><br></div>