[Insight-users] Nifti vs Dicom orientation
Elena Faggiano
elena.faggiano at gmail.com
Tue Apr 28 09:06:02 EDT 2009
Hi Antoine,
probably I had the same problem with DICOM converted in NIFTI using MIPAV (
http://mipav.cit.nih.gov/).
I solved the problem flipping and shifting the NIFTI file:
int main( int argc, char ** argv )
{
typedef short PixelType;
const unsigned int Dimension = 3;
typedef itk::OrientedImage< PixelType, Dimension > ImageType;
typedef itk::ImageFileReader< ImageType > ReaderType;
typedef itk::ImageFileWriter< ImageType > WriterType;
ReaderType::Pointer reader = ReaderType::New();
WriterType::Pointer writer = WriterType::New();
const char * inputFilename = argv[1];
const char * outputFilename = argv[2];
reader->SetFileName( inputFilename );
writer->SetFileName( outputFilename );
reader->Update();
reader->GetOutput()->Print(std::cout);
typedef itk::FlipImageFilter< ImageType> FlipType;
FlipType::Pointer flip = FlipType::New();
FlipType::FlipAxesArrayType flipAxesSet;
flipAxesSet[0] = 0;
flipAxesSet[1] = -1;
flipAxesSet[2] = 0;
flip->SetFlipAxes(flipAxesSet);
flip->FlipAboutOriginOff();
flip->SetInput(reader->GetOutput());
flip->Update();
flip->GetOutput()->Print(std::cout);
ImageType::Pointer image = ImageType::New();
image = flip->GetOutput();
image->SetOrigin(reader->GetOutput()->GetOrigin());
image->Print(std::cout);
writer->SetInput(image);
}
In this way if I read the original DICOM with itk I obtain:
TransformMatrix = 1 0 0 0 1 0 0 0 1
Offset = -250 -250 -515.03
AnatomicalOrientation = RAI
The NIFTI image converted using MIPAV is:
TransformMatrix = 1 0 0 0 -1 0 0 0 1
Offset = -250 -250 -515.03
AnatomicalOrientation = RPI
While the NIFTI image after flip and shif is:
TransformMatrix = 1 0 0 0 1 0 0 0 1
Offset = -250 -250 -515.03
AnatomicalOrientation = RAI
Also, if I use Paraview to see the images (after a conversion in .mhd
format) the original and the flipped and shifted one are consistent (are the
same) while the other (NIFTI from MIPAV) has a wrong position and
orientation.
I hope this could help you...
Elena
> From: Luis Ibanez <luis.ibanez at kitware.com>
> Subject: Re: [Insight-users] Nifti vs Dicom orientation
>
> Hi Antoine,
>
> Thanks for looking at the original image orientation.
>
> It seems that the problem lies in the interpretation
> of orientation in the Nii file...
> or... it may be a bug in dcm2nii...
>
>
> I would suggest to post the question about the assumed
> orientation of the Nifti file format to the Nifti forum:
>
> http://nifti.nimh.nih.gov/board/list.php?f=1
>
> Of course, we will be interested in learning about their
> reply.
>
> It may mean that we need to modify the NiftiImageIO
> class in ITK...
>
>
> ---
>
> On the other hand, please note that in practice you don't
> need to use "dcm2nii" since you can achieve exactly the
> same goal by runing the example:
>
>
> Insight/Examples/IO
> DicomSeriesReadImageWrite2.cxx
>
> (reading DICOM and saving it as a nifti file).
>
> Which should give you a consistent set of orientations.
>
>
> Thanks
>
>
> Luis
>
>
> ------------------------
> Antoine DUCHAMPS wrote:
>> Hi Luis,
>>
>> I've read the original DICOM with ITK and I've obtained exactly the same
>> direction cosines:
>>
>> 0.9997 0.0000 0.0252
>> 0.0002 1.0000 -0.0072
>> -0.0252 0.0072 0.9997
>>
>> So, should I assume a LAS orientation in nii image? (even when the
>> standard is RAS)
>>
>> Antoine.
>>
>>
>>
>> Le lundi 06 avril 2009 ? 11:47 -0400, Luis Ibanez a ?crit :
>>
>>>Hi Antoine,
>>>
>>>Could you please read the original DICOM series with ITK and
>>>report the Direction that you get from the ITK image in that case ?
>>>
>>>
>>>
>>>In this way we will be able to figure out if the problem is in
>>>
>>>
>>>A) the conversion from DICOM to Nifti as processed by "dcm2nii"
>>>
>>> or
>>>
>>>B) the process of reading the nifti file with itkNiftiImageIo.
>>>
>>>
>>>Please post to the list the Direction cosines that you obtain
>>>when your read the original DICOM series with ITK.
>>>
>>>
>>> Thanks
>>>
>>>
>>> Luis
>>>
>>>
>>>-----------------
>>>On Mon, Apr 6, 2009 at 10:46 AM, Antoine DUCHAMPS
>>><antoine.duchamps at gmail.com> wrote:
>>>
>>>>Hi all,
>>>>
>>>>I have a DWI sequence (brain) acquired with a Siemens scanner in Dicom
>>>>format. After converting it to NIfTI with dcm2nii
>>>>(http://www.sph.sc.edu/comd/rorden/mricron/dcm2nii.html) I tried to read
>>>>it an recover the orientation by using ITK (I've copied the code below).
>>>>The matrix I obtain is the following:
>>>>
>>>> 0.9997 0.0000 0.0252
>>>> 0.0002 -1.0000 -0.0072
>>>>-0.0252 -0.0072 0.9997
>>>>
>>>>However, the transforation matrix in the Dicom header is
>>>>
>>>> 0.9997 0.0000 0.0252
>>>> 0.0002 1.0000 -0.0072
>>>>-0.0252 0.0072 0.9997
>>>>
>>>>If the Dicom image orientation is LPS, this means that the image
>>>>orientation in NIfTI is LAS (And not RAS as I believed). Could anybody
>>>>clarify this please? Are there several possible orientations in NIfTI?
>>>>If so, how can I know the specific image orientation?
>>>>
>>>>Antoine.
>>>>
>>>>
>>>>#include "itkImageFileReader.h"
>>>>#include "itkOrientedImage.h"
>>>>
>>>>const unsigned int Dimension = 4;
>>>>typedef short PixelType;
>>>>typedef itk::OrientedImage<PixelType, Dimension> ImageType;
>>>>typedef ImageType::Pointer ImagePointerType;
>>>>typedef itk::ImageFileReader< ImageType > ReaderType;
>>>>
>>>>
>>>>int main(int argc, char* argv[])
>>>>{
>>>>
>>>> ImageType::Pointer image = ImageType::New();
>>>>
>>>> ReaderType::Pointer reader = ReaderType::New();
>>>> reader->SetFileName(argv[1]);
>>>> reader->Update();
>>>>
>>>> image = reader -> GetOutput();
>>>> std::cout << image->GetDirection() << std::endl; std::cout.flush();
>>>>
>>>>}
>>>>
>>>>_____________________________________
>>>>Powered by www.kitware.com
>>>>
>>>>Visit other Kitware open-source projects at
>>>>http://www.kitware.com/opensource/opensource.html
>>>>
>>>>Please keep messages on-topic and check the ITK FAQ at:
http://www.itk.org/Wiki/ITK_FAQ
>>>>
>>>>Follow this link to subscribe/unsubscribe:
>>>>http://www.itk.org/mailman/listinfo/insight-users
>>>>
>>
>>
>>
>
>
> ------------------------------
>
> Message: 2
> Date: Wed, 8 Apr 2009 15:04:43 -0400
> From: Bradley Lowekamp <blowekamp at mail.nih.gov>
> Subject: Re: [Insight-users] Visible Human Dataset
> To: Zein Salah <salah at gris.uni-tuebingen.de>
> Cc: ITK Users <insight-users at itk.org>
> Message-ID: <30DAA271-C7D3-4C09-A11C-3D015A1B0CB9 at mail.nih.gov>
> Content-Type: text/plain; charset="us-ascii"; Format="flowed";
> DelSp="yes"
>
> Hello Zein,
>
> You can find all the information for the original data here:
>
> http://www.nlm.nih.gov/research/visible/visible_human.html
> http://www.nlm.nih.gov/research/visible/getting_data.html
>
> The uncompressed Fullcolor slices are 7471104 bytes. The original data
> on the ftp is losslessly "Z" compress, but the sizes of these files
> very. They are originally named a_vm1001.raw.Z to a_vm2878.raw.Z
>
> Then the radiological frozenCT data is name c_vm1006.fro.Z to
> c_vm2882.fro.Z when they are decompressed they are only 527704 bytes.
>
> As your data does not match any of the original data, it has likely
> been processed some how. Hopefully there is information contained in
> the .inf file to help you.
>
> Good luck,
> Brad
>
>
> On Apr 7, 2009, at 4:37 PM, Zein Salah wrote:
>
>> Hello all,
>>
>> I have a copy of the Visible Human data (colored, male) which I
>> downloaded some years ago. I am trying now to read it using itk. I
>> found information how to generate a .mhd file for the raw images
>> that I have. My problem is that I do not any more know the
>> specification of the data, i.e. resolution, pixel type, etc.
>>
>> The data look like this:
>>
>> - There are raw files named as follows: c_vm1006.raw,
>> c_vm1007.raw, ..., c_vm2882.raw.
>> - There is a file named vismale_fro.inf
>> - The size of each raw file is exactly 4,980,736 bytes
>>
>> Does any body have this data? Can somebody help me identifying the
>> specification of the data that I have, probably with a suitable .mhd
>> file?
>>
>> Much thanks,
>>
>> Zein
>> <ATT00001.txt>
>
> ========================================================
> Bradley Lowekamp
> Lockheed Martin Contractor for
> Office of High Performance Computing and Communications
> National Library of Medicine
> blowekamp at mail.nih.gov
>
>
> -------------- next part --------------
> An HTML attachment was scrubbed...
> URL: <
http://www.itk.org/pipermail/insight-users/attachments/20090408/891c8f3c/attachment-0001.htm
>
>
> ------------------------------
>
> Message: 3
> Date: Wed, 8 Apr 2009 23:29:09 -0400
> From: Geoff Topping <g_topping at hotmail.com>
> Subject: [Insight-users] ResampleImageFilter Producing Garbled Output
> When Image Size Changed
> To: <insight-users at itk.org>
> Message-ID: <COL104-W51D457E7BFA5B25CF998B58C830 at phx.gbl>
> Content-Type: text/plain; charset="iso-8859-1"
>
>
> Hi.
>
> I'm trying to use ResampleImageFilter to resize, crop or expand the volume
of an image using ITK. My input image is 128x128x95 voxels with spacings of
0.865759x0.865759x0.796, 16-bit signed integer Analyze75 format.
>
> When I use the following code (see full listing below for context) to set
the output image size and scaling, things work fine, and I get back an image
very similar to my input image (although stored as floats instead of signed
ints, and with the calibration factor ignored by the casting between
formats):
>
> resampleFilter->SetSize(
inputImage->GetLargestPossibleRegion().GetSize());
> resampleFilter->SetOutputOrigin( inputImage->GetOrigin());
> resampleFilter->SetOutputSpacing( inputImage->GetSpacing());
>
> When I switch to using hard coded image size and spacings (128x128x95 and
0.865759x0.865759x0.796), I also get an effectively identical output image:
>
> double spacing[] = {0.865759, 0.865759, 0.796};
> resampleFilter->SetOutputSpacing(spacing);
>
> double origin[] = {0.0, 0.0, 0.0};
> resampleFilter->SetOutputOrigin(origin);
>
> ImageType::SizeType size = {128, 128, 95};
> resampleFilter->SetSize(size);
>
> However, if I change the hard-coded image size, I get garbled output.
Setting hard-coded size to 256x256x190, with or without dividing all the
spacings by 2.0 results in most, but not all, of the slices of the resulting
image being quite garbled, with apparent tilings of a few slices over and
over, occasional mirroring of a series of slices, or what looks like the
early frames of a high-speed camera observing an exploding object, instead
of the original image contents. Examining the resulting images, I see four
copies of the (distorted) image in some of the transverse slices, tiled ul,
ur, ll, lr. In other slice orientations I see two or four tiled copies in a
row.
>
> Any ideas what might be going wrong or how I can fix or debug this?
>
> Thanks,
> Geoff Topping
>
>
> My current code:
>
>
> The program takes two filenames from the command line: input image and
output image file name. It reads the input image, applies an identity
transform while resampling, and outputs the resulting image.
>
> ***********************************************************************
>
> #include "itkVersorRigid3DTransform.h"
> #include "itkIdentityTransform.h"
>
> #include "itkNearestNeighborInterpolateImageFunction.h"
> #include "itkLinearInterpolateImageFunction.h"
>
> #include "itkImage.h"
> #include "itkImageFileReader.h"
> #include "itkImageFileWriter.h"
>
> #include "itkResampleImageFilter.h"
> #include "itkShiftScaleImageFilter.h"
>
>
> #include "vcl_cmath.h"
>
> namespace {
> const unsigned int
Dimension = 3;
> typedef float
PixelType;
> typedef itk::Image<PixelType, Dimension>
ImageType;
> typedef itk::ImageFileReader<ImageType>
ImageReaderType;
> typedef itk::ImageFileWriter<ImageType>
ImageWriterType;
>
> typedef itk::VersorRigid3DTransform<double>
RigidTransformType;
> typedef itk::IdentityTransform<double, Dimension>
IdentityTransformType;
> typedef IdentityTransformType
TransformType;
>
> typedef itk::LinearInterpolateImageFunction<ImageType, double>
LinearInterpolatorType;
> typedef itk::NearestNeighborInterpolateImageFunction<
> ImageType, double>
NearestInterpolatorType;
> typedef NearestInterpolatorType
InterpolatorType;
>
> typedef itk::ResampleImageFilter<ImageType, ImageType>
ResampleFilterType;
> }
>
>
> int main( int argc, char *argv[] ) {
> if( argc < 2 ) {
> std::cerr << "Missing Parameters " << std::endl;
> std::cerr << "Usage: " << argv[0] << " fixedImageFile
movingImageFile outputImagefile" << std::endl;
> return EXIT_FAILURE;
> }
>
>
> ImageReaderType::Pointer imageReader = ImageReaderType::New();
> imageReader->SetFileName(argv[1]);
> imageReader->Update();
>
>
> TransformType::Pointer transform = TransformType::New();
>
> InterpolatorType::Pointer interpolator =
InterpolatorType::New();
>
>
> ImageType::Pointer inputImage = imageReader->GetOutput();
>
>
> ResampleFilterType::Pointer resampleFilter =
ResampleFilterType::New();
> resampleFilter->SetInput( inputImage);
> resampleFilter->SetTransform( transform);
> resampleFilter->SetInterpolator( interpolator);
> resampleFilter->SetDefaultPixelValue( 0);
> resampleFilter->SetOutputDirection( inputImage->GetDirection());
>
>
> #ifdef FROM_INPUT
> resampleFilter->SetSize(
inputImage->GetLargestPossibleRegion().GetSize());
> resampleFilter->SetOutputOrigin( inputImage->GetOrigin());
> resampleFilter->SetOutputSpacing( inputImage->GetSpacing());
> #endif
>
> #ifdef PRINT_INPUT_STUFF
> const ImageType::SpacingType& inputImageSpacing =
inputImage->GetSpacing();
> std::cout << "input image spacings: " << inputImageSpacing[0] << ", "
> << inputImageSpacing[1] << ", "
> << inputImageSpacing[2] <<
std::endl;
>
> const ImageType::PointType& inputImageOrigin = inputImage->GetOrigin();
> std::cout << "input image origin: " << inputImageOrigin[0] << ", "
> << inputImageOrigin[1] << ", "
> << inputImageOrigin[2] <<
std::endl;
>
> const ImageType::SizeType& inputImageSize =
inputImage->GetLargestPossibleRegion().GetSize();
> std::cout << "input image size: " << inputImageSize[0] << ", "
> << inputImageSize[1] << ", "
> << inputImageSize[2] << std::endl;
> #endif
>
> //#ifdef HARD_CODED
> double spacing[] = {0.865759, 0.865759, 0.796};
> resampleFilter->SetOutputSpacing(spacing);
>
> double origin[] = {0.0, 0.0, 0.0};
> resampleFilter->SetOutputOrigin(origin);
>
> ImageType::SizeType size = {128, 128, 95};
> resampleFilter->SetSize(size);
> //#endif
>
>
> ImageWriterType::Pointer writer = ImageWriterType::New();
> writer->SetFileName(argv[2]);
> writer->SetInput(resampleFilter->GetOutput());
>
> try {
> writer->Update();
> } catch (itk::ExceptionObject& err) {
> std::cerr << "ExceptionObject caught !" << std::endl;
> std::cerr << err << std::endl;
> return EXIT_FAILURE;
> }
>
> return EXIT_SUCCESS;
> }
>
>
> _________________________________________________________________
> Reinvent how you stay in touch with the new Windows Live Messenger.
> http://go.microsoft.com/?linkid=9650731
> -------------- next part --------------
> An HTML attachment was scrubbed...
> URL: <
http://www.itk.org/pipermail/insight-users/attachments/20090408/b8f41c60/attachment.htm
>
>
> ------------------------------
>
> _______________________________________________
> Insight-users mailing list
> Insight-users at itk.org
> http://www.itk.org/mailman/listinfo/insight-users
>
>
> End of Insight-users Digest, Vol 60, Issue 44
> *********************************************
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.itk.org/pipermail/insight-users/attachments/20090428/0ac7f4a0/attachment-0001.htm>
More information about the Insight-users
mailing list