Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
565 views
in Technique[技术] by (71.8m points)

c++ - Convert Cimg to ITK

I'm trying to convert a Cimg image to itk image to use it for registration algorithm. The Cimg is a RGB image and i want to convert it to RGB itk image. Her is my code :

void Cimg_To_ITK (CImg<uchar> img)
{

    const unsigned int Dimension = 2;
    typedef itk::RGBPixel< unsigned char > RGBPixelType;
    typedef itk::Image< RGBPixelType, Dimension > RGBImageType;
    typedef itk::ImportImageFilter< RGBPixelType, Dimension > ImportFilterType;
    ImportFilterType::Pointer importFilter = ImportFilterType::New();
    typedef itk::ImageFileWriter<  RGBImageType  > WriterType;
    WriterType::Pointer writer = WriterType::New();


    RGBImageType::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 );

    const unsigned int numberOfPixels = imsize[0] * imsize[1];
    const bool importImageFilterWillOwnTheBuffer = true;

    RGBPixelType * localBuffer = new RGBPixelType[ numberOfPixels ];
    RGBPixelType * it = localBuffer;
    memcpy(*it, img.data(), numberOfPixels);

    importFilter->SetImportPointer( localBuffer, numberOfPixels,importImageFilterWillOwnTheBuffer );

    writer->SetFileName( "output.png" );
}

I get this error at compilation :

error: cannot convert 'RGBPixelType {aka itk::RGBPixel}' to 'void*' for argument '1' to 'void* memcpy(void*, const void*, size_t)

What is wrong??

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

*it is a RGBPixelType, it can't be converted to a void pointer and memcpy() can't handle it. memcpy() needs pointers to values, such as img.data() or it. According to the documentation of CImg :

T* data () Return a pointer to the first pixel value.

An example of how to import an image from a buffer of values is provided by ITK here . My guess is that it is your starting point.

The other issue that you will soon face is the size of the image : RBG is 3 bytes per pixel, so it should be

memcpy(it, img.data(), numberOfPixels*3);

Here is an example of how to import a buffer of unsigned char as an ITK RGB Image, starting from your code. Feel free to edit this answer and add the function to handle a CImg !

#include <iostream>
#include <itkImage.h>

using namespace itk;
using namespace std;

#include <itkImportImageFilter.h>
#include <itkImageFileWriter.h>

void Cimg_To_ITK (unsigned char* data)
{

    const unsigned int Dimension = 2;
    typedef itk::RGBPixel< unsigned char > RGBPixelType;
    typedef itk::Image< RGBPixelType, Dimension > RGBImageType;
    typedef itk::ImportImageFilter< RGBPixelType, Dimension > ImportFilterType;
    ImportFilterType::Pointer importFilter = ImportFilterType::New();
    typedef itk::ImageFileWriter<  RGBImageType  > WriterType;
    WriterType::Pointer writer = WriterType::New();


    RGBImageType::SizeType imsize;
    // imsize[0] = img.width();
    // imsize[1] = img.height();
    imsize[0] = 100;
    imsize[1] = 200;

    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 );

    const unsigned int numberOfPixels = imsize[0] * imsize[1];

    const bool importImageFilterWillOwnTheBuffer = true;

    RGBPixelType * localBuffer = new RGBPixelType[ numberOfPixels ];
    RGBPixelType * it = localBuffer;
    memcpy(it, data, numberOfPixels*3);
    // no need to delete localBuffer : itk will care since importImageFilterWillOwnTheBuffer=true
    importFilter->SetImportPointer( localBuffer, numberOfPixels,importImageFilterWillOwnTheBuffer );

    writer->SetFileName( "output.png" );
    writer->SetInput(importFilter->GetOutput() );
    writer->Update();

}

int main()
{
    unsigned char* data=new unsigned char[100*200*3];
    for(int i=0;i<200;i++){
        for(int j=0;j<100;j++){
            data[(i*100+j)*3]=i;
            data[(i*100+j)*3+1]=0;
            data[(i*100+j)*3+2]=j;
        }

    }

    Cimg_To_ITK (data);

    delete[] data;
    cout<<"running fine"<<endl;
    return 0;
}

The file CMakeLists.txt :

cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(ItkTest)

find_package(ITK REQUIRED)
include(${ITK_USE_FILE})

add_executable(MyTest main.cpp)
target_link_libraries(MyTest ${ITK_LIBRARIES})

After installing ITK and setting the environment variable ITK_DIR, type cmake . and make to build this example.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...