hello every one,
i am a new user with itk, Here is my question :
how to automatic put some dicom tags in dicom when i turn raw volume data into dicom .?
I wrote some codes to make 3D volumen data in 2d slice , it works , but the 2d-dicom slice does not have any Dicom tags , how can i manually create them and write in dicom?
Anyone knows the solutions or give me some Hits?
here is my code,
Blockquote
int main(int argc, char ** argv)
{
// Verify the number of parameters in the command line
if (argc < 3)
{
std::cerr << "Usage: " << std::endl;
std::cerr << argv[0] << " input3DImageFile output2DImageFile " << std::endl;
std::cerr << " sliceNumber " << std::endl;
return EXIT_FAILURE;
}
using InputPixelType = float;
using OutputPixelType = unsigned short;//if change"short"to float the slice will be better but bigger
using InputImageType = itk::Image<InputPixelType, 3>;// 3D Volume
using OutputImageType = itk::Image<OutputPixelType, 2>;//2d slice
using ReaderType = itk::ImageSeriesReader<InputImageType>;//reader
using WriterType = itk::ImageSeriesWriter<InputImageType, OutputImageType>;//serieswriter
using RAWImageIOType = itk::RawImageIO<InputPixelType,3>;//use rawimageIo because input raw volume
using OUTImageIOType = itk::GDCMImageIO; //use GDCMImageIO because save as dicom slice
OUTImageIOType::Pointer gdcmImageIo = OUTImageIOType::New();// just pointer
RAWImageIOType::Pointer rawimageio = RAWImageIOType::New();// pointer+1
using NameGeneratorType = itk::NumericSeriesFileNames; //a NameGenerator magic!
using GDICOMTYPE = itk::GDCMSeriesFileNames; //a SeriesNameGenerator magic!
GDICOMTYPE::Pointer sliceNumberGenerator = GDICOMTYPE::New();//pointer+2
//sliceNumberGenerator->SetUseSeriesDetails(true);
//sliceNumberGenerator->AddSeriesRestriction("0020 | 0013");
////////////////////////////////////////////Set up how to read raw volume///////////////////////////////////
rawimageio->SetDimensions(0, 1289);
rawimageio->SetDimensions(1, 2617);
rawimageio->SetDimensions(2, 49);
rawimageio->SetOrigin(0, 0.0); // 图像原点, volume origin
rawimageio->SetOrigin(1, 0.0);
rawimageio->SetOrigin(2, 0.0);
rawimageio->SetSpacing(0, 0.085); //像素距离,pixel spacing
rawimageio->SetSpacing(1, 0.085);
rawimageio->SetSpacing(2, 1.0);
rawimageio->SetFileTypeToBinary(); // 二进制方式打开, read with Binary method
rawimageio->SetFileDimensionality(2); // 读取二维数据,read 2 Dimension data
rawimageio->SetByteOrderToLittleEndian();//no idea but it must be here
rawimageio->SetNumberOfComponents(1); // 单个像素的位数
rawimageio->SetPixelType(itk::ImageIOBase::SCALAR); // 像素类型
rawimageio->SetComponentType(itk::ImageIOBase::FLOAT); // 像素类型
rawimageio->SetHeaderSize(0);//just data volume no header in raw ,so set 0
////////////////////////////////////////////Set up how to write raw volume///////////////////////////////////
gdcmImageIo->SetSpacing(0, 0.085);
gdcmImageIo->SetSpacing(1, 0.085);
gdcmImageIo->SetNumberOfComponents(1); // 单个像素的位数
gdcmImageIo->SetPixelType(itk::ImageIOBase::SCALAR); // 像素类型
gdcmImageIo->SetLoadPrivateTagsDefault;
////////////////////////////////////////////Set up the Read/write Directory///////////////////////////////////
const char * inputFilename = argv[1];//"F:/ITKTrz/2020401reader/Volume00000_float_1289x2617x49.raw";
const char * outputDirectory = argv[2];//"F:/ITKTrz/2020401reader/";
itksys::SystemTools::MakeDirectory(outputDirectory);//if not exist the outputDirectory then create
//sliceNumberGenerator->SetOutputDirectory(outputDirectory);//outputDirectory
ReaderType::Pointer reader = ReaderType::New();//pointer
WriterType::Pointer writer = WriterType::New();//pointer
NameGeneratorType::Pointer nameGenerator = NameGeneratorType::New();//point
reader->SetFileName(inputFilename);//set up
reader->SetImageIO(rawimageio);//set up
////////////////////////////////////////////NameGenerator magic the name part!///////////////////////////////////
std::string format = "DICOM_";
std::string formatSlice = "%03d.";
std::string formatExtension = ".ima"; // filename extension
format = std::string(outputDirectory) +format+ formatSlice+formatExtension;// user can change the format of the dicom slice
nameGenerator->SetSeriesFormat(format.c_str());
//////////////////////////////////I wanna automatic set dicom header for each dicom slice but not work ,it will be all the same dicom header /////////////////////////////////////////////////////////////////////////////
int AcquisitionNumber = 1;
int InstanceNumber = 0;
int ImagePositionPatient[3] = { 111,111,11 };
int SliceLocation = 0;
itk::MetaDataDictionary & dict = gdcmImageIo->GetMetaDataDictionary();//MetaDataDictionary is about dicom header
//using itr = itk::MetaDataDictionary::Iterator;
std::string tagkey;
std::string value;
//std::string value2 = std::to_string(start[2]);
tagkey = "0020|0012";
value = "value2";//"Acquisition Number ";
itk::EncapsulateMetaData<std::string>(dict, tagkey, value);
tagkey = "0020|0013";
value = InstanceNumber++;//"Instance Number";
itk::EncapsulateMetaData<std::string>(dict, tagkey, value);
tagkey = "0020|0032";
value = "Image Position Patient";
itk::EncapsulateMetaData<std::string>(dict, tagkey, value);
tagkey = "0020|1041";
value = InstanceNumber++;//" Slice Location";
itk::EncapsulateMetaData<std::string>(dict, tagkey, value);
tagkey = "0008|0060";
value = "CT";//" Slice Location";
itk::EncapsulateMetaData<std::string>(dict, tagkey, value);
tagkey = "0020|000D";
value = "1.3.12.2.1107.5.12.7.310.30000020033006414815200000004";//" Slice Location";
itk::EncapsulateMetaData<std::string>(dict, tagkey, value);
tagkey = "0020|000E";
value = "1.3.12.2.1107.5.12.7.310.30000020033006414818900000667";//" Series Instance UID ";
reader->SetMetaDataDictionary(dict);
try
{
reader->Update();
}
catch ( itk::ExceptionObject & excp)
{
std::cerr << "Exception thrown while reading the image" << std::endl;
std::cerr << excp << std::endl;
}
////////////////////////////////////////////NameGenerator magic!how to extract slice from volume///////////////////////////////////
InputImageType::Pointer inputImage = reader->GetOutput();
InputImageType::RegionType region = inputImage->GetLargestPossibleRegion();
InputImageType::IndexType start = region.GetIndex();
InputImageType::SizeType size = region.GetSize();
const unsigned int firstSlice = start[2];
const unsigned int lastSlice = start[2] + size[2] - 1;
nameGenerator->SetStartIndex(firstSlice);
nameGenerator->SetEndIndex(lastSlice);
nameGenerator->SetIncrementIndex(1);
writer->SetFileNames(nameGenerator->GetFileNames());//SetFileNames
writer->SetImageIO(gdcmImageIo);
writer->SetInput(reader->GetOutput());
try
{
writer->Update();
}
catch (itk::ExceptionObject & err)
{
std::cerr << "ExceptionObject caught !" << std::endl;
std::cerr << err << std::endl;
return EXIT_FAILURE;
}
Thanks!!!