[Insight-users] RE: Reading and writing out DICOM images
Radhika Sivaramakrishna
radhika.sivaramakrishna at synarc.com
Tue, 30 Dec 2003 14:14:56 -0800
This message is in MIME format. Since your mail reader does not understand
this format, some or all of this message may not be legible.
------_=_NextPart_001_01C3CF22.5B35F4AA
Content-Type: text/plain
Hi Luis,
Thanks for the detailed explanation and the code. If I want to write out the
image as another DICOM series in a different directory, what is the
procedure?
Radhika
-----Original Message-----
From: Luis Ibanez [mailto:luis . ibanez at kitware . com]
Sent: Tuesday, December 30, 2003 1:17 AM
To: Radhika Sivaramakrishna
Cc: 'insight-users at itk . org'
Subject: Re: Reading and writing out DICOM images
Hi Radhika,
The DICOMImageIO by itself can only read 2D slices.
In order to read volumes from Dicom files you should
use the ImageSeriesReader in combination with the
DICOMSeriesFileNames class.
An example has been added to the repository for
illustrating how to do this. You will find this
example under
Insight/Examples/IO/DicomSeriesReadImageWrite.cxx
Note that this example is using "unsigned short" as
pixel type. If your Dicom files are coming from
CT they are likely of pixel type "signed short".
You may want to modify the code according to the
real encoding of your data.
The code is pasted below:
--------------------------------------------------
#include "itkDICOMImageIO2.h"
#include "itkImageSeriesReader.h"
#include "itkDICOMSeriesFileNames.h"
#include "itkImageFileWriter.h"
int main( int argc, char* argv[] )
{
if( argc < 3 )
{
std::cerr << "Usage: " << argv[0] << " DicomDirectory
outputFileName [seriesName]" << std::endl;
return EXIT_FAILURE;
}
typedef itk::Image<unsigned short,3> ImageType;
typedef itk::ImageSeriesReader< ImageType > ReaderType;
itk::DICOMImageIO2::Pointer dicomIO = itk::DICOMImageIO2::New();
// Get the DICOM filenames from the directory
itk::DICOMSeriesFileNames::Pointer nameGenerator =
itk::DICOMSeriesFileNames::New();
nameGenerator->SetDirectory( argv[1] );
typedef std::vector<std::string> seriesIdContainer;
const seriesIdContainer & seriesUID = nameGenerator->GetSeriesUIDs();
seriesIdContainer::const_iterator seriesItr = seriesUID.begin();
seriesIdContainer::const_iterator seriesEnd = seriesUID.end();
std::cout << std::endl << "The directory: " << std::endl;
std::cout << std::endl << argv[1] << std::endl << std::endl;
std::cout << "Contains the following DICOM Series: ";
std::cout << std::endl << std::endl;
while( seriesItr != seriesEnd )
{
std::cout << seriesItr->c_str() << std::endl;
seriesItr++;
}
std::cout << std::endl << std::endl;
std::cout << "Now reading series: " << std::endl << std::endl;
typedef std::vector<std::string> fileNamesContainer;
fileNamesContainer fileNames;
if( argc < 4 ) // If no optional third argument
{
std::cout << seriesUID.begin()->c_str() << std::endl;
fileNames = nameGenerator->GetFileNames();
}
else
{
std::cout << argv[3] << std::endl;
fileNames = nameGenerator->GetFileNames( argv[3] );
}
std::cout << std::endl << std::endl;
ReaderType::Pointer reader = ReaderType::New();
reader->SetFileNames( fileNames );
reader->SetImageIO( dicomIO );
try
{
reader->Update();
}
catch (itk::ExceptionObject &ex)
{
std::cout << ex << std::endl;
return EXIT_FAILURE;
}
typedef itk::ImageFileWriter< ImageType > WriterType;
WriterType::Pointer writer = WriterType::New();
std::cout << "Writing the image as " << std::endl << std::endl;
std::cout << argv[2] << std::endl << std::endl;
writer->SetFileName( argv[2] );
writer->SetInput( reader->GetOutput() );
try
{
writer->Update();
}
catch (itk::ExceptionObject &ex)
{
std::cout << ex;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
--------------------------------------------------
In order to use this program from the command line
you must provide as first argument the directory
where your DICOM slices are located, and as a second
argument the filename of the output image. In order
to produce Analyze you just need to provide an output
filename with extension ".hdr". You could produce
VTK files by using .vtk, or MetaImages by using .mhd.
Note that you may have multiple DICOM series in the
same directory. The current program will simply take
the first series. If you want to select a particular
series you can provide the optional third parameter
with the string identifying the desired series. If the
optional parameter is missing, this example will print
out all the available series and simply read the first
one.
Please let us know if you have further questions,
Thanks
Luis
---------------------------------
Radhika Sivaramakrishna wrote:
> Hi Luis,
>
> I was trying to modify the example in the Software guide to use an
> ImageIO class explicitly to read a DICOM series and write it out as a 3D
> Analyze format
>
> image. I am not sure how to specify the DICOM series in the input file
> name. I tried giving one of the files in the sequence [this only wrote
> out that particular slice]
>
> as well as tried to use a *.dcm wildcard method which gave an error. I
> have the same doubt for writing out a DICOM series. How do I specify the
> filename?
>
>
>
> Thanks
>
> Radhika
>
>
>
> -----------------------------------------------------
>
> Confidentiality Notice.
>
> This email message is for the sole use of the intended recipient(s) and
> may contain confidential and privileged information. Any unauthorized
> review, use, disclosure or distribution is prohibited. If you are not
> the intended recipient, please contact the sender by reply email and
> destroy all copies of the original message. If you are the intended
> recipient, please be advised that the content of this message is subject
> to access, review and disclosure by the sender's Email System
Administrator.
>
-----------------------------------------------------
Confidentiality Notice.
This email message is for the sole use of the intended recipient(s) and may
contain confidential and privileged information. Any unauthorized review,
use, disclosure or distribution is prohibited. If you are not the intended
recipient, please contact the sender by reply email and destroy all copies
of the original message. If you are the intended recipient, please be
advised that the content of this message is subject to access, review and
disclosure by the sender's Email System Administrator.
------_=_NextPart_001_01C3CF22.5B35F4AA
Content-Type: text/html
Content-Transfer-Encoding: quoted-printable
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV=3D"Content-Type" CONTENT=3D"text/html; =
charset=3Dus-ascii">
<META NAME=3D"Generator" CONTENT=3D"MS Exchange Server version =
5.5.2656.87">
<TITLE>RE: Reading and writing out DICOM images</TITLE>
</HEAD>
<BODY>
<P><FONT SIZE=3D2>Hi Luis,</FONT>
<BR><FONT SIZE=3D2>Thanks for the detailed explanation and the code. If =
I want to write out the image as another DICOM series in a different =
directory, what is the procedure? </FONT></P>
<P><FONT SIZE=3D2>Radhika</FONT>
</P>
<BR>
<P><FONT SIZE=3D2>-----Original Message-----</FONT>
<BR><FONT SIZE=3D2>From: Luis Ibanez [<A =
HREF=3D"mailto:luis . ibanez at kitware . com">mailto:luis . ibanez at kitware . com</=
A>] </FONT>
<BR><FONT SIZE=3D2>Sent: Tuesday, December 30, 2003 1:17 AM</FONT>
<BR><FONT SIZE=3D2>To: Radhika Sivaramakrishna</FONT>
<BR><FONT SIZE=3D2>Cc: 'insight-users at itk . org'</FONT>
<BR><FONT SIZE=3D2>Subject: Re: Reading and writing out DICOM =
images</FONT>
</P>
<BR>
<P><FONT SIZE=3D2>Hi Radhika,</FONT>
</P>
<P><FONT SIZE=3D2>The DICOMImageIO by itself can only read 2D =
slices.</FONT>
</P>
<P><FONT SIZE=3D2>In order to read volumes from Dicom files you =
should</FONT>
<BR><FONT SIZE=3D2>use the ImageSeriesReader in combination with =
the</FONT>
<BR><FONT SIZE=3D2>DICOMSeriesFileNames class.</FONT>
</P>
<P><FONT SIZE=3D2>An example has been added to the repository =
for</FONT>
<BR><FONT SIZE=3D2>illustrating how to do this. You will find =
this</FONT>
<BR><FONT SIZE=3D2>example under</FONT>
</P>
<P><FONT SIZE=3D2> =
Insight/Examples/IO/DicomSeriesReadImageWrite.cxx</FONT>
</P>
<P><FONT SIZE=3D2>Note that this example is using "unsigned =
short" as</FONT>
<BR><FONT SIZE=3D2>pixel type. If your Dicom files are coming =
from</FONT>
<BR><FONT SIZE=3D2>CT they are likely of pixel type "signed =
short".</FONT>
<BR><FONT SIZE=3D2>You may want to modify the code according to =
the</FONT>
<BR><FONT SIZE=3D2>real encoding of your data.</FONT>
</P>
<P><FONT SIZE=3D2>The code is pasted below:</FONT>
</P>
<P><FONT =
SIZE=3D2>--------------------------------------------------</FONT>
</P>
<P><FONT SIZE=3D2>#include "itkDICOMImageIO2.h"</FONT>
<BR><FONT SIZE=3D2>#include "itkImageSeriesReader.h"</FONT>
<BR><FONT SIZE=3D2>#include =
"itkDICOMSeriesFileNames.h"</FONT>
<BR><FONT SIZE=3D2>#include "itkImageFileWriter.h"</FONT>
</P>
<P><FONT SIZE=3D2>int main( int argc, char* argv[] )</FONT>
<BR><FONT SIZE=3D2>{</FONT>
</P>
<P><FONT SIZE=3D2> if( argc < 3 )</FONT>
<BR><FONT SIZE=3D2> {</FONT>
<BR><FONT SIZE=3D2> std::cerr << =
"Usage: " << argv[0] << " DicomDirectory =
</FONT>
<BR><FONT SIZE=3D2>outputFileName [seriesName]" << =
std::endl;</FONT>
<BR><FONT SIZE=3D2> return EXIT_FAILURE;</FONT>
<BR><FONT SIZE=3D2> }</FONT>
</P>
<P><FONT SIZE=3D2> typedef itk::Image<unsigned =
short,3> &=
nbsp; ImageType;</FONT>
<BR><FONT SIZE=3D2> typedef itk::ImageSeriesReader< =
ImageType > ReaderType;</FONT>
</P>
<P><FONT SIZE=3D2> itk::DICOMImageIO2::Pointer dicomIO =3D =
itk::DICOMImageIO2::New();</FONT>
</P>
<P><FONT SIZE=3D2> // Get the DICOM filenames from the =
directory</FONT>
<BR><FONT SIZE=3D2> itk::DICOMSeriesFileNames::Pointer =
nameGenerator =3D </FONT>
<BR><FONT SIZE=3D2>itk::DICOMSeriesFileNames::New();</FONT>
<BR><FONT SIZE=3D2> nameGenerator->SetDirectory( argv[1] =
);</FONT>
</P>
<BR>
<P><FONT SIZE=3D2> typedef std::vector<std::string> =
seriesIdContainer;</FONT>
<BR><FONT SIZE=3D2> const seriesIdContainer & seriesUID =
=3D nameGenerator->GetSeriesUIDs();</FONT>
</P>
<P><FONT SIZE=3D2> seriesIdContainer::const_iterator =
seriesItr =3D seriesUID.begin();</FONT>
<BR><FONT SIZE=3D2> seriesIdContainer::const_iterator =
seriesEnd =3D seriesUID.end();</FONT>
</P>
<P><FONT SIZE=3D2> std::cout << std::endl << =
"The directory: " << std::endl;</FONT>
<BR><FONT SIZE=3D2> std::cout << std::endl << =
argv[1] << std::endl << std::endl;</FONT>
<BR><FONT SIZE=3D2> std::cout << "Contains the =
following DICOM Series: ";</FONT>
<BR><FONT SIZE=3D2> std::cout << std::endl << =
std::endl;</FONT>
</P>
<P><FONT SIZE=3D2> while( seriesItr !=3D seriesEnd )</FONT>
<BR><FONT SIZE=3D2> {</FONT>
<BR><FONT SIZE=3D2> std::cout << =
seriesItr->c_str() << std::endl;</FONT>
<BR><FONT SIZE=3D2> seriesItr++;</FONT>
<BR><FONT SIZE=3D2> }</FONT>
</P>
<P><FONT SIZE=3D2> std::cout << std::endl << =
std::endl;</FONT>
<BR><FONT SIZE=3D2> std::cout << "Now reading =
series: " << std::endl << std::endl;</FONT>
</P>
<P><FONT SIZE=3D2> typedef std::vector<std::string> =
fileNamesContainer;</FONT>
<BR><FONT SIZE=3D2> fileNamesContainer fileNames;</FONT>
</P>
<P><FONT SIZE=3D2> if( argc < 4 ) // If no optional =
third argument</FONT>
<BR><FONT SIZE=3D2> {</FONT>
<BR><FONT SIZE=3D2> std::cout << =
seriesUID.begin()->c_str() << std::endl;</FONT>
<BR><FONT SIZE=3D2> fileNames =3D =
nameGenerator->GetFileNames();</FONT>
<BR><FONT SIZE=3D2> }</FONT>
<BR><FONT SIZE=3D2> else</FONT>
<BR><FONT SIZE=3D2> {</FONT>
<BR><FONT SIZE=3D2> std::cout << argv[3] =
<< std::endl;</FONT>
<BR><FONT SIZE=3D2> fileNames =3D =
nameGenerator->GetFileNames( argv[3] );</FONT>
<BR><FONT SIZE=3D2> }</FONT>
<BR><FONT SIZE=3D2> std::cout << std::endl << =
std::endl;</FONT>
</P>
<P><FONT SIZE=3D2> ReaderType::Pointer reader =3D =
ReaderType::New();</FONT>
<BR><FONT SIZE=3D2> reader->SetFileNames( fileNames =
);</FONT>
<BR><FONT SIZE=3D2> reader->SetImageIO( dicomIO =
);</FONT>
</P>
<P><FONT SIZE=3D2> try</FONT>
<BR><FONT SIZE=3D2> {</FONT>
<BR><FONT SIZE=3D2> reader->Update();</FONT>
<BR><FONT SIZE=3D2> }</FONT>
<BR><FONT SIZE=3D2> catch (itk::ExceptionObject =
&ex)</FONT>
<BR><FONT SIZE=3D2> {</FONT>
<BR><FONT SIZE=3D2> std::cout << ex =
<< std::endl;</FONT>
<BR><FONT SIZE=3D2> return EXIT_FAILURE;</FONT>
<BR><FONT SIZE=3D2> }</FONT>
</P>
<P><FONT SIZE=3D2> typedef itk::ImageFileWriter< =
ImageType > WriterType;</FONT>
<BR><FONT SIZE=3D2> WriterType::Pointer writer =3D =
WriterType::New();</FONT>
</P>
<P><FONT SIZE=3D2> std::cout << "Writing =
the image as " << std::endl << std::endl;</FONT>
<BR><FONT SIZE=3D2> std::cout << argv[2] =
<< std::endl << std::endl;</FONT>
</P>
<P><FONT SIZE=3D2> writer->SetFileName( argv[2] =
);</FONT>
</P>
<P><FONT SIZE=3D2> writer->SetInput( =
reader->GetOutput() );</FONT>
</P>
<P><FONT SIZE=3D2> try</FONT>
<BR><FONT SIZE=3D2> {</FONT>
<BR><FONT SIZE=3D2> writer->Update();</FONT>
<BR><FONT SIZE=3D2> }</FONT>
<BR><FONT SIZE=3D2> catch (itk::ExceptionObject =
&ex)</FONT>
<BR><FONT SIZE=3D2> {</FONT>
<BR><FONT SIZE=3D2> std::cout << =
ex;</FONT>
<BR><FONT SIZE=3D2> return EXIT_FAILURE;</FONT>
<BR><FONT SIZE=3D2> }</FONT>
</P>
<BR>
<P><FONT SIZE=3D2> return EXIT_SUCCESS;</FONT>
</P>
<P><FONT SIZE=3D2>}</FONT>
</P>
<BR>
<BR>
<P><FONT =
SIZE=3D2>--------------------------------------------------</FONT>
</P>
<BR>
<P><FONT SIZE=3D2>In order to use this program from the command =
line</FONT>
<BR><FONT SIZE=3D2>you must provide as first argument the =
directory</FONT>
<BR><FONT SIZE=3D2>where your DICOM slices are located, and as a =
second</FONT>
<BR><FONT SIZE=3D2>argument the filename of the output image. In =
order</FONT>
<BR><FONT SIZE=3D2>to produce Analyze you just need to provide an =
output</FONT>
<BR><FONT SIZE=3D2>filename with extension ".hdr". You could =
produce</FONT>
<BR><FONT SIZE=3D2>VTK files by using .vtk, or MetaImages by using =
.mhd.</FONT>
</P>
<P><FONT SIZE=3D2>Note that you may have multiple DICOM series in =
the</FONT>
<BR><FONT SIZE=3D2>same directory. The current program will simply =
take</FONT>
<BR><FONT SIZE=3D2>the first series. If you want to select a =
particular</FONT>
<BR><FONT SIZE=3D2>series you can provide the optional third =
parameter</FONT>
<BR><FONT SIZE=3D2>with the string identifying the desired =
series. If the</FONT>
<BR><FONT SIZE=3D2>optional parameter is missing, this example will =
print</FONT>
<BR><FONT SIZE=3D2>out all the available series and simply read the =
first</FONT>
<BR><FONT SIZE=3D2>one.</FONT>
</P>
<BR>
<BR>
<P><FONT SIZE=3D2>Please let us know if you have further =
questions,</FONT>
</P>
<BR>
<P><FONT SIZE=3D2> Thanks</FONT>
</P>
<BR>
<P><FONT SIZE=3D2> Luis</FONT>
</P>
<BR>
<P><FONT SIZE=3D2>---------------------------------</FONT>
<BR><FONT SIZE=3D2>Radhika Sivaramakrishna wrote:</FONT>
<BR><FONT SIZE=3D2>> Hi Luis,</FONT>
<BR><FONT SIZE=3D2>> </FONT>
<BR><FONT SIZE=3D2>> I was trying to modify the example in the =
Software guide to use an </FONT>
<BR><FONT SIZE=3D2>> ImageIO class explicitly to read a DICOM series =
and write it out as a 3D </FONT>
<BR><FONT SIZE=3D2>> Analyze format</FONT>
<BR><FONT SIZE=3D2>> </FONT>
<BR><FONT SIZE=3D2>> image. I am not sure how to specify the DICOM =
series in the input file </FONT>
<BR><FONT SIZE=3D2>> name. I tried giving one of the files in the =
sequence [this only wrote </FONT>
<BR><FONT SIZE=3D2>> out that particular slice]</FONT>
<BR><FONT SIZE=3D2>> </FONT>
<BR><FONT SIZE=3D2>> as well as tried to use a *.dcm wildcard =
method which gave an error. I </FONT>
<BR><FONT SIZE=3D2>> have the same doubt for writing out a DICOM =
series. How do I specify the </FONT>
<BR><FONT SIZE=3D2>> filename?</FONT>
<BR><FONT SIZE=3D2>> </FONT>
<BR><FONT SIZE=3D2>> </FONT>
<BR><FONT SIZE=3D2>> </FONT>
<BR><FONT SIZE=3D2>> Thanks</FONT>
<BR><FONT SIZE=3D2>> </FONT>
<BR><FONT SIZE=3D2>> Radhika</FONT>
<BR><FONT SIZE=3D2>> </FONT>
<BR><FONT SIZE=3D2>> </FONT>
<BR><FONT SIZE=3D2>> </FONT>
<BR><FONT SIZE=3D2>> =
-----------------------------------------------------</FONT>
<BR><FONT SIZE=3D2>> </FONT>
<BR><FONT SIZE=3D2>> Confidentiality Notice.</FONT>
<BR><FONT SIZE=3D2>> </FONT>
<BR><FONT SIZE=3D2>> This email message is for the sole use of the =
intended recipient(s) and </FONT>
<BR><FONT SIZE=3D2>> may contain confidential and privileged =
information. Any unauthorized </FONT>
<BR><FONT SIZE=3D2>> review, use, disclosure or distribution is =
prohibited. If you are not </FONT>
<BR><FONT SIZE=3D2>> the intended recipient, please contact the =
sender by reply email and </FONT>
<BR><FONT SIZE=3D2>> destroy all copies of the original message. If =
you are the intended </FONT>
<BR><FONT SIZE=3D2>> recipient, please be advised that the content =
of this message is subject </FONT>
<BR><FONT SIZE=3D2>> to access, review and disclosure by the =
sender's Email System Administrator.</FONT>
<BR><FONT SIZE=3D2>> </FONT>
</P>
<BR>
<P><FONT =
SIZE=3D2> &nb=
sp; &nb=
sp; &nb=
sp; &nb=
sp; </FONT>
<BR><FONT =
SIZE=3D2>----------------------------------------------------- =
</FONT>
<BR><FONT SIZE=3D2>Confidentiality Notice. </FONT>
<BR><FONT SIZE=3D2>This email message is for the sole use of the =
intended recipient(s) and may contain confidential and privileged =
information. Any unauthorized review, use, disclosure or distribution =
is prohibited. If you are not the intended recipient, please contact =
the sender by reply email and destroy all copies of the original =
message. If you are the intended recipient, please be advised that the =
content of this message is subject to access, review and disclosure by =
the sender's Email System Administrator.</FONT></P>
</BODY>
</HTML>
------_=_NextPart_001_01C3CF22.5B35F4AA--