// ------------------------------------------------------------------------ void LoadImage(const std::string &filename, ImageType::Pointer &image) { typedef itk::Image<unsigned short, 4> InImageType; typedef itk::ImageFileReader<InImageType> ReaderType; ReaderType::Pointer reader = ReaderType::New(); reader->SetFileName(filename); reader->SetImageIO(itk::NrrdImageIO::New()); reader->Update(); typedef itk::ExtractImageFilter<InImageType, ImageType> ExtractorType; ExtractorType::Pointer extractor = ExtractorType::New(); extractor->SetInput(reader->GetOutput()); InImageType::RegionType exRegion = reader->GetOutput()->GetLargestPossibleRegion(); InImageType::SizeType exSize = exRegion.GetSize(); InImageType::IndexType exIndex = exRegion.GetIndex(); exSize[3] = 0; exIndex[3] = 0; exRegion.SetSize(exSize); exRegion.SetIndex(exIndex); extractor->SetExtractionRegion(exRegion); extractor->SetDirectionCollapseToSubmatrix(); extractor->Update(); image = extractor->GetOutput(); }
// ------------------------------------------------------------------------ void loadImageSeries(SeriesTransform &series, const unsigned int &instanceNumbers) { // resize the image vector series.images.resize(series.imageFilenames.size()); typedef itk::GDCMImageIO IOType; typedef itk::ImageFileReader<ImageType> ReaderType; for(unsigned int i = 0; i < instanceNumbers; i++) { ReaderType::Pointer reader = ReaderType::New(); reader->SetImageIO(IOType::New()); reader->SetFileName(series.imageFilenames[i]); try { reader->Update(); } catch(itk::ExceptionObject &e) { std::cout << e << std::endl; exit(1); } series.images[i] = reader->GetOutput(); } }
//read CT image void CTImageTreeItem::retrieveITKImage(QProgressDialog *progress, int progressScale, int progressBase) { //define and create file reader typedef ReaderProgress::ReaderType ReaderType; ReaderType::Pointer imageReader = ReaderType::New(); ReaderType::FileNamesContainer fc; //assign filenames fc.assign(m_fnList.begin(), m_fnList.end()); //set ImageIO and filenames itk::GDCMImageIO::Pointer gdcmImageIO = itk::GDCMImageIO::New(); imageReader->SetImageIO( gdcmImageIO ); imageReader->SetFileNames(fc); //create reader progress ReaderProgress::Pointer progressor = ReaderProgress::New(); if (progress) { progressor->setDialog( progress, progressScale, progressBase ); imageReader->AddObserver(itk::AnyEvent(), progressor); } //try to read the images try { imageReader->Update(); }catch( itk::ExceptionObject & excep ) { std::cerr << "Exception caught !" << std::endl; std::cerr << excep << std::endl; } //assign the reader output to an image pointer ImageType::Pointer imagePtr = imageReader->GetOutput(); setITKImage(imagePtr, 1); //emit signal, that data has changed m_model->dataChanged(m_model->createIndex(childNumber(),0,parent()),m_model->createIndex(childNumber(),columnCount()-1,parent())); }
int main(int argc, char** argv) { if(argc != 3){ std::cout << "Usage: Test2DImage inputFilename outputFilename"; return 1; } typedef signed int InputPixelType; const unsigned int Dimension = 2; typedef itk::Image<InputPixelType, Dimension> InputImageType; typedef itk::RGBPixel<unsigned char> RGBPixelType; typedef itk::Image<RGBPixelType, 2> RGBImageType; typedef itk::ImageFileReader<InputImageType> ReaderType; typedef itk::ImageFileWriter<RGBImageType> WriterType; typedef itk::GDCMImageIO ImageIOType; typedef itk::GradientAnisotropicDiffusionImageFilter<InputImageType, InputImageType> DiffusionFilterType; typedef itk::GradientMagnitudeImageFilter<InputImageType, InputImageType> GradientMagnitudeFilterType; typedef itk::Functor::ScalarToRGBPixelFunctor<int> ColorMapFunctorType; typedef itk::UnaryFunctorImageFilter<InputImageType, RGBImageType, ColorMapFunctorType> ColorMapFilterType; typedef itk::JPEGImageIO JImageIOType; ReaderType::Pointer reader = ReaderType::New(); WriterType::Pointer writer = WriterType::New(); ImageIOType::Pointer GDCMImageIO = ImageIOType::New(); JImageIOType::Pointer JPEGImageIO = JImageIOType::New(); ColorMapFilterType::Pointer colormapper = ColorMapFilterType::New(); reader->SetFileName(argv[1]); reader->SetImageIO(GDCMImageIO); try { reader->Update(); } catch (itk::ExceptionObject & e) { std::cerr << "exception in file reader " << std::endl; std::cerr << e << std::endl; return 1; } DiffusionFilterType::Pointer diffusion = DiffusionFilterType::New(); diffusion->SetNumberOfIterations(1); diffusion->SetConductanceParameter(4); diffusion->SetTimeStep(0.125); GradientMagnitudeFilterType::Pointer gradient = GradientMagnitudeFilterType::New(); diffusion->SetInput(reader->GetOutput()); gradient->SetInput(diffusion->GetOutput()); gradient->Update(); MyWatershedSegmenter<InputImageType> watershed(gradient->GetOutput()); watershed.buildLowerCompleteImage(); watershed.buildLabeledImage(); colormapper->SetInput(watershed.returnFinalImage()); writer->SetInput(colormapper->GetOutput()); writer->UseInputMetaDataDictionaryOff(); writer->SetImageIO(JPEGImageIO); writer->SetFileName(argv[2]); writer->Update(); }
bool extractPointAndNormalFromMask(string filename, CVector3 &point, CVector3 &normal1, CVector3 &normal2) { ReaderType::Pointer reader = ReaderType::New(); itk::NiftiImageIO::Pointer io = itk::NiftiImageIO::New(); reader->SetImageIO(io); reader->SetFileName(filename); try { reader->Update(); } catch( itk::ExceptionObject & e ) { cerr << "Exception caught while reading input image " << endl; cerr << e << endl; return false; } ImageType::Pointer image = reader->GetOutput(); vector<CVector3> result; ImageType::IndexType ind; itk::Point<double,3> pnt; ImageIterator it( image, image->GetRequestedRegion() ); it.GoToBegin(); while(!it.IsAtEnd()) { if (it.Get()!=0) { ind = it.GetIndex(); image->TransformIndexToPhysicalPoint(ind, pnt); bool added = false; if (result.size() == 0) { result.push_back(CVector3(pnt[0],pnt[1],pnt[2])); added = true; } else { for (vector<CVector3>::iterator it=result.begin(); it!=result.end(); it++) { if (pnt[2] < (*it)[2]) { result.insert(it, CVector3(pnt[0],pnt[1],pnt[2])); added = true; break; } } } if (!added) result.push_back(CVector3(pnt[0],pnt[1],pnt[2])); } ++it; } if (result.size() != 3) { cerr << "Error: Not enough of too many points in the binary mask. Number of point needed = 3. Detected points = " << result.size() << endl; return false; } point = result[1]; normal1 = (result[0]-result[1]).Normalize(); normal2 = (result[2]-result[1]).Normalize(); return true; }
// ------------------------------------------------------------------------ void DicomParser::writeSeries(const DicomSeries &series, const QString &outputFolder) { // create the series name QString name = QString::fromStdString(series.description); name.replace(" ","_"); name += "_" + QString::number(series.images.front().seriesNumber); name += ".nrrd"; QDir path(outputFolder); QString fullPath = path.absoluteFilePath(name); std::vector<DicomImage> images = series.images; std::sort(images.begin(), images.end()); // write and build the output images typedef itk::Image<unsigned short, 3> ImageType; typedef itk::Image<unsigned short, 4> OutputImageType; typedef itk::ImageFileReader<ImageType> ReaderType; typedef itk::JoinSeriesImageFilter<ImageType, OutputImageType> JoinerType; JoinerType::Pointer joiner = JoinerType::New(); ImageType::Pointer orig; for(unsigned int i = 0; i < images.size(); i++) { ReaderType::Pointer reader = ReaderType::New(); reader->SetFileName(images[i].filename); std::cout << images[i].filename << std::endl; reader->SetImageIO(itk::GDCMImageIO::New()); reader->Update(); ImageType::Pointer im = reader->GetOutput(); if(i == 0) orig = im; im->SetOrigin(orig->GetOrigin()); im->SetDirection(orig->GetDirection()); im->SetSpacing(orig->GetSpacing()); joiner->SetInput(i, reader->GetOutput()); } std::cout << joiner->GetOutput()->GetDirection() << std::endl; typedef itk::ImageFileWriter<OutputImageType> WriterType; WriterType::Pointer writer = WriterType::New(); writer->SetInput(joiner->GetOutput()); writer->SetFileName(fullPath.toStdString()); writer->SetImageIO(itk::NrrdImageIO::New()); writer->Update(); }
FilterImageType::Pointer getImage(const FileNamesContainer &filenames, DictionaryArray &dictArray) { typedef itk::ImageSeriesReader< FilterImageType > ReaderType; ReaderType::Pointer reader = ReaderType::New(); ImageIOType::Pointer gdcmImageIO = ImageIOType::New(); reader->SetImageIO( gdcmImageIO ); reader->SetFileNames(filenames); reader->Update(); ReaderType::DictionaryArrayRawPointer dict; dict = reader->GetMetaDataDictionaryArray(); for( ReaderType::DictionaryArrayType::const_iterator it = dict->begin(); it != dict->end(); ++it) { dictArray.push_back( **it ); } return reader->GetOutput(); }
itk::Image<unsigned char, 3>::Pointer boner::Importer::import(std::string path) { itk::Image<unsigned char, 3>::Pointer image; typedef itk::ImageSeriesReader<itk::Image<unsigned char, 3>> ReaderType; ReaderType::Pointer reader = ReaderType::New(); itk::GDCMSeriesFileNames::Pointer namegenerator = itk::GDCMSeriesFileNames::New(); namegenerator->SetInputDirectory(path); reader->SetImageIO(itk::GDCMImageIO::New()); reader->SetFileNames(namegenerator->GetInputFileNames()); image = reader->GetOutput(); image->Update(); return image; }
// ------------------------------------------------------------------------ void InitialTransformExtractor::Compute() { GetFilenames(m_Filenames); BuildMapping(m_Mapping); std::string referenceFilename = GetReferenceImageFilename(); // load the reference file typedef itk::ImageFileReader<ImageType> ReaderType; ReaderType::Pointer reader = ReaderType::New(); reader->SetFileName(referenceFilename); reader->SetImageIO(itk::GDCMImageIO::New()); reader->Update(); ImageType::Pointer refImage = reader->GetOutput(); // flip the x and y axis typedef itk::PermuteAxesImageFilter<ImageType> FlipperType; FlipperType::Pointer flipper = FlipperType::New(); itk::FixedArray<unsigned int, 3> order; order[0] = 1; order[1] = 0; order[2] = 2; flipper->SetOrder(order); flipper->SetInput(refImage); flipper->Update(); //refImage = flipper->GetOutput(); // transformation is the negative origin of the reference ImageType::PointType origin = refImage->GetOrigin(); m_Translation[0] = -origin[0]; m_Translation[1] = -origin[1]; m_Translation[2] = -origin[2]; m_Rotation = refImage->GetDirection().GetInverse(); m_Reference = refImage; }
void NrrdPlugin::readSlice(int idx[3], int sz[3], int nbytes, uchar *slice) { typedef itk::Image<T, 3> ImageType; typedef itk::ImageFileReader<ImageType> ReaderType; ReaderType::Pointer reader = ReaderType::New(); reader->SetFileName(m_fileName[0].toAscii().data()); typedef itk::NrrdImageIO NrrdIOType; NrrdIOType::Pointer nrrdIO = NrrdIOType::New(); reader->SetImageIO(nrrdIO); typedef itk::RegionOfInterestImageFilter<ImageType,ImageType> RegionExtractor; ImageType::RegionType region; ImageType::SizeType size; ImageType::IndexType index; index[2] = idx[2]; index[1] = idx[1]; index[0] = idx[0]; size[2] = sz[2]; size[1] = sz[1]; size[0] = sz[0]; region.SetIndex(index); region.SetSize(size); // Extract the relevant sub-region. RegionExtractor::Pointer extractor = RegionExtractor::New(); extractor->SetInput(reader->GetOutput()); extractor->SetRegionOfInterest(region); extractor->Update(); ImageType *dimg = extractor->GetOutput(); char *tdata = (char*)(dimg->GetBufferPointer()); memcpy(slice, tdata, nbytes); }
int main(int, char ** argv) { OptionsData options; readXMLValues(argv[2], options); exit(1); // parse the dicom directory gdcm::Directory dir; dir.Load(argv[1], true); gdcm::Directory::FilenamesType filenames = dir.GetFilenames(); gdcm::Tag seriesDescription = gdcm::Tag(0x0008,0x103e); gdcm::Tag seriesNumber = gdcm::Tag(0x0020,0x0011); gdcm::Tag instanceNumber = gdcm::Tag(0x0020,0x0013); gdcm::Tag sliceThickness = gdcm::Tag(0x0018,0x0050); gdcm::Tag triggerTime = gdcm::Tag(0x0018,0x1060); gdcm::Tag numberOfImages = gdcm::Tag(0x0018,0x1090); gdcm::Tag slicePosition = gdcm::Tag(0x0019,0x1015); gdcm::Tag imagePosition = gdcm::Tag(0x0020,0x0032); gdcm::Tag imageOrientation = gdcm::Tag(0x0020,0x0037); gdcm::Tag sliceLocation = gdcm::Tag(0x0020,0x1041); gdcm::Tag rows = gdcm::Tag(0x0028,0x0010); gdcm::Tag cols = gdcm::Tag(0x0028,0x0011); gdcm::Tag pixelSpacing = gdcm::Tag(0x0028,0x0030); gdcm::Scanner scanner; scanner.AddTag(seriesDescription); scanner.AddTag(seriesNumber); scanner.AddTag(instanceNumber); scanner.AddTag(sliceThickness); scanner.AddTag(triggerTime); scanner.AddTag(numberOfImages); scanner.AddTag(slicePosition); scanner.AddTag(imagePosition); scanner.AddTag(imageOrientation); scanner.AddTag(sliceLocation); scanner.AddTag(rows); scanner.AddTag(cols); scanner.AddTag(pixelSpacing); scanner.Scan(filenames); gdcm::Scanner::MappingType mapping = scanner.GetMappings(); // extract all the images that are Short axis and are the first instance gdcm::Directory::FilenamesType targetFilenames; for(unsigned int i = 0; i < filenames.size(); i++) { const char * fname = filenames[i].c_str(); if(mapping.count(fname) == 0) continue; // extract the image information std::string descriptionStr = mapping[fname][seriesDescription]; std::string instanceNumberStr = mapping[fname][instanceNumber]; QString description = QString::fromStdString(descriptionStr); unsigned int instanceNumber = QString::fromStdString(instanceNumberStr).toInt(); // check that the description is a short axis one and is instance 1 if(instanceNumber == 1 && description.contains("sa", Qt::CaseInsensitive)) { targetFilenames.push_back(filenames[i]); } } // sort the images based on their slice position /* gdcm::Sorter sorter; sorter.SetSortFunction(position_sort); sorter.StableSort(targetFilenames); gdcm::Directory::FilenamesType sorted = sorter.GetFilenames(); for(unsigned int i = 0; i < sorted.size(); i++) { const char * fname = sorted[i].c_str(); std::string position = mapping[fname][imagePosition]; std::cout << position << std::endl; std::cout << mapping[fname][sliceLocation] << std::endl; } */ std::cout << targetFilenames.size() << std::endl; // find the slice with the smallest slice position double smallest = 1000000.0; int smallestIndex; for(unsigned int i = 0; i < targetFilenames.size(); i++) { const char * fname = targetFilenames[i].c_str(); std::string slicePosition = mapping[fname][sliceLocation]; double pos = QString::fromStdString(slicePosition).toDouble(); std::cout << pos << std::endl; if(pos < smallest) { smallest = pos; smallestIndex = i; } } // load the image typedef itk::Image<unsigned short, 3> ImageType; typedef itk::ImageFileReader<ImageType> ReaderType; ReaderType::Pointer reader = ReaderType::New(); reader->SetFileName(targetFilenames[smallestIndex]); reader->SetImageIO(itk::GDCMImageIO::New()); reader->Update(); // flip the x and y axis typedef itk::PermuteAxesImageFilter<ImageType> FlipperType; FlipperType::Pointer flipper = FlipperType::New(); itk::FixedArray<unsigned int, 3> order; order[0] = 1; order[1] = 0; order[2] = 2; flipper->SetOrder(order); flipper->SetInput(reader->GetOutput()); flipper->Update(); ImageType::Pointer referenceImage = flipper->GetOutput(); ImageType::DirectionType direction = referenceImage->GetDirection(); direction.SetIdentity(); referenceImage->SetDirection(direction); ImageType::PointType origin = referenceImage->GetOrigin(); origin.Fill(20.0); referenceImage->SetOrigin(origin); ImageType::SpacingType spacing; spacing.Fill(1.0); referenceImage->SetSpacing(spacing); flipper->GetOutput()->Print(std::cout); typedef itk::ImageFileWriter<ImageType> WriterType; WriterType::Pointer writer = WriterType::New(); writer->SetInput(referenceImage); writer->SetImageIO(itk::NrrdImageIO::New()); writer->SetFileName("test.nrrd"); writer->Update(); std::cout << targetFilenames[smallestIndex] << std::endl; return 0; }
int main(int argc, char *argv[]) { //print help if( argc == 1 ) //argv[0] { PrintHelp(argv); return 1; } if( argc == 2 ) //argv[0] -h { if( argv[1] == string("-h") || argv[1] == string("-H") || argv[1] == string("-help") ) { PrintHelp(argv); return 1; } else { cerr<< "For help: "<< argv[0] << " -h" <<endl; return 0; } } //tags used to name the converted 3d filename: PatientID_StudyID_StudyDate_Access#_Series#_SeriesDescription.mha vector<string> tags; tags.push_back("0010|0020");//patientID tags.push_back("0020|0010");//studyID tags.push_back("0008|0020");//studyDate tags.push_back("0008|0050");//access# tags.push_back("0020|0011");//series# tags.push_back("0008|103e");//series description //illegal filename chracters: \ / : * ? " < > | , which will be removed from tag value. string illegalChars = "\\/:?\"<>|"; //accept output format, specified by -f vector<string> acceptFormat; acceptFormat.push_back("mha"); acceptFormat.push_back("nii"); acceptFormat.push_back("mhd"); acceptFormat.push_back("nrrd"); acceptFormat.push_back("hdr"); //timer start const clock_t begin_time = clock(); //parse arguments string dicomDirectory; // -i string outputDirectory;// -o bool write3D = false; //will be set to true, if outputDirectory is good bool writeAllSeries = true; // default, if without -k string outputFormat = "mha"; //default, if without -f vector<string> seriesKeywords; //record series keywords specified by -f string convertedList; //-l bool writeConvertedList = false; for (int ac = 1; ac < argc; ac++) { //-i if( argv[ac] == string("-i") || argv[ac] == string("-I")) { if ( ++ac >= argc ) { cerr<< "missing argument for -i" <<endl; return 1; } dicomDirectory = argv[ac]; } //-o if( argv[ac] == string("-o") || argv[ac] == string("-O") ) { if ( ++ac >= argc ) { cerr<< "missing argument for -o" <<endl; return 1; } outputDirectory = argv[ac]; } //-f if( argv[ac] == string("-f") || argv[ac] == string("-F") ) { if ( ++ac >= argc ) { cerr<< "missing argument for -f" <<endl; return 1; } outputFormat = argv[ac]; transform(outputFormat.begin(), outputFormat.end(),outputFormat.begin(), tolower); //to lower case } //-k if ( argv[ac] == string("-k") || argv[ac] == string("-K") ) { if ( ++ac >= argc ) { cerr<< "missing argument for -k" <<endl; return 1; } //add elements after -f to vector serieskeywords string seriesKeyword; for( int i=ac; i<argc; i++ ) { seriesKeyword=argv[i]; //push_back until next option if( seriesKeyword == string("-l") || seriesKeyword == string("-i") || seriesKeyword == string("-o") || seriesKeyword == string("-f") ) { break; } transform(seriesKeyword.begin(), seriesKeyword.end(), seriesKeyword.begin(), tolower);//to lower case seriesKeyword = std::regex_replace(seriesKeyword, regex("^ +| +$|( ) +"), "$1");//remove leading,trailing and extra white space seriesKeywords.push_back(seriesKeyword); } if( seriesKeywords.size() > 0 ) { writeAllSeries = false; } } //-l if( argv[ac] == string("-l") || argv[ac] == string("-L") ) { if ( ++ac >= argc ) { cerr<< "missing argument for -l" <<endl; return 1; } convertedList = argv[ac]; } } // Check if dicomDirectory is a directory and exist bool exist = itksys::SystemTools::FileExists(dicomDirectory.c_str()); bool isDir = itksys::SystemTools::FileIsDirectory(dicomDirectory.c_str()); if ( !(exist && isDir) ) { cerr << "ERROR: " << dicomDirectory << " does not exist or is no directory." << endl; return 1; } //check if outputDirectory is good if ( !(outputDirectory.empty()) ) { //check if outputDirectory is a file bool isFile = itksys::SystemTools::FileExists(outputDirectory.c_str(),true); if ( isFile ) { cerr << "ERROR: " << outputDirectory << " should be a directory!" << endl; return 1; } // Check if outputDirectory exist exist = itksys::SystemTools::FileExists( outputDirectory.c_str() ); if( !exist ) //create directory is not exist { try { itksys::SystemTools::MakeDirectory( outputDirectory.c_str() ); cout << outputDirectory << " created." << endl; } catch (itk::ExceptionObject &ex) { cout << ex << std::endl; return 1; } } //set write3D to ture when outputDirectory is good. write3D = true; } //check if ouput format is accept if ( !(find(acceptFormat.begin(), acceptFormat.end(), outputFormat) != acceptFormat.end()) ) { cerr<< "accepted output formats:mha, nii, mhd, nrrd, hdr" <<endl; return 1; } //open convertedList file specified by -l ofstream convertedListFile; if ( !convertedList.empty() ) { convertedListFile.exceptions ( ofstream::failbit | ofstream::badbit ); try { convertedListFile.open( outputDirectory + string(PATH_SEP) + convertedList, ios::out | ios::app); writeConvertedList = true; } catch (std::ofstream::failure e) { cerr << "Exception opening file."<<endl; return 1; } } cout<<"Analyzing "<<dicomDirectory<<endl; //image type to read 2d dicom image, used to get the dicom tags of patientID,studyId,etc... typedef itk::Image< signed short, 2 > ImageType2D; typedef itk::ImageFileReader< ImageType2D > ReaderType2D; ReaderType2D::Pointer reader2D = ReaderType2D::New(); //image type to write 3d mha image typedef signed short PixelType; const unsigned int Dimension = 3; typedef itk::Image< PixelType, Dimension > ImageType; typedef itk::ImageSeriesReader< ImageType > ReaderType; typedef itk::GDCMSeriesFileNames NamesGeneratorType; NamesGeneratorType::Pointer nameGenerator = NamesGeneratorType::New(); ReaderType::Pointer reader = ReaderType::New(); typedef itk::GDCMImageIO ImageIOType; ImageIOType::Pointer dicomIO = ImageIOType::New(); nameGenerator->SetRecursive(true); nameGenerator->SetUseSeriesDetails(true); nameGenerator->AddSeriesRestriction("0008|0021"); nameGenerator->SetDirectory(dicomDirectory); //get all the series (by series UID) under the input folder typedef std::vector< std::string > SeriesIdContainer; const SeriesIdContainer & seriesUID = nameGenerator->GetSeriesUIDs(); SeriesIdContainer::const_iterator seriesItr = seriesUID.begin(); SeriesIdContainer::const_iterator seriesEnd = seriesUID.end(); //get the correspondence between series UID and PatientID,studyId,studyDate,accessNumber,seriesNumber,seriesDescription //key is series UID, vector<string> is PatientID,studyID,studyDate,accessNumber,seriesNumber,seriesDescription map< string, vector<string> > seriesUidToOtherStuff; seriesItr = seriesUID.begin(); while (seriesItr != seriesUID.end()) { string seriesIdentifier = seriesItr->c_str(); //get file names belong to specific series vector< string > fileNames = nameGenerator->GetFileNames(seriesIdentifier); vector< string > otherStuff; //read tags(PatientID StudyID StudyDate Access# Series# SeriesDescription) value from the first file of each series if (!fileNames.empty()) { reader2D->SetFileName(fileNames[0]); reader2D->SetImageIO(dicomIO); try { reader2D->UpdateLargestPossibleRegion(); //do not use reader->Update(),since image size is different across series. } catch (itk::ExceptionObject &ex) { cout << ex << endl; return 1; } typedef itk::MetaDataDictionary DictionaryType; const DictionaryType & dictionary = dicomIO->GetMetaDataDictionary(); typedef itk::MetaDataObject< std::string > MetaDataStringType; DictionaryType::ConstIterator itr = dictionary.Begin(); DictionaryType::ConstIterator end = dictionary.End(); for (int i = 0; i < tags.size(); i++) { string entryId = tags[i]; DictionaryType::ConstIterator tagItr = dictionary.Find( entryId ); if( tagItr != end ) { MetaDataStringType::ConstPointer entryvalue =dynamic_cast<const MetaDataStringType *>(tagItr->second.GetPointer() ); if( entryvalue )//entry found { string tagvalue = entryvalue->GetMetaDataObjectValue(); tagvalue = regex_replace(tagvalue, regex("^ +| +$|( ) +"), "$1");//remove leading,trailing and extra white space otherStuff.push_back(tagvalue); } else { otherStuff.push_back("EntryNotFound"); } } }//end for }//end if (!fileNames.empty()) seriesUidToOtherStuff[seriesIdentifier] = otherStuff; seriesItr++; }//end while //list series number and description for each patient and access# /*patientID, access#, series#, series descrition hierarchy: patientid access# series#:series description series#:series description ... access# series#:series description series#:series description ... patientid ... ... */ //create 2d vector for sorting vector<string> vs; vector< vector<string> > vvs; for( map< string,vector<string> >::iterator ii=seriesUidToOtherStuff.begin(); ii!=seriesUidToOtherStuff.end(); ++ii) { vector<string> vsNew; vs = (*ii).second; vsNew.push_back(vs[0]);//patientID vsNew.push_back(vs[3]);//access# vsNew.push_back(vs[4]);//series# vsNew.push_back(vs[5]);//series description vvs.push_back(vsNew); } //sort: patientID and access# by string lexicographical order, series# by integer sort(vvs.begin(),vvs.end(),comparator); //print series number and description for each patient and access# string patientID; string accessNumber; vector<string> patientIDVector; vector<string> accessNumberVector; if ( vvs.size()>0 ) { cout <<dicomDirectory<<" contains the following DICOM Series:"<<endl; for( int i = 0; i < vvs.size(); i++) { patientID = vvs[i][0]; accessNumber = vvs[i][1]; if (find(patientIDVector.begin(), patientIDVector.end(), patientID) == patientIDVector.end() ) // a new patientID { patientIDVector.push_back(patientID); cout<<"patient ID: "<<patientID<<endl; } if (find(accessNumberVector.begin(), accessNumberVector.end(), accessNumber) == accessNumberVector.end() ) // a new accessNumber { accessNumberVector.push_back(accessNumber); cout<<" "<<"access#: "<<accessNumber<<endl; } cout<<" "<<vvs[i][2]<<": "<<vvs[i][3]<<endl; //list series#:series description } } else { cout << "The directory: "<<dicomDirectory<<" contains no DICOM Series! InputDirectory correct?"<<endl; return 0; } //write 3D volume if (write3D) { typedef std::vector< std::string > FileNamesContainer; FileNamesContainer fileNames; typedef itk::ImageFileWriter< ImageType > WriterType; WriterType::Pointer writer = WriterType::New(); string outFileName; seriesItr = seriesUID.begin(); while (seriesItr != seriesUID.end()) { string seriesIdentifier; if (writeAllSeries) //without -k option { seriesIdentifier = seriesItr->c_str(); } else //with -k option { //get sereisDescription according to seriesUID string seriesDescription = seriesUidToOtherStuff[*seriesItr][5]; transform(seriesDescription.begin(), seriesDescription.end(), seriesDescription.begin(), tolower);//to lower case //check if series Description contains the specified keyword (by -k) for( int i = 0; i < seriesKeywords.size(); i++) { if (seriesDescription.find(seriesKeywords[i]) != string::npos) { seriesIdentifier = seriesItr->c_str(); } } }//end if (writeAllSeries) if ( !seriesIdentifier.empty() ) { //get file names belong to specific series fileNames = nameGenerator->GetFileNames(seriesIdentifier); reader->SetImageIO(dicomIO); reader->SetFileNames(fileNames); //get output file name:PatientID_StudyID_StudyDate_Access#_Series#_SeriesDescription vector<string> vs = seriesUidToOtherStuff[seriesIdentifier]; string temp = vs[0]+"_"+vs[1]+"_"+vs[2]+"_"+vs[3]+"_"+vs[4]+"_"+vs[5]; string tempNew; //remove illegal characters for (string::iterator it = temp.begin(); it < temp.end(); ++it) { bool found = illegalChars.find(*it) != string::npos; if(!found){ tempNew=tempNew+(*it); } } //repace space with . . Many series descriptions come with spaces. But, filenames with spaces is not good. replace( tempNew.begin(), tempNew.end(), ' ', '.'); //get full path file name outFileName = outputDirectory + string(PATH_SEP) + tempNew + "."+outputFormat; //write writer->SetFileName(outFileName); writer->UseCompressionOn(); writer->SetInput(reader->GetOutput()); cout << "Writing: " << outFileName << endl; try { writer->Update(); } catch (itk::ExceptionObject &ex) { cout << ex << std::endl; continue; } //writing converted files full path to convertedList if ( writeConvertedList ) { try { convertedListFile << outFileName <<endl; } catch (std::ofstream::failure e) { cerr << "Exception writing file"<<endl; } } } seriesItr++; }//end while }//end if write3D //close convertedList file if (convertedListFile.is_open()) { try { convertedListFile.close(); } catch (std::ofstream::failure e) { cerr << "Exception closing file"<<endl; } } //print elasped time cout << "Elapsed time: "<<float( clock () - begin_time )/CLOCKS_PER_SEC<<" Seconds"; return 0; }
void QtDcmConvert::convert() { if (QtDcmPreferences::instance()->useDcm2nii()) { QString program = QtDcmPreferences::instance()->getDcm2niiPath(); QStringList arguments; arguments << "-x" << "N"; arguments << "-r" << "N"; arguments << "-g" << "N"; arguments << "-o" << d->outputDirectory << d->inputDirectory; QProcess * process = new QProcess(this); process->setStandardOutputFile(d->tempDirectory + QDir::separator() + "logs" + QDir::separator() + d->serieUID + ".txt"); process->start(program, arguments); process->waitForFinished(); delete process; } else { typedef signed short PixelType; const unsigned int Dimension = 3; typedef itk::Image< PixelType, Dimension > ImageType; typedef itk::ImageSeriesReader< ImageType > ReaderType; typedef itk::ImageFileWriter<ImageType> WriterType; typedef itk::GDCMImageIO ImageIOType; typedef itk::GDCMSeriesFileNames NamesGeneratorType; typedef std::vector< std::string > FileNamesContainer; typedef std::vector< std::string > SeriesIdContainer; // ImageType::Pointer image = 0; ReaderType::Pointer reader = ReaderType::New(); ImageIOType::Pointer dicomIO = ImageIOType::New(); NamesGeneratorType::Pointer inputNames = NamesGeneratorType::New(); inputNames->SetUseSeriesDetails ( true ); inputNames->AddSeriesRestriction ( "0008|0021" ); inputNames->AddSeriesRestriction ( "0020,0037" ); inputNames->LoadSequencesOn(); inputNames->LoadPrivateTagsOn(); inputNames->SetInputDirectory ( d->inputDirectory.toStdString() ); try { const SeriesIdContainer & seriesUID = inputNames->GetSeriesUIDs(); std::string seriesIdentifier = seriesUID.begin()->c_str(); FileNamesContainer filenames = inputNames->GetFileNames ( seriesIdentifier ); dicomIO->SetFileName ( filenames.begin()->c_str() ); try { dicomIO->ReadImageInformation(); } catch ( itk::ExceptionObject &e ) { qDebug() << e.GetDescription(); return; } reader->UseStreamingOn(); reader->SetFileNames ( filenames ); reader->SetImageIO ( dicomIO ); try { reader->Update(); } catch ( itk::ExceptionObject &excp ) { std::cerr << excp << std::endl; return; } // IteratorType itOut; // // image = reader->GetOutput(); // // RegionType region; // region.SetSize ( 0, image->GetLargestPossibleRegion().GetSize() [0] ); // region.SetSize ( 1, image->GetLargestPossibleRegion().GetSize() [1] ); // region.SetSize ( 2, image->GetLargestPossibleRegion().GetSize() [2] ); // image->SetRegions ( region ); // image->Allocate(); // SpacingType spacing; // spacing[0] = image->GetSpacing() [0]; // spacing[1] = image->GetSpacing() [1]; // spacing[2] = image->GetSpacing() [2]; // spacing[3] = 1; // image->SetSpacing ( spacing ); // PointType origin; // origin[0] = image->GetOrigin() [0]; // origin[1] = image->GetOrigin() [1]; // origin[2] = image->GetOrigin() [2]; // origin[3] = 0; // image->SetOrigin ( origin ); // DirectionType direction; // for ( unsigned int i=0; i<4; i++ ) // for ( unsigned int j=0; j<4; j++ ) // { // if ( ( i < 3 ) && ( j < 3 ) ) // direction[i][j] = image->GetDirection() [i][j]; // else // direction[i][j] = ( i == j ) ? 1 : 0; // } // image->SetDirection ( direction ); // itOut = IteratorType ( image, region ); // // image->SetMetaDataDictionary ( dicomIO->GetMetaDataDictionary() ); // // // itk::ImageRegionIterator<ImageType> itIn ( image, image->GetLargestPossibleRegion() ); // while ( !itIn.IsAtEnd() ) // { // itOut.Set ( itIn.Get() ); // ++itIn; // ++itOut; // } WriterType::Pointer writer = WriterType::New(); QString completeFilename = d->outputDirectory + QDir::separator() + d->outputFilename; writer->SetFileName ( completeFilename.toStdString() ); writer->SetInput ( reader->GetOutput() ); // writer->SetInput ( image ); try { writer->Update(); } catch ( itk::ExceptionObject &ex ) { std::cout << ex << std::endl; return; } } catch ( itk::ExceptionObject &ex ) { std::cout << ex << std::endl; return; } } }
// ------------------------------------------------------------------------ void DicomParser::loadImages() { // group the series into sa and not sa DicomSeriesList saList; DicomSeriesList otherList; for(unsigned int i = 0; i < series.size(); i++) { std::string description = series[i].description; QString desc = QString::fromStdString(description); if(desc.contains("Cine_SA")) saList.push_back(series[i]); else if(desc.contains("cine_SA")) saList.push_back(series[i]); else if(desc.contains("Cine_sa")) saList.push_back(series[i]); else if(desc.contains("Cine_ipat SA")) saList.push_back(series[i]); //else if(desc.contains("sa")) //saList.push_back(series[i]); else otherList.push_back(series[i]); } // sort the sa list based on position std::sort(saList.begin(), saList.end(), series_sort); std::sort(otherList.begin(), otherList.end(), series_sort); for(unsigned int i = 0; i < saList.size(); i++) { seriesAgain.push_back(saList[i]); } for(unsigned int i = 0; i < otherList.size(); i++) { seriesAgain.push_back(otherList[i]); } for(unsigned int i = 0; i < seriesAgain.size(); i++) { std::string filename = seriesAgain[i].images.front().filename; typedef itk::Image<unsigned short,3> ImageType; typedef itk::ImageFileReader<ImageType> ReaderType; ReaderType::Pointer reader = ReaderType::New(); reader->SetImageIO(itk::GDCMImageIO::New()); reader->SetFileName(filename); typedef itk::ImageToVTKImageFilter<ImageType> VTKFilterType; VTKFilterType::Pointer vtkFilter = VTKFilterType::New(); vtkFilter->SetInput(reader->GetOutput()); vtkFilter->Update(); vtkSmartPointer<vtkImageData> image = vtkSmartPointer<vtkImageData>::New(); image->DeepCopy(vtkFilter->GetOutput()); image->Print(std::cout); vtkSmartPointer<vtkImageSliceMapper> mapper = vtkSmartPointer<vtkImageSliceMapper>::New(); mapper->SetInputData(image); vtkSmartPointer<vtkImageSlice> actor = vtkSmartPointer<vtkImageSlice>::New(); actor->SetMapper(mapper); actor->GetProperty()->SetColorLevel(177.48); actor->GetProperty()->SetColorWindow(512.04); images.push_back(actor); } }
virtual ReadResult readImage(const std::string& file, const osgDB::ReaderWriter::Options* options) const { std::string ext = osgDB::getLowerCaseFileExtension(file); if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED; std::string fileName = osgDB::findDataFile( file, options ); if (fileName.empty()) return ReadResult::FILE_NOT_FOUND; notice()<<"Reading DICOM file "<<fileName<<std::endl; typedef unsigned short PixelType; const unsigned int Dimension = 3; typedef itk::Image< PixelType, Dimension > ImageType; typedef itk::ImageFileReader< ImageType > ReaderType; ReaderType::Pointer reader = ReaderType::New(); reader->SetFileName( fileName.c_str() ); typedef itk::GDCMImageIO ImageIOType; ImageIOType::Pointer gdcmImageIO = ImageIOType::New(); reader->SetImageIO( gdcmImageIO ); try { reader->Update(); } catch (itk::ExceptionObject & e) { std::cerr << "exception in file reader " << std::endl; std::cerr << e.GetDescription() << std::endl; std::cerr << e.GetLocation() << std::endl; return ReadResult::ERROR_IN_READING_FILE; } ImageType::Pointer inputImage = reader->GetOutput(); ImageType::RegionType region = inputImage->GetBufferedRegion(); ImageType::SizeType size = region.GetSize(); ImageType::IndexType start = region.GetIndex(); //inputImage->GetSpacing(); //inputImage->GetOrigin(); unsigned int width = size[0]; unsigned int height = size[1]; unsigned int depth = size[2]; osg::RefMatrix* matrix = new osg::RefMatrix; notice()<<"width = "<<width<<" height = "<<height<<" depth = "<<depth<<std::endl; for(unsigned int i=0; i<Dimension; ++i) { (*matrix)(i,i) = inputImage->GetSpacing()[i]; (*matrix)(3,i) = inputImage->GetOrigin()[i]; } osg::Image* image = new osg::Image; image->allocateImage(width, height, depth, GL_LUMINANCE, GL_UNSIGNED_BYTE, 1); unsigned char* data = image->data(); typedef itk::ImageRegionConstIterator< ImageType > IteratorType; IteratorType it(inputImage, region); it.GoToBegin(); while (!it.IsAtEnd()) { *data = it.Get(); ++data; ++it; } image->setUserData(matrix); matrix->preMult(osg::Matrix::scale(double(image->s()), double(image->t()), double(image->r()))); return image; }
int main(int argc, char ** argv) { std::string folderName = argv[1]; std::string filter = argv[2]; typedef utils::Directory Directory; Directory::FilenamesType filenames = Directory::GetFiles(folderName, ".nrrd"); Directory::FilenamesType goodFilenames; filterFilenames(filenames, filter, goodFilenames); // load the images std::vector<ImageType::Pointer> imageList; for(unsigned int i = 0; i < goodFilenames.size(); i++) { std::cout << goodFilenames[i] << std::endl; typedef itk::ImageFileReader<ImageType> ReaderType; ReaderType::Pointer reader = ReaderType::New(); reader->SetFileName(goodFilenames[i]); reader->SetImageIO(itk::NrrdImageIO::New()); reader->Update(); imageList.push_back(reader->GetOutput()); } std::sort(imageList.begin(), imageList.end(), imageSort); ImageType::Pointer outputImage = ImageType::New(); ImageType::RegionType outputRegion; ImageType::SizeType outputSize = imageList.front()->GetLargestPossibleRegion().GetSize(); outputSize[2] = imageList.size(); ImageType::IndexType outputIndex; outputIndex.Fill(0); outputRegion.SetSize(outputSize); outputRegion.SetIndex(outputIndex); // compute the spacing double meanSpacing = 0.0; for(unsigned int i = 1; i < imageList.size(); i++) { ImageType::Pointer im1 = imageList[i-1]; ImageType::Pointer im2 = imageList[i]; meanSpacing += (im1->GetOrigin()-im2->GetOrigin()).GetNorm(); } meanSpacing /= (double) (imageList.size()-1); ImageType::SpacingType spacing = imageList.front()->GetSpacing(); spacing[2] = meanSpacing; outputImage->SetRegions(outputRegion); outputImage->SetSpacing(spacing); outputImage->SetOrigin(imageList.front()->GetOrigin()); outputImage->SetDirection(imageList.front()->GetDirection()); outputImage->Allocate(); itk::ImageRegionIterator<ImageType> outIt(outputImage, outputImage->GetLargestPossibleRegion()); outIt.GoToBegin(); while(!outIt.IsAtEnd()) { ImageType::IndexType index = outIt.GetIndex(); ImageType::IndexType testIndex = index; testIndex[2] = 0; outIt.Set(imageList[index[2]]->GetPixel(testIndex)); ++outIt; } std::string stackFilename = folderName + "/stack.nrrd"; typedef itk::ImageFileWriter<ImageType> WriterType; WriterType::Pointer writer = WriterType::New(); writer->SetInput(outputImage); writer->SetFileName(stackFilename); writer->SetImageIO(itk::NrrdImageIO::New()); writer->Update(); return 0; }
bool NrrdPlugin::setFile(QStringList files) { m_fileName = files; typedef itk::Image<unsigned char, 3> ImageType; typedef itk::ImageFileReader<ImageType> ReaderType; ReaderType::Pointer reader = ReaderType::New(); reader->SetFileName(m_fileName[0].toAscii().data()); typedef itk::NrrdImageIO NrrdIOType; NrrdIOType::Pointer nrrdIO = NrrdIOType::New(); reader->SetImageIO(nrrdIO); reader->Update(); itk::ImageIOBase::Pointer imageIO = reader->GetImageIO(); m_height = imageIO->GetDimensions(0); m_width = imageIO->GetDimensions(1); m_depth = imageIO->GetDimensions(2); m_voxelSizeX = imageIO->GetSpacing(0); m_voxelSizeY = imageIO->GetSpacing(1); m_voxelSizeZ = imageIO->GetSpacing(2); int et = imageIO->GetComponentType(); if (et == itk::ImageIOBase::UCHAR) m_voxelType = _UChar; if (et == itk::ImageIOBase::CHAR) m_voxelType = _Char; if (et == itk::ImageIOBase::USHORT) m_voxelType = _UShort; if (et == itk::ImageIOBase::SHORT) m_voxelType = _Short; if (et == itk::ImageIOBase::INT) m_voxelType = _Int; if (et == itk::ImageIOBase::FLOAT) m_voxelType = _Float; m_skipBytes = m_headerBytes = 0; m_bytesPerVoxel = 1; if (m_voxelType == _UChar) m_bytesPerVoxel = 1; else if (m_voxelType == _Char) m_bytesPerVoxel = 1; else if (m_voxelType == _UShort) m_bytesPerVoxel = 2; else if (m_voxelType == _Short) m_bytesPerVoxel = 2; else if (m_voxelType == _Int) m_bytesPerVoxel = 4; else if (m_voxelType == _Float) m_bytesPerVoxel = 4; if (m_4dvol) // do not perform further calculations. return true; if (m_voxelType == _UChar || m_voxelType == _Char || m_voxelType == _UShort || m_voxelType == _Short) { findMinMaxandGenerateHistogram(); } else { findMinMax(); generateHistogram(); } return true; }
int main(int, char ** argv) { // load the input nifti image std::string inputFolderName = argv[1]; std::string outputFilename = argv[2]; // get the set of images from the input folder QStringList nameFilters; nameFilters << "phiContour*_t=*_final.nii"; QDir inputFolder(QString::fromStdString(inputFolderName)); QStringList inputFiles = inputFolder.entryList(nameFilters); unsigned int numTimeSteps = inputFiles.size(); qSort(inputFiles.begin(), inputFiles.end(), file_sort); std::cout << "--> Found " << numTimeSteps << " segmentations" << std::endl; std::cout << "--> Loading images and thresholding " << std::endl; utils::LabelVolumeList labels; for(unsigned int i = 0; i < numTimeSteps; i++) { std::cout << "\t" << inputFiles[i].toStdString() << std::endl; typedef itk::Image<float,3> InputImageType; typedef itk::ImageFileReader<InputImageType> ReaderType; std::string filename = inputFolderName + "/" + inputFiles[i].toStdString(); ReaderType::Pointer reader = ReaderType::New(); reader->SetFileName(filename); reader->SetImageIO(itk::NiftiImageIO::New()); reader->Update(); typedef itk::BinaryThresholdImageFilter<InputImageType, utils::LabelVolume> ThresholderType; ThresholderType::Pointer thresholder = ThresholderType::New(); thresholder->SetInput(reader->GetOutput()); thresholder->SetOutsideValue(0); thresholder->SetInsideValue(1); thresholder->SetLowerThreshold(0); thresholder->SetUpperThreshold(255); thresholder->Update(); labels.push_back(thresholder->GetOutput()); } // build the output image typedef itk::Image<unsigned char, 4> OutputType; OutputType::Pointer output = OutputType::New(); typedef itk::JoinSeriesImageFilter<utils::LabelVolume, OutputType> JoinerType; JoinerType::Pointer joiner = JoinerType::New(); joiner->SetSpacing(1.0); joiner->SetOrigin(0); for(unsigned int i = 0; i < labels.size(); i++) { joiner->SetInput(i, labels[i]); } joiner->Update(); output = joiner->GetOutput(); // save the output typedef itk::ImageFileWriter<OutputType> WriterType; WriterType::Pointer writer = WriterType::New(); writer->SetInput(output); writer->SetFileName(outputFilename); writer->Update(); /* utils::LabelVolume::Pointer ref = labels[0]; OutputType::SpacingType outSpacing; OutputType::DirectionType outDirection; outDirection.SetIdentity(); OutputType::PointType outOrigin; for(unsigned int i = 0; i < 3; i++) { outSpacing[i] = ref->GetSpacing()[i]; outOrigin[i] = ref->GetOrigin()[i]; } return 0; utils::LabelVolumeIO::Write(outputFilename, thresholder->GetOutput()); */ return 0; }
int main() { typedef unsigned short PixelType; const unsigned int Dimension = 3; typedef itk::Image< PixelType, Dimension > ImageType; typedef itk::VTKImageExport<ImageType> ImageExportType; typedef itk::ImageSeriesReader< ImageType > ReaderType; ReaderType::Pointer reader = ReaderType::New(); typedef itk::GDCMImageIO ImageIOType; ImageIOType::Pointer dicomIO = ImageIOType::New(); reader->SetImageIO( dicomIO ); typedef itk::GDCMSeriesFileNames NamesGeneratorType; NamesGeneratorType::Pointer nameGenerator = NamesGeneratorType::New(); nameGenerator->SetUseSeriesDetails( true ); nameGenerator->AddSeriesRestriction("0008|0021" ); nameGenerator->SetDirectory( "/Users/mac/BIOMED/Subjects/testSubject"); typedef std::vector< std::string > SeriesIdContainer; const SeriesIdContainer & seriesUID = nameGenerator->GetSeriesUIDs(); std::cout << seriesUID.size() << std::endl; SeriesIdContainer::const_iterator seriesItr = seriesUID.begin(); SeriesIdContainer::const_iterator seriesEnd = seriesUID.end(); while( seriesItr != seriesEnd ) { std::cout << seriesItr->c_str() << std::endl; seriesItr++; } std::string seriesIdentifier; seriesIdentifier = seriesUID.begin()->c_str(); std::cout << seriesIdentifier.c_str() << std::endl; typedef std::vector< std::string > FileNamesContainer; FileNamesContainer fileNames; fileNames = nameGenerator->GetFileNames( seriesIdentifier ); reader->SetFileNames( fileNames ); try { reader->Update(); } catch (itk::ExceptionObject &ex) { std::cout << ex << std::endl; } //------------------------------------------------------------------------ // ITK to VTK pipeline connection. //------------------------------------------------------------------------ // Create the itk::VTKImageExport instance and connect it to the // itk::CurvatureFlowImageFilter. ImageExportType::Pointer exporter = ImageExportType::New(); exporter->SetInput(reader->GetOutput()); exporter->Update(); // Create the vtkImageImport and connect it to the // itk::VTKImageExport instance. vtkImageImport* importer = vtkImageImport::New(); ConnectPipelines(exporter, importer); //------------------------------------------------------------------------ // VTK pipeline. //------------------------------------------------------------------------ //Demo Display DICOM Image /* string folder = "/Users/mac/BIOMED/Subjects/testSubject"; // Read all the DICOM files in the specified directory. vtkSmartPointer<vtkDICOMImageReader> reader2 = vtkSmartPointer<vtkDICOMImageReader>::New(); reader2->SetDirectoryName(folder.c_str()); reader2->Update(); */ vtkSmartPointer<vtkImageSliceMapper> imageSliceMapper = vtkSmartPointer<vtkImageSliceMapper>::New(); imageSliceMapper->SetInputConnection(importer->GetOutputPort()); //imageSliceMapper->SetInputData(importer->GetOutput()); imageSliceMapper->Update(); vtkSmartPointer<vtkImageSlice> imageSlice = vtkSmartPointer<vtkImageSlice>::New(); imageSlice->SetMapper(imageSliceMapper); vtkSmartPointer<vtkSmartVolumeMapper> volumeMapper = vtkSmartPointer<vtkSmartVolumeMapper>::New(); volumeMapper->SetBlendModeToComposite(); volumeMapper->SetInputConnection(importer->GetOutputPort()); vtkSmartPointer<vtkVolumeProperty> volumeProperty = vtkSmartPointer<vtkVolumeProperty>::New(); volumeProperty->ShadeOff(); volumeProperty->SetInterpolationType(VTK_LINEAR_INTERPOLATION); // Setup renderers vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New(); renderer->AddViewProp(imageSlice); renderer->ResetCamera(); renderer->SetBackground(0.1,0.4,0.2); // Setup render window vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New(); renderWindow->SetSize(500, 500); renderWindow->AddRenderer(renderer); vtkSmartPointer<vtkVolume> volume = vtkSmartPointer<vtkVolume>::New(); volume->SetMapper(volumeMapper); volume->SetProperty(volumeProperty); renderer->AddViewProp(volume); renderer->ResetCamera(); volumeMapper->SetRequestedRenderModeToRayCast(); volumeMapper->SetBlendModeToMinimumIntensity(); renderWindow->Render(); vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New(); // Render and start interaction renderWindowInteractor->SetRenderWindow(renderWindow); renderWindowInteractor->Initialize(); renderWindowInteractor->Start(); return 0; }
int main(int argc, char *argv[]) { srand (time(NULL)); if (argc == 1) { help(); return EXIT_FAILURE; } string inputFilename = "", outputPath = "", outputFilenameBinary = "", outputFilenameMesh = "", outputFilenameBinaryCSF = "", outputFilenameMeshCSF = "", outputFilenameAreas = "", outputFilenameAreasCSF = "", outputFilenameCenterline = "", outputFilenameCenterlineBinary = "", inputCenterlineFilename = "", initMaskFilename = ""; double typeImageFactor = 0.0, initialisation = 0.5; int downSlice = -10000, upSlice = 10000; string suffix; bool input_dicom = false, output_detection = false, output_mesh = false, output_centerline_binary = false, output_centerline_coord = false, output_cross = false, init_with_centerline = false, init_with_mask = false, verbose = false, output_init_tube = false, completeCenterline = false, init_validation = false, low_res_mesh = false, CSF_segmentation = false; int gapInterSlices = 4, nbSlicesInitialisation = 5; double radius = 4.0; int numberOfPropagationIteration = 200; double maxDeformation = 0.0, maxArea = 0.0, minContrast = 50.0, tradeoff_d; bool tradeoff_d_bool = false; for (int i = 0; i < argc; ++i) { if (strcmp(argv[i],"-i")==0) { i++; inputFilename = argv[i]; } else if (strcmp(argv[i],"-i-dicom")==0) { i++; //inputFilename = argv[i]; //input_dicom = true; } else if (strcmp(argv[i],"-o")==0) { i++; outputPath = argv[i]; } else if (strcmp(argv[i],"-t")==0) { i++; if (strcmp(argv[i],"t1")==0) { typeImageFactor = -1.0; if (verbose) cout << endl << "WARNING: be sure your image is a T1-weighted image." << endl << endl; } else if (strcmp(argv[i],"t2")==0) { typeImageFactor = 1.0; if (verbose) cout << endl << "WARNING: be sure your image is a T2-weighted image." << endl << endl; } else { cout << "Error: Invalid type or image (need to be \"t1\" or \"t2\")" << endl << endl; help(); return EXIT_FAILURE; } } else if (strcmp(argv[i],"-init")==0) { i++; initialisation = atof(argv[i]); } else if (strcmp(argv[i],"-down")==0) { i++; downSlice = atoi(argv[i]); } else if (strcmp(argv[i],"-up")==0) { i++; upSlice = atoi(argv[i]); } else if (strcmp(argv[i],"-detect-display")==0) { output_detection = true; } else if (strcmp(argv[i],"-mesh")==0) { output_mesh = true; } else if (strcmp(argv[i],"-centerline-binary")==0) { output_centerline_binary = true; } else if (strcmp(argv[i],"-centerline-coord")==0) { output_centerline_coord = true; } else if (strcmp(argv[i],"-cross")==0) { output_cross = true; } else if (strcmp(argv[i],"-detect-n")==0) { i++; nbSlicesInitialisation = atoi(argv[i]); } else if (strcmp(argv[i],"-detect-gap")==0) { i++; gapInterSlices = atoi(argv[i]); } else if (strcmp(argv[i],"-detect-radius")==0) { i++; radius = atof(argv[i]); } else if (strcmp(argv[i],"-init-centerline")==0) { i++; inputCenterlineFilename = argv[i]; init_with_centerline = true; } else if (strcmp(argv[i],"-nbiter")==0) { i++; numberOfPropagationIteration = atoi(argv[i]); } else if (strcmp(argv[i],"-init-mask")==0) { i++; initMaskFilename = argv[i]; init_with_mask = true; } else if (strcmp(argv[i],"-init-tube")==0) { output_init_tube = true; } else if (strcmp(argv[i],"-init-validation")==0) { init_validation = true; } else if (strcmp(argv[i],"-low-resolution-mesh")==0) { low_res_mesh = true; } else if (strcmp(argv[i],"-max-deformation")==0) { i++; maxDeformation = atof(argv[i]); } else if (strcmp(argv[i],"-max-area")==0) { i++; maxArea = atof(argv[i]); } else if (strcmp(argv[i],"-min-contrast")==0) { i++; minContrast = atof(argv[i]); } else if (strcmp(argv[i],"-d")==0) { i++; tradeoff_d = atof(argv[i]); tradeoff_d_bool = true; } else if (strcmp(argv[i],"-CSF")==0) { CSF_segmentation = true; if (maxArea == 0.0) maxArea = 120; if (maxDeformation == 0.0) maxDeformation = 2.5; } else if (strcmp(argv[i],"-verbose")==0) { verbose = true; } else if (strcmp(argv[i],"-help")==0) { help(); return EXIT_FAILURE; } } if (inputFilename == "") { cerr << "Input filename or folder (if DICOM) not provided" << endl; help(); return EXIT_FAILURE; } if (typeImageFactor == 0) { cerr << "Error: The type of contrast not provided (option -t)" << endl; help(); return EXIT_FAILURE; } // output files must have the same extension as input file string nii=".nii", niigz=".nii.gz"; suffix=niigz; size_t pos = inputFilename.find(niigz); if (pos == string::npos) { pos = inputFilename.find(nii); suffix = nii; } if (outputPath!="" && outputPath.compare(outputPath.length()-1,1,"/")) outputPath += "/"; // add "/" if missing outputFilenameBinary = outputPath+"segmentation_binary"+suffix; outputFilenameMesh = outputPath+"segmentation_mesh.vtk"; outputFilenameBinaryCSF = outputPath+"segmentation_CSF_binary"+suffix; outputFilenameMeshCSF = outputPath+"segmentation_CSF_mesh.vtk"; outputFilenameAreas = outputPath+"cross_sectional_areas.txt"; outputFilenameAreasCSF = outputPath+"cross_sectional_areas_CSF.txt"; outputFilenameCenterline = outputPath+"segmentation_centerline.txt"; outputFilenameCenterlineBinary = outputPath+"segmentation_centerline_binary"+suffix; // if output path doesn't exist, we create it if (outputPath!="") itk::FileTools::CreateDirectory(outputPath.c_str()); // Image reading - image can be T1 or T2 (or Tx-like) depending on contrast between spinal cord and CSF // typeImageFactor depend of contrast type and is equal to +1 when CSF is brighter than spinal cord and equal to -1 inversely ImageType::Pointer initialImage, image = ImageType::New(); if (input_dicom) { /*ImageIOType::Pointer gdcmIO = ImageIOType::New(); InputNamesGeneratorType::Pointer inputNames = InputNamesGeneratorType::New(); inputNames->SetInputDirectory( inputFilename ); const DICOMReaderType::FileNamesContainer & filenames = inputNames->GetInputFileNames(); DICOMReaderType::Pointer reader = DICOMReaderType::New(); reader->SetImageIO( gdcmIO ); reader->SetFileNames( filenames ); try { reader->Update(); } catch (itk::ExceptionObject &excp) { std::cerr << "Exception thrown while reading the DICOM series" << std::endl; std::cerr << excp << std::endl; return EXIT_FAILURE; } initialImage = reader->GetOutput();*/ } else { ReaderType::Pointer reader = ReaderType::New(); itk::NiftiImageIO::Pointer io = itk::NiftiImageIO::New(); reader->SetImageIO(io); reader->SetFileName(inputFilename); try { reader->Update(); } catch( itk::ExceptionObject & e ) { cerr << "Exception caught while reading input image" << endl; cerr << e << endl; return EXIT_FAILURE; } initialImage = reader->GetOutput(); } // Change orientation of input image to AIL. Output images will have the same orientation as input image OrientImage<ImageType> orientationFilter; orientationFilter.setInputImage(initialImage); orientationFilter.orientation(itk::SpatialOrientation::ITK_COORDINATE_ORIENTATION_AIL); initialImage = orientationFilter.getOutputImage(); // Crop image if it is too large in left-right direction. No need to compute the initialization on the whole image. We assume the spinal cord is included in a 5cm large region. ImageType::SizeType desiredSize = initialImage->GetLargestPossibleRegion().GetSize(); ImageType::SpacingType spacingI = initialImage->GetSpacing(); if (desiredSize[2]*spacingI[2] > 60 && !init_with_mask && !init_with_centerline) { SymmetricalCropping symCroppingFilter; symCroppingFilter.setInputImage(initialImage); symCroppingFilter.setInitSlice(initialisation); int crop_slice = -1; try { crop_slice = symCroppingFilter.symmetryDetection(); } catch(exception & e) { cerr << "Exception caught while computing symmetry" << endl; cerr << e.what() << endl; return EXIT_FAILURE; } if (crop_slice != -1) { if (verbose) cout << "Cropping input image in left-right direction around slice = " << crop_slice << endl; image = symCroppingFilter.cropping(); } else { if (verbose) cout << "Image non cropped for symmetry" << endl; image = initialImage; } } else image = initialImage; // Intensity normalization RescaleFilterType::Pointer rescaleFilter = RescaleFilterType::New(); rescaleFilter->SetInput(image); rescaleFilter->SetOutputMinimum(0); rescaleFilter->SetOutputMaximum(1000); try { rescaleFilter->Update(); } catch( itk::ExceptionObject & e ) { cerr << "Exception caught while normalizing input image " << endl; cerr << e << endl; return EXIT_FAILURE; } image = rescaleFilter->GetOutput(); // computing magnitude and direction of gradient image GradientMFilterType::Pointer gradientMagnitudeFilter = GradientMFilterType::New(); gradientMagnitudeFilter->SetInput(image); try { gradientMagnitudeFilter->Update(); } catch( itk::ExceptionObject & e ) { cerr << "Exception caught while updating gradientMagnitudeFilter " << endl; cerr << e << endl; return EXIT_FAILURE; } ImageType::Pointer imageGradient = gradientMagnitudeFilter->GetOutput(); VectorGradientFilterType::Pointer gradientMapFilter = VectorGradientFilterType::New(); gradientMapFilter->SetInput( image ); try { gradientMapFilter->Update(); } catch( itk::ExceptionObject & e ) { cerr << "Exception caught while updating gradientMapFilter " << endl; cerr << e << endl; return EXIT_FAILURE; } GradientImageType::Pointer imageVectorGradient = gradientMapFilter->GetOutput(); // Creation of 3D image with origin, orientation and scaling, containing original image, gradient image, vector gradient image ImageType::SizeType regionSize = image->GetLargestPossibleRegion().GetSize(); ImageType::PointType origineI = image->GetOrigin(); CVector3 origine = CVector3(origineI[0],origineI[1],origineI[2]); ImageType::DirectionType directionI = image->GetInverseDirection(); CVector3 directionX = CVector3(directionI[0][0],directionI[0][1],directionI[0][2]), directionY = CVector3(directionI[1][0],directionI[1][1],directionI[1][2]), directionZ = CVector3(directionI[2][0],directionI[2][1],directionI[2][2]); CVector3 spacing = CVector3(spacingI[0],spacingI[1],spacingI[2]); Image3D* image3DGrad = new Image3D(imageVectorGradient,regionSize[0],regionSize[1],regionSize[2],origine,directionX,directionY,directionZ,spacing,typeImageFactor); image3DGrad->setImageOriginale(initialImage); image3DGrad->setCroppedImageOriginale(image); image3DGrad->setImageMagnitudeGradient(imageGradient); /****************************************** // Initialization of Propagated Deformable Model of Spinal Cord ******************************************/ int radialResolution, axialResolution, numberOfDeformIteration = 3; double axialStep, propagationLength = 800.0; // Definition of parameters for T1 and T2 images. T1 need better resolution to provide accurate segmentation. if (typeImageFactor == 1.0) { // T2 radialResolution = 15; axialResolution = 3; axialStep = 6.0; } else { // T1 radialResolution = 20; //30 axialResolution = 3; //5 axialStep = 6.0; //8 } CVector3 point, normal1, normal2; // normal1 and normal2 and normals in both direction from initial point double stretchingFactor = 1.0; vector<CVector3> centerline; if (init_with_centerline) { if (verbose) cout << "Initialization - using given centerline" << endl; centerline = extractCenterline(inputCenterlineFilename); if (centerline.size() == 0) return EXIT_FAILURE; } else if (init_with_mask) { if (verbose) cout << "Initialization - using given mask" << endl; bool result_init = extractPointAndNormalFromMask(initMaskFilename, point, normal1, normal2); if (!result_init) return EXIT_FAILURE; if (verbose) { cout << "Point = " << point << endl; cout << "Normal 1 = " << normal1 << endl; cout << "Normal 2 = " << normal2 << endl; } } else { bool isSpinalCordDetected = false; int countFailure = 0; double step = 0.025; // step of displacement in pourcentage of the image do { if (verbose) cout << "Initialization - spinal cord detection on axial slices" << endl; Initialisation init(image,typeImageFactor); init.setVerbose(verbose); init.setGap(gapInterSlices); // gap between slices is necessary to provide good normals init.setRadius(radius); // approximate radius of spinal cord. This parameter is used to initiate Hough transform init.setNumberOfSlices(nbSlicesInitialisation); // if the initialization fails at the first position in the image, an other spinal cord detection process is launch higher. int d = rand() % 2; if (d==0) d = -1; isSpinalCordDetected = init.computeInitialParameters(initialisation+(double)countFailure*step*(double)d); //if (!isSpinalCordDetected) isSpinalCordDetected = init.computeInitialParameters(0.7); if(isSpinalCordDetected) { if (output_detection) init.savePointAsAxialImage(image,outputPath+"result_detection.png"); init.getPoints(point,normal1,normal2,radius,stretchingFactor); if (normal2 == CVector3::ZERO) normal2 = -normal1; if (verbose) { cout << "Initialization - Spinal Cord Detection:" << endl; cout << "Point = " << point << endl; cout << "Normal 1 = " << normal1 << endl; cout << "Normal 2 = " << normal2 << endl; cout << "Radius = " << radius << endl; } if(init_validation) { // Definition of discrimination surface for the validation of the spinal cord detection module double K_T1 = 15.7528, K_T2 = 3.2854; CVector3 L_T1 = CVector3(-0.0762,-2.5921,0.3472), L_T2 = CVector3(-0.0022,-1.2995,0.4909); CMatrix3x3 Q_T1, Q_T2; Q_T1[0] = 0.0; Q_T1[1] = 0.0; Q_T1[2] = 0.0; Q_T1[3] = 0.0; Q_T1[4] = 0.1476; Q_T1[5] = 0.0; Q_T1[6] = 0.0; Q_T1[7] = 0.0; Q_T1[8] = 0.6082; Q_T2[0] = 0.0; Q_T2[1] = 0.0; Q_T2[2] = 0.0; Q_T2[3] = 0.0; Q_T2[4] = 0.0687; Q_T2[5] = 0.0; Q_T2[6] = 0.0; Q_T2[7] = 0.0; Q_T2[8] = 0.3388; double contrast = 0.0, mean_distance = 0.0, std_distance = 0.0; // validation of the spinal cord detetion int *sizeDesired = new int[3]; double *spacingDesired = new double[3]; sizeDesired[0] = 61; sizeDesired[1] = 61; sizeDesired[2] = 11; spacingDesired[0] = 0.5; spacingDesired[1] = 0.5; spacingDesired[2] = 0.5; SCRegion* spinal_cord_verif = new SCRegion(); spinal_cord_verif->setSize(sizeDesired); spinal_cord_verif->setSpacing(spacingDesired); spinal_cord_verif->setOrigin(point[0],point[1],point[2]); spinal_cord_verif->setNormal(normal1[0],normal1[1],normal1[2]); spinal_cord_verif->setFactor(typeImageFactor); try { spinal_cord_verif->readImage(initialImage); spinal_cord_verif->createImage(); contrast = spinal_cord_verif->computeContrast(mean_distance,std_distance,15); } catch (string const& e) { cerr << e << endl; contrast = -1.0; } CVector3 vec = CVector3(contrast,mean_distance,std_distance); double discrim = 0.0; if (typeImageFactor == -1) // if T1 { CVector3 temp = vec*Q_T1; double quad = 0.0; for(int r=0; r<3; r++) { quad += temp[r]*vec[r]; } discrim = K_T1 + vec*L_T1 + quad; } else{ CVector3 temp = vec*Q_T2; double quad = 0.0; for(int r=0; r<3; r++) { quad += temp[r]*vec[r]; } discrim = K_T2 + vec*L_T2 + quad; } if (discrim > 0.0) { countFailure++; isSpinalCordDetected = false; if (verbose) cout << "WARNING: Bad initialization. Attempt to locate spinal cord at an other level." << endl << endl; } else { isSpinalCordDetected = true; } delete sizeDesired, spacingDesired, spinal_cord_verif; } else { isSpinalCordDetected = true; } } else { countFailure++; } } while (!isSpinalCordDetected && countFailure<10); if (!isSpinalCordDetected) { cerr << "Error: Enable to detect the spinal cord. Please provide the initial position and orientation of the spinal cord (-init, -init-mask)" << endl; return EXIT_FAILURE; } } /****************************************** // Launch of Propagated Deformable Model of Spinal Cord. Propagation have to be done in both direction ******************************************/ PropagatedDeformableModel* prop = new PropagatedDeformableModel(radialResolution,axialResolution,radius,numberOfDeformIteration,numberOfPropagationIteration,axialStep,propagationLength); if (maxDeformation != 0.0) prop->setMaxDeformation(maxDeformation); if (maxArea != 0.0) prop->setMaxArea(maxArea); prop->setMinContrast(minContrast); prop->setInitialPointAndNormals(point,normal1,normal2); prop->setStretchingFactor(stretchingFactor); prop->setUpAndDownLimits(downSlice,upSlice); prop->setImage3D(image3DGrad); if (init_with_centerline) { prop->propagationWithCenterline(); for (unsigned int k=0; k<centerline.size(); k++) prop->addPointToCenterline(centerline[k]); if (initialisation <= 1) prop->setInitPosition(initialisation); } if (tradeoff_d_bool) { prop->setTradeOffDistanceFeature(tradeoff_d); } prop->setVerbose(verbose); prop->computeMeshInitial(); if (output_init_tube) { SpinalCord *tube1 = prop->getInitialMesh(), *tube2 = prop->getInverseInitialMesh(); tube1->save(outputPath+"InitialTube1.vtk"); tube2->save(outputPath+"InitialTube2.vtk"); } prop->adaptationGlobale(); // Propagation // Saving low resolution mesh if (low_res_mesh) { SpinalCord *meshOutputLowResolution = prop->getOutput(); meshOutputLowResolution->save(outputPath+"segmentation_mesh_low_resolution.vtk",initialImage); //meshOutput->computeCenterline(true,path+"LowResolution"); //meshOutput->computeCrossSectionalArea(true,path+"LowResolution"); //image3DGrad->TransformMeshToBinaryImage(meshOutput,path+"LowResolution",orientationFilter.getInitialImageOrientation()); //meshOutput->saveCenterlineAsBinaryImage(initialImage,path+"LowResolution",orientationFilter.getInitialImageOrientation()); } /****************************************** // High Resolution Deformation ******************************************/ prop->rafinementGlobal(); SpinalCord* meshOutputFinal = prop->getOutputFinal(); if (output_mesh) meshOutputFinal->save(outputFilenameMesh,initialImage); if (output_centerline_coord) meshOutputFinal->computeCenterline(true,outputFilenameCenterline,true); if (output_cross) meshOutputFinal->computeCrossSectionalArea(true,outputFilenameAreas,true,image3DGrad); image3DGrad->TransformMeshToBinaryImage(meshOutputFinal,outputFilenameBinary,orientationFilter.getInitialImageOrientation()); if (output_centerline_binary) meshOutputFinal->saveCenterlineAsBinaryImage(initialImage,outputFilenameCenterlineBinary,orientationFilter.getInitialImageOrientation()); if (verbose) { double lengthPropagation = meshOutputFinal->getLength(); cout << "Total propagation length = " << lengthPropagation << " mm" << endl; } if (CSF_segmentation) { /****************************************** // Launch of Propagated Deformable Model on the CSF. Propagation have to be done in both direction ******************************************/ double factor_CSF = 2; PropagatedDeformableModel* prop_CSF = new PropagatedDeformableModel(radialResolution,axialResolution,radius*factor_CSF,numberOfDeformIteration,numberOfPropagationIteration,axialStep,propagationLength); if (maxDeformation != 0.0) prop_CSF->setMaxDeformation(maxDeformation*factor_CSF); if (maxArea != 0.0) prop_CSF->setMaxArea(maxArea*factor_CSF*2); prop->setMinContrast(minContrast); prop_CSF->setInitialPointAndNormals(point,normal1,normal2); prop_CSF->setStretchingFactor(stretchingFactor); prop_CSF->setUpAndDownLimits(downSlice,upSlice); image3DGrad->setTypeImageFactor(-image3DGrad->getTypeImageFactor()); prop_CSF->setImage3D(image3DGrad); if (init_with_centerline) { prop_CSF->propagationWithCenterline(); for (unsigned int k=0; k<centerline.size(); k++) prop->addPointToCenterline(centerline[k]); if (initialisation <= 1) prop->setInitPosition(initialisation); } prop_CSF->setVerbose(verbose); prop_CSF->computeMeshInitial(); if (output_init_tube) { SpinalCord *tube1 = prop_CSF->getInitialMesh(), *tube2 = prop_CSF->getInverseInitialMesh(); tube1->save(outputPath+"InitialTubeCSF1.vtk"); tube2->save(outputPath+"InitialTubeCSF2.vtk"); } prop_CSF->adaptationGlobale(); // Propagation // Saving low resolution mesh if (low_res_mesh) { SpinalCord *meshOutputLowResolution = prop_CSF->getOutput(); meshOutputLowResolution->save(outputPath+"segmentation_CSF_mesh_low_resolution.vtk",initialImage); //meshOutput->computeCenterline(true,path+"LowResolution"); //meshOutput->computeCrossSectionalArea(true,path+"LowResolution"); //image3DGrad->TransformMeshToBinaryImage(meshOutput,path+"LowResolution",orientationFilter.getInitialImageOrientation()); //meshOutput->saveCenterlineAsBinaryImage(initialImage,path+"LowResolution",orientationFilter.getInitialImageOrientation()); } /****************************************** // High Resolution Deformation ******************************************/ prop_CSF->rafinementGlobal(); SpinalCord* meshOutputFinal = prop_CSF->getOutputFinal(); if (output_mesh) meshOutputFinal->save(outputFilenameMeshCSF,initialImage); if (output_cross) meshOutputFinal->computeCrossSectionalArea(true,outputFilenameAreasCSF,true,image3DGrad); image3DGrad->TransformMeshToBinaryImage(meshOutputFinal,outputFilenameBinaryCSF,orientationFilter.getInitialImageOrientation()); if (verbose) { double lengthPropagation = meshOutputFinal->getLength(); cout << "Total propagation length = " << lengthPropagation << " mm" << endl; } delete prop_CSF; } delete image3DGrad, prop; return EXIT_SUCCESS; }
bool itkDataTensorImageReaderBase::read (const QString &path) { if (this->io.IsNull()) return false; this->readInformation ( path ); qDebug() << "Read with: " << this->identifier(); if (medAbstractData *medData = dynamic_cast<medAbstractData*>(this->data()) ) { if (medData->identifier()=="itkDataTensorImageDouble3") { if (this->io->GetNumberOfComponents()==6) { typedef itk::Tensor<double, 3> TensorType; typedef itk::Image<TensorType, 3> TensorImageType; typedef itk::Vector<double, 6> VectorType; typedef itk::Image<VectorType, 3> VectorImageType; typedef itk::ImageFileReader<VectorImageType> ReaderType; VectorImageType::Pointer image = 0; { ReaderType::Pointer reader = ReaderType::New(); reader->SetImageIO (this->io); reader->SetFileName ( path.toAscii().constData() ); try { reader->Update(); } catch (itk::ExceptionObject &e) { qDebug() << e.GetDescription(); return false; } image = reader->GetOutput(); } TensorImageType::Pointer tensors = TensorImageType::New(); TensorImageType::RegionType region = image->GetLargestPossibleRegion(); tensors->SetRegions (region); tensors->SetSpacing (image->GetSpacing()); tensors->SetOrigin (image->GetOrigin()); tensors->SetDirection (image->GetDirection()); try { tensors->Allocate(); } catch (itk::ExceptionObject &e) { qDebug() << e.GetDescription(); return false; } itk::ImageRegionConstIteratorWithIndex<VectorImageType> itIn (image, image->GetLargestPossibleRegion()); itk::ImageRegionIteratorWithIndex<TensorImageType> itOut(tensors, tensors->GetLargestPossibleRegion()); while(!itOut.IsAtEnd()) { VectorType vec = itIn.Get(); TensorType tensor; for( unsigned int j=0; j<6; j++) { tensor[j] = vec[j]; } itOut.Set (tensor); ++itOut; ++itIn; } medData->setData (tensors); } else if (this->io->GetNumberOfComponents()==9) { typedef itk::Tensor<double, 3> TensorType; typedef itk::Image<TensorType, 3> TensorImageType; typedef itk::Vector<double, 9> VectorType; typedef itk::Image<VectorType, 3> VectorImageType; typedef itk::ImageFileReader<VectorImageType> ReaderType; VectorImageType::Pointer image = 0; { ReaderType::Pointer reader = ReaderType::New(); reader->SetImageIO (this->io); reader->SetFileName ( path.toAscii().constData() ); try { reader->Update(); } catch (itk::ExceptionObject &e) { qDebug() << e.GetDescription(); return false; } image = reader->GetOutput(); } TensorImageType::Pointer tensors = TensorImageType::New(); TensorImageType::RegionType region = image->GetLargestPossibleRegion(); tensors->SetRegions (region); tensors->SetSpacing (image->GetSpacing()); tensors->SetOrigin (image->GetOrigin()); tensors->SetDirection (image->GetDirection()); try { tensors->Allocate(); } catch (itk::ExceptionObject &e) { qDebug() << e.GetDescription(); return false; } itk::ImageRegionConstIteratorWithIndex<VectorImageType> itIn (image, image->GetLargestPossibleRegion()); itk::ImageRegionIteratorWithIndex<TensorImageType> itOut(tensors, tensors->GetLargestPossibleRegion()); while(!itOut.IsAtEnd()) { VectorType vec = itIn.Get(); TensorType tensor; for (unsigned int i=0; i<3; i++) for (unsigned int j=0; j<3; j++) tensor.SetComponent (i, j, vec[i*3+j]); itOut.Set (tensor); ++itOut; ++itIn; } medData->setData (tensors); } else { qDebug() << "Unsupported number of components"; return false; } } else if (medData->identifier()=="itkDataTensorImageFloat3") { if (this->io->GetNumberOfComponents()==6) { typedef itk::Tensor<float, 3> TensorType; typedef itk::Image<TensorType, 3> TensorImageType; typedef itk::Vector<float, 6> VectorType; typedef itk::Image<VectorType, 3> VectorImageType; typedef itk::ImageFileReader<VectorImageType> ReaderType; VectorImageType::Pointer image = 0; { ReaderType::Pointer reader = ReaderType::New(); reader->SetImageIO (this->io); reader->SetFileName ( path.toAscii().constData() ); try { reader->Update(); } catch (itk::ExceptionObject &e) { qDebug() << e.GetDescription(); return false; } image = reader->GetOutput(); } TensorImageType::Pointer tensors = TensorImageType::New(); TensorImageType::RegionType region = image->GetLargestPossibleRegion(); tensors->SetRegions (region); tensors->SetSpacing (image->GetSpacing()); tensors->SetOrigin (image->GetOrigin()); tensors->SetDirection (image->GetDirection()); try { tensors->Allocate(); } catch (itk::ExceptionObject &e) { qDebug() << e.GetDescription(); return false; } itk::ImageRegionConstIteratorWithIndex<VectorImageType> itIn (image, image->GetLargestPossibleRegion()); itk::ImageRegionIteratorWithIndex<TensorImageType> itOut(tensors, tensors->GetLargestPossibleRegion()); while(!itOut.IsAtEnd()) { VectorType vec = itIn.Get(); TensorType tensor; for( unsigned int j=0; j<6; j++) { tensor[j] = vec[j]; } itOut.Set (tensor); ++itOut; ++itIn; } medData->setData (tensors); } else if (this->io->GetNumberOfComponents()==9) { typedef itk::Tensor<float, 3> TensorType; typedef itk::Image<TensorType, 3> TensorImageType; typedef itk::Vector<float, 9> VectorType; typedef itk::Image<VectorType, 3> VectorImageType; typedef itk::ImageFileReader<VectorImageType> ReaderType; VectorImageType::Pointer image = 0; { ReaderType::Pointer reader = ReaderType::New(); reader->SetImageIO (this->io); reader->SetFileName ( path.toAscii().constData() ); try { reader->Update(); } catch (itk::ExceptionObject &e) { qDebug() << e.GetDescription(); return false; } image = reader->GetOutput(); } TensorImageType::Pointer tensors = TensorImageType::New(); TensorImageType::RegionType region = image->GetLargestPossibleRegion(); tensors->SetRegions (region); tensors->SetSpacing (image->GetSpacing()); tensors->SetOrigin (image->GetOrigin()); tensors->SetDirection (image->GetDirection()); try { tensors->Allocate(); } catch (itk::ExceptionObject &e) { qDebug() << e.GetDescription(); return false; } itk::ImageRegionConstIteratorWithIndex<VectorImageType> itIn (image, image->GetLargestPossibleRegion()); itk::ImageRegionIteratorWithIndex<TensorImageType> itOut(tensors, tensors->GetLargestPossibleRegion()); while(!itOut.IsAtEnd()) { VectorType vec = itIn.Get(); TensorType tensor; for (unsigned int i=0; i<3; i++) for (unsigned int j=0; j<3; j++) tensor.SetComponent (i, j, vec[i*3+j]); itOut.Set (tensor); ++itOut; ++itIn; } medData->setData (tensors); } else { qDebug() << "Unsupported number of components"; return false; } } else { qDebug() << "Unsupported data type"; return false; } } else { qDebug() << "No data set or could not create one"; return false; } return true; }
vector<CVector3> extractCenterline(string filename) { vector<CVector3> result; string nii=".nii", niigz=".nii.gz", txt=".txt", suffix=""; size_t pos_niigz = filename.find(niigz), pos_nii = filename.find(nii), pos_txt = filename.find(txt); if (pos_niigz != string::npos || pos_nii != string::npos) { ReaderType::Pointer reader = ReaderType::New(); itk::NiftiImageIO::Pointer io = itk::NiftiImageIO::New(); reader->SetImageIO(io); reader->SetFileName(filename); try { reader->Update(); } catch( itk::ExceptionObject & e ) { cerr << "Exception caught while reading centerline input image " << endl; cerr << e << endl; } ImageType::Pointer image_centerline = reader->GetOutput(); OrientImage<ImageType> orientationFilter; orientationFilter.setInputImage(image_centerline); orientationFilter.orientation(itk::SpatialOrientation::ITK_COORDINATE_ORIENTATION_AIL); image_centerline = orientationFilter.getOutputImage(); ImageType::IndexType ind; itk::Point<double,3> point; ImageIterator it( image_centerline, image_centerline->GetRequestedRegion() ); it.GoToBegin(); while(!it.IsAtEnd()) { if (it.Get()!=0) { ind = it.GetIndex(); image_centerline->TransformIndexToPhysicalPoint(ind, point); bool added = false; if (result.size() == 0) { result.push_back(CVector3(point[0],point[1],point[2])); added = true; } else { for (vector<CVector3>::iterator it=result.begin(); it!=result.end(); it++) { if (point[2] < (*it)[2]) { result.insert(it, CVector3(point[0],point[1],point[2])); added = true; break; } } } if (!added) result.push_back(CVector3(point[0],point[1],point[2])); } ++it; } /*// spline approximation to produce correct centerline double range = result.size()/4.0 ; const unsigned int ParametricDimension = 1; const unsigned int DataDimension = 3; typedef double RealType; typedef itk::Vector<RealType, DataDimension> VectorType; typedef itk::Image<VectorType, ParametricDimension> ImageType; typedef itk::PointSet <VectorType , ParametricDimension > PointSetType; PointSetType::Pointer pointSet = PointSetType::New(); // Sample the helix. int nb = result.size(); for (unsigned long i=0; i<nb; i++) { PointSetType::PointType point; point[0] = (double)i/(double)(nb-1); pointSet ->SetPoint( i, point ); VectorType V; V[0] = result[i][0]; V[1] = result[i][1]; V[2] = result[i][2]; pointSet ->SetPointData( i, V ); } typedef itk::BSplineScatteredDataPointSetToImageFilter <PointSetType , ImageType > FilterType; FilterType::Pointer filter = FilterType::New(); ImageType::SpacingType spacing; spacing.Fill( 1.0 ); ImageType::SizeType size; size.Fill( 2.0); ImageType::PointType origin; origin.Fill( 0.0 ); ImageType::RegionType region(size); FilterType::ArrayType closedim; closedim.Fill(0); filter->SetSize( size ); filter->SetOrigin( origin ); filter->SetSpacing( spacing ); filter->SetInput( pointSet ); int splineOrder = 3; filter->SetSplineOrder( splineOrder ); FilterType::ArrayType ncps; ncps.Fill( splineOrder + 1 ); filter->SetNumberOfControlPoints( ncps ); filter->SetNumberOfLevels( 5 ); filter->SetGenerateOutputImage( false ); try { filter->Update(); } catch( itk::ExceptionObject & e ) { std::cerr << "Exception caught while reading input image " << std::endl; std::cerr << e << std::endl; } typedef itk::BSplineControlPointImageFunction < ImageType, double > BSplineType; BSplineType::Pointer bspline = BSplineType::New(); bspline->SetSplineOrder(filter->GetSplineOrder()); bspline->SetOrigin(origin); bspline->SetSpacing(spacing); bspline->SetSize(size); bspline->SetInputImage(filter->GetPhiLattice()); result.clear(); for (double i=0; i<=2.0*range; i++) { PointSetType::PointType point; point[0] = i/(2.0*range); VectorType V = bspline->Evaluate( point ); result.push_back(CVector3(V[0],V[1],V[2])); }*/ } else if (pos_txt != string::npos) { ifstream myfile; string l; double x, y, z; CVector3 point, pointPrecedent; int i = 0; myfile.open(filename.c_str()); if (myfile.is_open()) { while (myfile.good()) { getline(myfile,l); stringstream ss(l); ss >> x >> z >> y; point = CVector3(x,y,z); if ((point-pointPrecedent).Norm() > 0) { pointPrecedent = point; //point[1] = -point[1]; result.push_back(point); } i++; } } myfile.close(); }
int main(int argc, char *argv[]) { printf("STARTING\n"); srand (time(NULL)); if (argc == 1) { help(); return EXIT_FAILURE; } // Initialization of parameters string inputFilename = "", outputPath = "", outputFilenameBinary = "", outputFilenameMesh = "", outputFilenameBinaryCSF = "", outputFilenameMeshCSF = "", outputFilenameAreas = "", outputFilenameAreasCSF = "", outputFilenameCenterline = "", outputFilenameCenterlineBinary = "", inputCenterlineFilename = "", initMaskFilename = ""; double typeImageFactor = 0.0, initialisation = 0.5; int downSlice = -10000, upSlice = 10000; string suffix; bool input_dicom = false, output_detection = false, output_detection_nii = false, output_mesh = false, output_centerline_binary = false, output_centerline_coord = false, output_cross = false, init_with_centerline = false, init_with_mask = false, verbose = false, output_init_tube = false, completeCenterline = false, init_validation = false, low_res_mesh = false, CSF_segmentation = false; int gapInterSlices = 4, nbSlicesInitialisation = 5; double radius = 4.0; int numberOfPropagationIteration = 200; double maxDeformation = 0.0, maxArea = 0.0, minContrast = 50.0, tradeoff_d = 25, tradeoff_K = 200; bool tradeoff_d_bool = false; int nbiter_GGVF = 2; // Initialization with Vesselness Filter and Minimal Path bool init_with_minimalpath = true; double minimalPath_alpha=0.1; double minimalPath_beta=1.0; double minimalPath_gamma=5.0; double minimalPath_sigmaMinimum=1.5; double minimalPath_sigmaMaximum=4.5; unsigned int minimalPath_numberOfSigmaSteps=10; double minimalPath_sigmaDistance=30.0; // Reading option parameters from user input cout << argc; for (int i = 0; i < argc; ++i) { if (strcmp(argv[i],"-i")==0) { i++; inputFilename = argv[i]; } else if (strcmp(argv[i],"-i-dicom")==0) { i++; //inputFilename = argv[i]; //input_dicom = true; } else if (strcmp(argv[i],"-o")==0) { i++; outputPath = argv[i]; } else if (strcmp(argv[i],"-t")==0) { i++; if (strcmp(argv[i],"t1")==0) { typeImageFactor = -1.0; if (verbose) cout << endl << "WARNING: be sure your image is a T1-weighted image." << endl << endl; } else if (strcmp(argv[i],"t2")==0) { typeImageFactor = 1.0; if (verbose) cout << endl << "WARNING: be sure your image is a T2-weighted image." << endl << endl; } else { cout << "Error: Invalid type or image (need to be \"t1\" or \"t2\")" << endl << endl; help(); return EXIT_FAILURE; } } else if (strcmp(argv[i],"-param-init")==0) { printf("\nPARAM INIT\n"); // param structure delimited by commas: // minimalPath_alpha,minimalPath_beta,minimalPath_gamma,minimalPath_sigmaMinimum,minimalPath_sigmaMaximum,minimalPath_numberOfSigmaSteps,minimalPath_sigmaDistance vector<string> param_init = split(argv[i], ','); minimalPath_alpha = atof(param_init[0].c_str()); printf("%f\n", minimalPath_alpha); minimalPath_beta = atof(param_init[1].c_str()); printf("%f\n", minimalPath_beta); minimalPath_gamma = atof(param_init[2].c_str()); printf("%f\n", minimalPath_gamma); minimalPath_sigmaMinimum = atof(param_init[3].c_str()); printf("%f\n", minimalPath_sigmaMinimum); minimalPath_sigmaMaximum = atof(param_init[4].c_str()); printf("%f\n", minimalPath_sigmaMaximum); minimalPath_numberOfSigmaSteps = atoi(param_init[5].c_str()); printf("%i\n", minimalPath_numberOfSigmaSteps); minimalPath_sigmaDistance = atof(param_init[6].c_str()); printf("%f\n", minimalPath_sigmaDistance); } else if (strcmp(argv[i],"-verbose")==0) { verbose = true; } else if (strcmp(argv[i],"-help")==0) { help(); return EXIT_FAILURE; } } // Checking if user added mandatory arguments if (inputFilename == "") { cerr << "Input filename not provided" << endl; help(); return EXIT_FAILURE; } if (typeImageFactor == 0) { cerr << "Error: The type of contrast not provided (option -t)" << endl; help(); return EXIT_FAILURE; } // output files must have the same extension as input file string nii=".nii", niigz=".nii.gz"; suffix=niigz; size_t pos = inputFilename.find(niigz); if (pos == string::npos) { pos = inputFilename.find(nii); suffix = nii; } // Extract the input file name unsigned found_slash = inputFilename.find_last_of("/\\"); string inputFilename_nameonly = inputFilename.substr(found_slash+1); unsigned found_point = inputFilename_nameonly.find_first_of("."); inputFilename_nameonly = inputFilename_nameonly.substr(0,found_point); // Check if output folder ends with / if (outputPath!="" && outputPath.compare(outputPath.length()-1,1,"/")) outputPath += "/"; // add "/" if missing // Set output filenames outputFilenameBinary = outputPath+inputFilename_nameonly+"_seg"+suffix; outputFilenameMesh = outputPath+inputFilename_nameonly+"_mesh.vtk"; outputFilenameBinaryCSF = outputPath+inputFilename_nameonly+"_CSF_seg"+suffix; outputFilenameMeshCSF = outputPath+inputFilename_nameonly+"_CSF_mesh.vtk"; outputFilenameAreas = outputPath+inputFilename_nameonly+"_cross_sectional_areas.txt"; outputFilenameAreasCSF = outputPath+inputFilename_nameonly+"_cross_sectional_areas_CSF.txt"; outputFilenameCenterline = outputPath+inputFilename_nameonly+"_centerline.txt"; outputFilenameCenterlineBinary = outputPath+inputFilename_nameonly+"_centerline"+suffix; // if output path doesn't exist, we create it if (outputPath!="") itk::FileTools::CreateDirectory(outputPath.c_str()); // Image reading - image can be T1 or T2 (or Tx-like) depending on contrast between spinal cord and CSF // typeImageFactor depend of contrast type and is equal to +1 when CSF is brighter than spinal cord and equal to -1 inversely ImageType::Pointer initialImage, image = ImageType::New(); ReaderType::Pointer reader = ReaderType::New(); itk::NiftiImageIO::Pointer io = itk::NiftiImageIO::New(); reader->SetImageIO(io); reader->SetFileName(inputFilename); try { reader->Update(); } catch( itk::ExceptionObject & e ) { cerr << "ERROR: Exception caught while reading input image (-i option). Are you sure the image exist?" << endl; cerr << e << endl; return EXIT_FAILURE; } initialImage = reader->GetOutput(); ImageType::SizeType desiredSize = initialImage->GetLargestPossibleRegion().GetSize(); ImageType::SpacingType spacingI = initialImage->GetSpacing(); // Intensity normalization RescaleFilterType::Pointer rescaleFilter = RescaleFilterType::New(); rescaleFilter->SetInput(initialImage); rescaleFilter->SetOutputMinimum(0); rescaleFilter->SetOutputMaximum(1000); try { rescaleFilter->Update(); } catch( itk::ExceptionObject & e ) { cerr << "Exception caught while normalizing input image " << endl; cerr << e << endl; return EXIT_FAILURE; } image = rescaleFilter->GetOutput(); vesselnessFilter(image, typeImageFactor, minimalPath_alpha, minimalPath_beta, minimalPath_gamma, minimalPath_sigmaMinimum, minimalPath_sigmaMaximum, minimalPath_numberOfSigmaSteps, minimalPath_sigmaDistance); return EXIT_SUCCESS; }