nm97
(Hrach)
July 3, 2019, 10:54am
1
How can I specify image channels.
I have created image object.
using ImageType = itk::Image< uint8_t, 2 >;
ImageType::Pointer image = ImageType::New();
ImageType::SizeType size;
size[0] = width;
size[1] = height;
ImageType::IndexType start;
start.Fill( 0 );
ImageType::RegionType region;
region.SetSize( size );
region.SetIndex( start );
image->SetRegions( region );
image->Allocate();
I can specify size, start but could not find in documentation how to specify image channels.
dzenanz
(Dženan ZukiÄ)
July 3, 2019, 2:30pm
2
You just have to define vector image type.
using VectorPixelType = itk::Vector<uint8_t, 10>; // 10 channel pixel
using ImageType = itk::Image< VectorPixelType, 2 >; // 2D image
Read more about it in the software guide , section 4.1.6.
nm97
(Hrach)
July 3, 2019, 2:57pm
3
Thank you very much for quick response.
In that case I get an error in this line
rescaler->SetOutputMaximum( 255 );
rescaler->SetOutputMinimum( 0 );
error: conversion from āintā to āitk::RescaleIntensityImageFilter<itk::Image<itk::Vector<float, 3>, 2>, itk::Image<itk::Vector<unsigned char, 3>, 2> >::OutputPixelTypeā {aka āitk::Vector<unsigned char, 3>ā} is ambiguous
180 | rescaler->SetOutputMinimum( 0 );
These methods expect arguments of same type as the pixels in your image. Since the pixel in your image is a vector (aka multi-channel image), you should input a vector.
Giving only one value is ambiguous, i.e. in which channel should the value goes ? first? all?
If itās the latter, you could do something like:
itk::Vector<uint8_t, 3> MaxPixel, MinPixel;
MaxPixel[0] = MaxPixel[1] = MaxPixel[2] = 255;
MinPixel[0] = MinPixel[1] = MinPixel[2] = 0;
rescaler->SetOutputMaximum( MaxPixel );
rescaler->SetOutputMinimum( MinPixel );
HTH,
Tim
1 Like
nm97
(Hrach)
July 3, 2019, 4:50pm
5
In that case I get an error in the last line
using VectorPixelType = itk::Vector<uint8_t, 3>; // 10 channel pixel
using ImageType = itk::Image< VectorPixelType, 2 >; // 2D image
using OutputVectorPixelType = itk::Vector<float, 3>;
// using OutputPixelType = float;
using OutputImageType = itk::Image< OutputVectorPixelType, 2 >;
using FilterType = itk::MinMaxCurvatureFlowImageFilter< ImageType, OutputImageType >;
FilterType::Pointer filter = FilterType::New();
invalid static_cast from type āitk::Vector<unsigned char, 3>ā to type āfloatā
185 | auto b = static_cast< T2 >( a );
dzenanz
(Dženan ZukiÄ)
July 3, 2019, 5:01pm
6
I guess that MinMaxCurvatureFlowImageFilter
does not support vector images. You might use SplitComponentsImageFilter or VectorImageToImageAdaptor to split the image into constituent channels, apply some processing on each channel independently, and combine them using ComposeImageFilter .
1 Like
blowekamp
(Bradley Lowekamp)
July 3, 2019, 5:28pm
7
Here is a snippet of code generated in SimpleITK which run certain filters on a āper component basisā:
//
// Dispatched methods to call ExecuteInternal on each component of the VectorImage
//
template <class TImageType> Image BilateralImageFilter::ExecuteInternalVectorImage ( const Image& inImage1 )
{
typedef TImageType VectorInputImageType;
typedef typename VectorInputImageType::InternalPixelType ComponentType;
typedef typename itk::Image<ComponentType, VectorInputImageType::ImageDimension> ComponentImageType;
// we must define the input and output image types should be the
// same as the scalar execute internal method
typedef ComponentImageType InputImageType;
// Define output image type
typedef InputImageType OutputImageType;
// Get the pointer to the ITK image contained in image1
typename VectorInputImageType::ConstPointer image1 =
this->CastImageToITK<VectorInputImageType>( inImage1 );
typedef itk::VectorIndexSelectionCastImageFilter< VectorInputImageType, ComponentImageType > ComponentExtratorType;
typename ComponentExtratorType::Pointer extractor = ComponentExtratorType::New();
extractor->SetInput( image1 );
typedef itk::ComposeImageFilter<OutputImageType> ToVectorFilterType;
typename ToVectorFilterType::Pointer toVector = ToVectorFilterType::New();
unsigned int numComps = image1->GetNumberOfComponentsPerPixel();
for ( unsigned int i = 0; i < numComps; ++i )
{
extractor->SetIndex( i );
extractor->Update();
Image tmp = this->ExecuteInternal<InputImageType>( Image( extractor->GetOutput() ) );
typename OutputImageType::ConstPointer tempITKImage = this->CastImageToITK<OutputImageType>( tmp );
toVector->SetInput( i, tempITKImage );
}
toVector->Update();
return Image( toVector->GetOutput() );
}
nm97
(Hrach)
July 3, 2019, 5:44pm
8
Ok, but in InsightToolkit-5.0.0/Examples/Filtering/MinMaxCurvatureFlowImageFilter.cxx in this example input image has 3 channels and still it does not specify the number of channels.
But still it filters image and writes in the file as a multichanel image
nm97
(Hrach)
July 3, 2019, 6:02pm
9
And one more question,
If MaxCurvatureFlowImageFilter
does not support vector images how can I filter multi channel images without using vector? Because as I said in example there is no use of vector, but it filters fine
dzenanz
(Dženan ZukiÄ)
July 3, 2019, 6:34pm
10
Instead of itk::Vector<uint8_t, 3>
, you might want to try itk::RGBPixel<uint8_t>
.
In the example you mentioned, the pixel type is scalar = grayscale (float). If color image is supplied, the IO mechanism in ITK converts it to grayscale and the example deals with that afterwards.
1 Like