Как я могу преобразовать образ CImg в itkImage?

У меня есть изображение CImg (с двойными значениями) со следующей формой на С++:

CImg<double> image(512,512);
Tcyl.fill(1);

Я хотел бы использовать функциональность ITK для преобразования этого изображения. Поэтому мне нужно преобразовать это изображение CImg в объект itkImage. Как я могу конвертировать?


person PeetRoxor    schedule 25.11.2017    source источник
comment
Это должно помочь... stackoverflow.com/q/26584208/2836621 Если нет, опубликуйте свой код и укажите, какой аспект не не работает правильно.   -  person Mark Setchell    schedule 25.11.2017
comment
Спасибо, я постараюсь. Функция принимает CImg ‹uchar› в качестве параметра. Мне нужно преобразовать мой CImg ‹double› в CImg ‹uchar›?   -  person PeetRoxor    schedule 25.11.2017
comment
Если ваш CImg содержит double, вы можете получить указатель на их начало, используя image.data()   -  person Mark Setchell    schedule 25.11.2017
comment
Если производительность не совсем критична, просто создайте свой образ ITK того же размера и напишите два вложенных цикла, копирующих из CImg в образ ITK, и улучшите скорость позже.   -  person Mark Setchell    schedule 25.11.2017


Ответы (1)


Я никогда раньше не пользовался ITK, так что пришлось учиться. Во всяком случае, мне удалось создать радиальный градиент плавающих элементов в CImg и преобразовать его в изображение ITK, а затем записать его как число с плавающей запятой TIFF.

#include <iostream>
#include <cstdlib>
#define cimg_display 0
#include "CImg.h"
#include "itkImage.h"
#include "itkImportImageFilter.h"
#include "itkImageFileWriter.h"
#include "itkTIFFImageIO.h"

using namespace cimg_library;
using namespace std;

#define W       512
#define H       512

int main() {
    // Create and initialise float image with radial gradient
   cimg_library::CImg<float> img(W,H); 
   cimg_forXY(img,x,y) {img(x,y) = hypot((float)(W/2-x),(float)(H/2-y)); }

   // Now convert CImg image to ITK image
   const unsigned int Dimension = 2;
   typedef itk::Image<float,Dimension>             InputImageType;
   typedef itk::ImportImageFilter<float,Dimension> ImportFilterType;
   ImportFilterType::Pointer importFilter = ImportFilterType::New();

   InputImageType::SizeType imsize;
   imsize[0] = img.width();
   imsize[1] = img.height();

   ImportFilterType::IndexType start;
   start.Fill(0);
   ImportFilterType::RegionType region;
   region.SetIndex(start);
   region.SetSize(imsize);
   importFilter->SetRegion(region);

   const itk::SpacePrecisionType origin[Dimension] = {0.0,0.0};
   importFilter->SetOrigin(origin);

   const itk::SpacePrecisionType spacing[Dimension] = {1.0,1.0};
   importFilter->SetSpacing(spacing);

   // Tell ITK importFilter to take pixels directly from CImg's buffer
   importFilter->SetImportPointer(img.data(),imsize[0]*imsize[1],false);

   // Write result as a TIFF - so I can check it worked
   typedef itk::ImageFileWriter<InputImageType> WriterType;
   typedef itk::TIFFImageIO                  TIFFIOType;
   TIFFIOType::Pointer tiffIO = TIFFIOType::New();
   tiffIO->SetPixelType(itk::ImageIOBase::SCALAR);
   WriterType::Pointer writer = WriterType::New();
   writer->SetFileName("result.tif");
   writer->SetInput(importFilter->GetOutput());
   writer->SetImageIO(tiffIO);
   writer->Update();
}

И вот результат (преобразованный в JPEG для SO):

введите здесь описание изображения

Это работает точно так же, если вы замените float на double, за исключением того, что вы не можете записать doubles в TIFF, поэтому последний бит не будет работать.


Я еще немного повозился и сумел загрузить пиксели в новое изображение ITK, готовое для дальнейшей обработки, а не для вывода:

#include <iostream>
#include <cstdlib>
#define cimg_display 0
#include "CImg.h"
#include "itkImage.h"
#include "itkImageRegionIterator.h"

using namespace cimg_library;
using namespace std;

#define W 5
#define H 3

int main() {
    // Create and initialise double image with simple formula
   cimg_library::CImg<double> img(W,H); 
   cimg_forXY(img,x,y) {img(x,y) = (double)x+(10.0*(double)y); }

   // Now convert CImg image to ITK image
   const unsigned int Dimension = 2;
   typedef itk::Image<double,2> ImageType;
   ImageType::Pointer image = ImageType::New();

   ImageType::SizeType size;
   size[0] = img.width();
   size[1] = img.height();

   ImageType::IndexType start;
   start.Fill(0);

   ImageType::RegionType region;
   region.SetSize(size);
   region.SetIndex(start);
   image->SetRegions(region);
   image->Allocate();

   double origin[2];
   origin[0]=0;
   origin[1]=0;
   image->SetOrigin(origin);

   double spacing[2];
   spacing[0]=1;
   spacing[1]=1;
   image->SetSpacing(spacing);

   typedef itk::ImageRegionIterator<ImageType> IteratorType;
   IteratorType it(image,region);
   it.GoToBegin();

   const double* data = img.data();
   while(!it.IsAtEnd()){
      it.Set(*data);
      ++it;
      ++data;
   }

  // Display pixels for checking purposes
  for(unsigned int r = 0; r < H; r++)
  {
      for(unsigned int c = 0; c < W; c++)
      {
          ImageType::IndexType pixelIndex;
          pixelIndex[0] = c;
          pixelIndex[1] = r;
          ImageType::PixelType      pixelValue = image->GetPixel( pixelIndex );
          cout << "Image[" << r << "," << c << "]: " << pixelValue << endl; 
      }
  }
}

Пример вывода

Image[0,0]: 0
Image[0,1]: 1
Image[0,2]: 2
Image[0,3]: 3
Image[0,4]: 4
Image[1,0]: 10
Image[1,1]: 11
Image[1,2]: 12
Image[1,3]: 13
Image[1,4]: 14
Image[2,0]: 20
Image[2,1]: 21
Image[2,2]: 22
Image[2,3]: 23
Image[2,4]: 24
person Mark Setchell    schedule 29.11.2017