使用ITK访问tif图像的像素值

时间:2014-11-10 22:08:40

标签: c++ itk

我是ITK的新手,我正在尝试使用ITK读取tif文件并访问其像素。以下是我为此目的编写的代码:

    typedef float PixelType;   // Pixel type
    const unsigned char Dimension = 2;
    typedef itk::Image< PixelType, Dimension > ImageType; 
    ImageType::Pointer image;

    typedef itk::ImageFileReader< ImageType > ReaderType;
    ReaderType::Pointer reader;
    reader = ReaderType::New();

    const char * filename = "test.tif";
    reader->SetImageIO(itk::TIFFImageIO::New());
    reader->SetFileName(filename);

    try
    {
        reader->Update();
    }
    catch (itk::ExceptionObject & excp)
    {
        std::cerr << excp << std::endl;
    }

    // Access to a pixel
    ImageType::IndexType pixelIndex;
    pixelIndex[0] = 103;
    pixelIndex[1] = 178;
    ImageType::PixelType pixelValue = image->GetPixel(pixelIndex);
    std::cout << "pixel : " << pixelValue << std::endl;

我得到的像素值与正确的值不匹配!我用MATLAB来检查我的测试图像。这是它的尺寸:&lt; 298x237x4 uint8&gt;。

我尝试使用MATLAB将图像(:,:,1)(即&lt; 298x237 uint8&gt;)存储为新的tif图像,然后将此图像作为输入图像传递给上面的程序。它正在工作,我得到了我预期的正确像素值!

我知道问题是什么,但我不知道如何解决它。我不知道如何修改我的程序以提取&lt; 298x237 uint8&gt;图像超出&lt; 298x237x4 uint8&gt;输入图像。


更新

以下是我从tiffinfo获取的信息: enter image description here

1 个答案:

答案 0 :(得分:1)

您的文件包含RGBA的像素,但您正在将它们读取为只有浮动的图像。

快速解决方案是只更改此typedef:

typedef float PixelType;   // Pixel type

为:

typedef itk::RGBAPixel<float> PixelType;   // Pixel type

使用ITK指定ImageFileReader时,您要指定所需的类型作为输出。 ITK将隐式执行转换为您请求的类型。在您的情况下,您要求从RGBA转换为浮动。

通过直接构建ImageIO,您可以从文件中获取像素类型信息。以下是Wiki Examples

的示例
  std::string inputFilename = argv[1];

  typedef itk::ImageIOBase::IOComponentType ScalarPixelType;

  itk::ImageIOBase::Pointer imageIO =
        itk::ImageIOFactory::CreateImageIO(
            inputFilename.c_str(), itk::ImageIOFactory::ReadMode);

  imageIO->SetFileName(inputFilename);
  imageIO->ReadImageInformation();
  const ScalarPixelType pixelType = imageIO->GetComponentType();
  std::cout << "Pixel Type is " << imageIO->GetComponentTypeAsString(pixelType) // 'double'
            << std::endl;
  const size_t numDimensions =  imageIO->GetNumberOfDimensions();
  std::cout << "numDimensions: " << numDimensions << std::endl; // '2'

  std::cout << "component size: " << imageIO->GetComponentSize() << std::endl; // '8'
  std::cout << "pixel type (string): " << imageIO->GetPixelTypeAsString(imageIO->GetPixelType()) << std::endl; // 'vector'
  std::cout << "pixel type: " << imageIO->GetPixelType() << std::endl; // '5'

  /*
  switch (pixelType)
  {
    case itk::ImageIOBase::COVARIANTVECTOR:
      typedef itk::Image<unsigned char, 2> ImageType;
      ImageType::Pointer image = ImageType::New();
      ReadFile<ImageType>(inputFilename, image);
      break;

      typedef itk::Image<unsigned char, 2> ImageType;
      ImageType::Pointer image = ImageType::New();
      ReadFile<ImageType>(inputFilename, image);
      break;

    default:
      std::cerr << "Pixel Type ("
                << imageIO->GetComponentTypeAsString(pixelType)
                << ") not supported. Exiting." << std::endl;
      return -1;
  }
  */

我还参与了SimpleITK项目,该项目为ITK提供了简化的层,专为快速原型设计和交互式计算而设计,例如脚本语言。它添加了一个自动将图像加载到正确类型的图层。如果你来自Matlab,这可能是一个更容易的过渡。