void Preprocess::CannyEdgeDetection(float variance, float upperThreshold, float lowerThreshold) { typedef itk::CastImageFilter< ImageType3D, FloatImageType3D > CastFilterType; CastFilterType::Pointer cast = CastFilterType::New(); cast->SetInput( myImg ); typedef itk::CannyEdgeDetectionImageFilter< FloatImageType3D, FloatImageType3D > FilterType; FilterType::Pointer filter = FilterType::New(); filter->SetInput( cast->GetOutput() ); filter->SetUpperThreshold(upperThreshold); //Threshold for detected edges = threshold filter->SetLowerThreshold(lowerThreshold); //Threshold for detected edges = threshold/2 //filter->SetThreshold(threshold); //Lowest allowed value in the output image filter->SetVariance(variance); //For Gaussian smoothing //filter->SetMaximumError(.01f); //For Gaussian smoothing try { filter->Update(); } catch( itk::ExceptionObject & err ) { std::cerr << "Exception caught: " << err << std::endl; } myImg = RescaleFloatToImageType( filter->GetOutput() ); }
//generate binary segment at actual CT image BinaryImageTreeItem *CTImageTreeItem::generateSegment(void) { typedef itk::CastImageFilter< CTImageType, BinaryImageType> CastFilterType; bool ok; //show dialog for segment name QString segName = QInputDialog::getText(NULL, QObject::tr("Segment Name"), QObject::tr("Name:"), QLineEdit::Normal, QObject::tr("Unnamed Segment"), &ok); BinaryImageTreeItem::ImageType::Pointer seg; //if name is valid and dialog was closed with OK if (ok && !segName.isEmpty()) { //create caster, that transforme the CT image to a binary image CastFilterType::Pointer caster = CastFilterType::New(); caster->SetInput( getITKImage() ); caster->Update(); seg = caster->GetOutput(); //fills the segment with zeros seg->FillBuffer(BinaryPixelOff); //create a binary tree item as child of this CT image BinaryImageTreeItem *result = new BinaryImageTreeItem(this, seg, segName); //insert child into the hierarchy insertChild(result); return result; } return NULL; }
int main (int argc, char *argv[]) { // Verify arguments if(argc != 3) { std::cerr << "Required arguments: InputFileName OutputFileName" << std::endl; return EXIT_FAILURE; } // Parse arguments std::string inputFileName = argv[1]; std::string outputFileName = argv[2]; // Output arguments std::cout << "Input image: " << inputFileName << std::endl; std::cout << "Output image: " << outputFileName << std::endl; //typedef itk::Image<unsigned char, 2> ImageType; typedef itk::RGBPixel<float> RGBFloatPixelType; // We must use float pixels so that the averaging operation does not overflow typedef itk::Image<RGBFloatPixelType> RGBFloatImageType; typedef itk::ImageFileReader<RGBFloatImageType> ReaderType; ReaderType::Pointer reader = ReaderType::New(); reader->SetFileName(inputFileName); reader->Update(); SmallHoleFiller<RGBFloatImageType> smallHoleFiller; smallHoleFiller.SetImage(reader->GetOutput()); RGBFloatImageType::PixelType green; green.SetRed(0); green.SetGreen(255); green.SetBlue(0); smallHoleFiller.SetHolePixel(green); smallHoleFiller.GenerateMaskFromImage(); smallHoleFiller.Fill(); typedef itk::RGBPixel<unsigned char> RGBUCharPixelType; typedef itk::Image<RGBUCharPixelType> RGBUCharImageType; typedef itk::CastImageFilter<RGBFloatImageType, RGBUCharImageType> CastFilterType; CastFilterType::Pointer castFilter = CastFilterType::New(); castFilter->SetInput(smallHoleFiller.GetOutput()); castFilter->Update(); typedef itk::ImageFileWriter< RGBUCharImageType > WriterType; WriterType::Pointer writer = WriterType::New(); writer->SetFileName(outputFileName); writer->SetInput(castFilter->GetOutput()); writer->Update(); return EXIT_SUCCESS; }
ImageType::Pointer SBFilterUtils::GaussianSmoothImage(ImageType::Pointer image, float variance) { GaussianFilterType::Pointer gaussianFilter = GaussianFilterType::New(); gaussianFilter->SetInput(image); gaussianFilter->SetVariance(variance); gaussianFilter->Update(); CastFilterType::Pointer castFilter = CastFilterType::New(); castFilter->SetInput(gaussianFilter->GetOutput()); castFilter->Update(); return castFilter->GetOutput(); }
//generate binary segment at actual CT image BinaryImageTreeItem *CTImageTreeItem::generateSegment(QString name) { typedef itk::CastImageFilter< CTImageType, BinaryImageType> CastFilterType; BinaryImageTreeItem::ImageType::Pointer seg; //if name is valid and dialog was closed with OK if (!name.isEmpty()) { //create caster, that transforme the CT image to a binary image CastFilterType::Pointer caster = CastFilterType::New(); caster->SetInput( getITKImage() ); caster->Update(); seg = caster->GetOutput(); //fills the segment with zeros seg->FillBuffer(BinaryPixelOff); //create a binary tree item as child of this CT image BinaryImageTreeItem *result = new BinaryImageTreeItem(this, seg, name); //insert child into the hierarchy insertChild(result); return result; } return NULL; }
int main( int argc, char *argv[] ) { if( argc < 4 ) { std::cerr << "Missing Parameters " << std::endl; std::cerr << "Usage: " << argv[0]; std::cerr << " fixedImageFile movingImageFile "; std::cerr << " outputImagefile [differenceBeforeRegistration] "; std::cerr << " [differenceAfterRegistration] "; std::cerr << " [sliceBeforeRegistration] "; std::cerr << " [sliceDifferenceBeforeRegistration] "; std::cerr << " [sliceDifferenceAfterRegistration] "; std::cerr << " [sliceAfterRegistration] " << std::endl; return EXIT_FAILURE; } const unsigned int Dimension = 3; typedef float PixelType; typedef itk::Image< PixelType, Dimension > FixedImageType; typedef itk::Image< PixelType, Dimension > MovingImageType; // Software Guide : BeginLatex // // The Transform class is instantiated using the code below. The only // template parameter to this class is the representation type of the // space coordinates. // // \index{itk::Versor\-Rigid3D\-Transform!Instantiation} // // Software Guide : EndLatex // Software Guide : BeginCodeSnippet // Software Guide : EndCodeSnippet typedef itk:: LinearInterpolateImageFunction< MovingImageType, double > InterpolatorType; typedef itk::ImageRegistrationMethod< FixedImageType, MovingImageType > RegistrationType; MetricType::Pointer metric = MetricType::New(); OptimizerType::Pointer optimizer = OptimizerType::New(); InterpolatorType::Pointer interpolator = InterpolatorType::New(); RegistrationType::Pointer registration = RegistrationType::New(); registration->SetMetric( metric ); registration->SetOptimizer( optimizer ); registration->SetInterpolator( interpolator ); // Software Guide : BeginLatex // // The transform object is constructed below and passed to the registration // method. // // \index{itk::Versor\-Rigid3D\-Transform!New()} // \index{itk::Versor\-Rigid3D\-Transform!Pointer} // \index{itk::Registration\-Method!SetTransform()} // // Software Guide : EndLatex // Software Guide : BeginCodeSnippet TransformType::Pointer transform = TransformType::New(); registration->SetTransform( transform ); // Software Guide : EndCodeSnippet typedef itk::ImageFileReader< FixedImageType > FixedImageReaderType; typedef itk::ImageFileReader< MovingImageType > MovingImageReaderType; FixedImageReaderType::Pointer fixedImageReader = FixedImageReaderType::New(); MovingImageReaderType::Pointer movingImageReader = MovingImageReaderType::New(); fixedImageReader->SetFileName( argv[1] ); movingImageReader->SetFileName( argv[2] ); registration->SetFixedImage( fixedImageReader->GetOutput() ); registration->SetMovingImage( movingImageReader->GetOutput() ); fixedImageReader->Update(); registration->SetFixedImageRegion( fixedImageReader->GetOutput()->GetBufferedRegion() ); // Software Guide : BeginLatex // // The input images are taken from readers. It is not necessary here to // explicitly call \code{Update()} on the readers since the // \doxygen{CenteredTransformInitializer} will do it as part of its // computations. The following code instantiates the type of the // initializer. This class is templated over the fixed and moving image type // as well as the transform type. An initializer is then constructed by // calling the \code{New()} method and assigning the result to a smart // pointer. // // \index{itk::Centered\-Transform\-Initializer!Instantiation} // \index{itk::Centered\-Transform\-Initializer!New()} // \index{itk::Centered\-Transform\-Initializer!SmartPointer} // // Software Guide : EndLatex // Software Guide : BeginCodeSnippet // Software Guide : BeginLatex // // Let's execute this example over some of the images available in the ftp // site // // \url{ftp://public.kitware.com/pub/itk/Data/BrainWeb} // // Note that the images in the ftp site are compressed in \code{.tgz} files. // You should download these files an uncompress them in your local system. // After decompressing and extracting the files you could take a pair of // volumes, for example the pair: // // \begin{itemize} // \item \code{brainweb1e1a10f20.mha} // \item \code{brainweb1e1a10f20Rot10Tx15.mha} // \end{itemize} // // The second image is the result of intentionally rotating the first image // by $10$ degrees around the origin and shifting it $15mm$ in $X$. The // registration takes $24$ iterations and produces: // // \begin{center} // \begin{verbatim} // [-6.03744e-05, 5.91487e-06, -0.0871932, 2.64659, -17.4637, -0.00232496] // \end{verbatim} // \end{center} // // That are interpreted as // // \begin{itemize} // \item Versor = $(-6.03744e-05, 5.91487e-06, -0.0871932)$ // \item Translation = $(2.64659, -17.4637, -0.00232496)$ millimeters // \end{itemize} // // This Versor is equivalent to a rotation of $9.98$ degrees around the $Z$ // axis. // // Note that the reported translation is not the translation of $(15.0,0.0,0.0)$ // that we may be naively expecting. The reason is that the // \code{VersorRigid3DTransform} is applying the rotation around the center // found by the \code{CenteredTransformInitializer} and then adding the // translation vector shown above. // // It is more illustrative in this case to take a look at the actual // rotation matrix and offset resulting form the $6$ parameters. // // Software Guide : EndLatex // Software Guide : BeginCodeSnippet transform->SetParameters( finalParameters ); TransformType::MatrixType matrix = transform->GetMatrix(); TransformType::OffsetType offset = transform->GetOffset(); std::cout << "Matrix = " << std::endl << matrix << std::endl; std::cout << "Offset = " << std::endl << offset << std::endl; // Software Guide : EndCodeSnippet // Software Guide : BeginLatex // // The output of this print statements is // // \begin{center} // \begin{verbatim} // Matrix = // 0.984795 0.173722 2.23132e-05 // -0.173722 0.984795 0.000119257 // -1.25621e-06 -0.00012132 1 // // Offset = // [-15.0105, -0.00672343, 0.0110854] // \end{verbatim} // \end{center} // // From the rotation matrix it is possible to deduce that the rotation is // happening in the X,Y plane and that the angle is on the order of // $\arcsin{(0.173722)}$ which is very close to 10 degrees, as we expected. // // Software Guide : EndLatex // Software Guide : BeginLatex // // \begin{figure} // \center // \includegraphics[width=0.44\textwidth]{BrainProtonDensitySliceBorder20} // \includegraphics[width=0.44\textwidth]{BrainProtonDensitySliceR10X13Y17} // \itkcaption[CenteredTransformInitializer input images]{Fixed and moving image // provided as input to the registration method using // CenteredTransformInitializer.} // \label{fig:FixedMovingImageRegistration8} // \end{figure} // // // \begin{figure} // \center // \includegraphics[width=0.32\textwidth]{ImageRegistration8Output} // \includegraphics[width=0.32\textwidth]{ImageRegistration8DifferenceBefore} // \includegraphics[width=0.32\textwidth]{ImageRegistration8DifferenceAfter} // \itkcaption[CenteredTransformInitializer output images]{Resampled moving // image (left). Differences between fixed and moving images, before (center) // and after (right) registration with the // CenteredTransformInitializer.} // \label{fig:ImageRegistration8Outputs} // \end{figure} // // Figure \ref{fig:ImageRegistration8Outputs} shows the output of the // registration. The center image in this figure shows the differences // between the fixed image and the resampled moving image before the // registration. The image on the right side presents the difference between // the fixed image and the resampled moving image after the registration has // been performed. Note that these images are individual slices extracted // from the actual volumes. For details, look at the source code of this // example, where the ExtractImageFilter is used to extract a slice from the // the center of each one of the volumes. One of the main purposes of this // example is to illustrate that the toolkit can perform registration on // images of any dimension. The only limitations are, as usual, the amount of // memory available for the images and the amount of computation time that it // will take to complete the optimization process. // // \begin{figure} // \center // \includegraphics[height=0.32\textwidth]{ImageRegistration8TraceMetric} // \includegraphics[height=0.32\textwidth]{ImageRegistration8TraceAngle} // \includegraphics[height=0.32\textwidth]{ImageRegistration8TraceTranslations} // \itkcaption[CenteredTransformInitializer output plots]{Plots of the metric, // rotation angle, center of rotation and translations during the // registration using CenteredTransformInitializer.} // \label{fig:ImageRegistration8Plots} // \end{figure} // // Figure \ref{fig:ImageRegistration8Plots} shows the plots of the main // output parameters of the registration process. The metric values at every // iteration. The Z component of the versor is plotted as an indication of // how the rotation progress. The X,Y translation components of the // registration are plotted at every iteration too. // // Shell and Gnuplot scripts for generating the diagrams in // Figure~\ref{fig:ImageRegistration8Plots} are available in the directory // // \code{InsightDocuments/SoftwareGuide/Art} // // You are strongly encouraged to run the example code, since only in this // way you can gain a first hand experience with the behavior of the // registration process. Once again, this is a simple reflection of the // philosophy that we put forward in this book: // // \emph{If you can not replicate it, then it does not exist!}. // // We have seen enough published papers with pretty pictures, presenting // results that in practice are impossible to replicate. That is vanity, not // science. // // Software Guide : EndLatex typedef itk::ResampleImageFilter< MovingImageType, FixedImageType > ResampleFilterType; TransformType::Pointer finalTransform = TransformType::New(); finalTransform->SetCenter( transform->GetCenter() ); finalTransform->SetParameters( finalParameters ); finalTransform->SetFixedParameters( transform->GetFixedParameters() ); ResampleFilterType::Pointer resampler = ResampleFilterType::New(); resampler->SetTransform( finalTransform ); resampler->SetInput( movingImageReader->GetOutput() ); FixedImageType::Pointer fixedImage = fixedImageReader->GetOutput(); resampler->SetSize( fixedImage->GetLargestPossibleRegion().GetSize() ); resampler->SetOutputOrigin( fixedImage->GetOrigin() ); resampler->SetOutputSpacing( fixedImage->GetSpacing() ); resampler->SetOutputDirection( fixedImage->GetDirection() ); resampler->SetDefaultPixelValue( 100 ); typedef unsigned char OutputPixelType; typedef itk::Image< OutputPixelType, Dimension > OutputImageType; typedef itk::CastImageFilter< FixedImageType, OutputImageType > CastFilterType; typedef itk::ImageFileWriter< OutputImageType > WriterType; WriterType::Pointer writer = WriterType::New(); CastFilterType::Pointer caster = CastFilterType::New(); writer->SetFileName( argv[3] ); caster->SetInput( resampler->GetOutput() ); writer->SetInput( caster->GetOutput() ); writer->Update(); typedef itk::SubtractImageFilter< FixedImageType, FixedImageType, FixedImageType > DifferenceFilterType; DifferenceFilterType::Pointer difference = DifferenceFilterType::New(); typedef itk::RescaleIntensityImageFilter< FixedImageType, OutputImageType > RescalerType; RescalerType::Pointer intensityRescaler = RescalerType::New(); intensityRescaler->SetInput( difference->GetOutput() ); intensityRescaler->SetOutputMinimum( 0 ); intensityRescaler->SetOutputMaximum( 255 ); difference->SetInput1( fixedImageReader->GetOutput() ); difference->SetInput2( resampler->GetOutput() ); resampler->SetDefaultPixelValue( 1 ); WriterType::Pointer writer2 = WriterType::New(); writer2->SetInput( intensityRescaler->GetOutput() ); // Compute the difference image between the // fixed and resampled moving image. if( argc > 5 ) { writer2->SetFileName( argv[5] ); writer2->Update(); } typedef itk::IdentityTransform< double, Dimension > IdentityTransformType; IdentityTransformType::Pointer identity = IdentityTransformType::New(); // Compute the difference image between the // fixed and moving image before registration. if( argc > 4 ) { resampler->SetTransform( identity ); writer2->SetFileName( argv[4] ); writer2->Update(); } // // Here we extract slices from the input volume, and the difference volumes // produced before and after the registration. These slices are presented as // figures in the Software Guide. // // typedef itk::Image< OutputPixelType, 2 > OutputSliceType; typedef itk::ExtractImageFilter< OutputImageType, OutputSliceType > ExtractFilterType; ExtractFilterType::Pointer extractor = ExtractFilterType::New(); extractor->SetDirectionCollapseToSubmatrix(); extractor->InPlaceOn(); FixedImageType::RegionType inputRegion = fixedImage->GetLargestPossibleRegion(); FixedImageType::SizeType size = inputRegion.GetSize(); FixedImageType::IndexType start = inputRegion.GetIndex(); // Select one slice as output size[2] = 0; start[2] = 90; FixedImageType::RegionType desiredRegion; desiredRegion.SetSize( size ); desiredRegion.SetIndex( start ); extractor->SetExtractionRegion( desiredRegion ); typedef itk::ImageFileWriter< OutputSliceType > SliceWriterType; SliceWriterType::Pointer sliceWriter = SliceWriterType::New(); sliceWriter->SetInput( extractor->GetOutput() ); if( argc > 6 ) { extractor->SetInput( caster->GetOutput() ); resampler->SetTransform( identity ); sliceWriter->SetFileName( argv[6] ); sliceWriter->Update(); } if( argc > 7 ) { extractor->SetInput( intensityRescaler->GetOutput() ); resampler->SetTransform( identity ); sliceWriter->SetFileName( argv[7] ); sliceWriter->Update(); } if( argc > 8 ) { resampler->SetTransform( finalTransform ); sliceWriter->SetFileName( argv[8] ); sliceWriter->Update(); } if( argc > 9 ) { extractor->SetInput( caster->GetOutput() ); resampler->SetTransform( finalTransform ); sliceWriter->SetFileName( argv[9] ); sliceWriter->Update(); } return EXIT_SUCCESS; }
double Mesh::computeStandardDeviationFromPixelsInside(ImageType::Pointer image) { MeshTypeB::Pointer mesh = MeshTypeB::New(); typedef itk::Point< double, 3 > PointType; PointType pnt; ImageType::IndexType index; CVector3 p, n, min(10000,10000,10000), max; for (unsigned int i=0; i<points_.size(); i++) { p = points_[i]->getPosition(); pnt[0] = p[0]; pnt[1] = p[1]; pnt[2] = p[2]; mesh->SetPoint(i,pnt); image->TransformPhysicalPointToIndex(pnt, index); if (index[0]<min[0]) min[0]=index[0]; if (index[1]<min[1]) min[1]=index[1]; if (index[2]<min[2]) min[2]=index[2]; if (index[0]>max[0]) max[0]=index[0]; if (index[1]>max[1]) max[1]=index[1]; if (index[2]>max[2]) max[2]=index[2]; } for (unsigned int i=0; i<triangles_.size(); i+=3) { CellTypeB::CellAutoPointer triangle; triangle.TakeOwnership(new CellTypeB); triangle->SetPointId(0,triangles_[i]); triangle->SetPointId(1,triangles_[i+1]); triangle->SetPointId(2,triangles_[i+2]); mesh->SetCell((int)(i+1)/3,triangle); } CastFilterType::Pointer castFilter = CastFilterType::New(); castFilter->SetInput(image); BinaryImageType::Pointer im = castFilter->GetOutput(); BinaryImageType::IndexType indexRegion; BinaryImageType::SizeType sizeRegion; sizeRegion[0] = max[0]-min[0]+5; // adding two pixels at each side to be sure sizeRegion[1] = max[1]-min[1]+5; sizeRegion[2] = max[2]-min[2]+5; indexRegion[0] = min[0]-2; indexRegion[1] = min[1]-2; indexRegion[2] = min[2]-2; BinaryImageType::RegionType region(indexRegion,sizeRegion); im->SetRegions(region); MeshFilterType::Pointer meshFilter = MeshFilterType::New(); meshFilter->SetInput(mesh); meshFilter->SetInfoImage(im); /*meshFilter->SetDirection(image->GetDirection()); meshFilter->SetSpacing(image->GetSpacing()); meshFilter->SetOrigin(image->GetOrigin()); meshFilter->SetSize(sizeRegion); meshFilter->SetIndex(indexRegion);*/ meshFilter->SetTolerance(1.0); meshFilter->SetInsideValue(1.0); meshFilter->SetOutsideValue(0.0); try { meshFilter->Update(); } catch( itk::ExceptionObject & e ) { cout << "Exception thrown ! " << endl; cout << "An error ocurred during creating binary image" << endl; cout << "Location = " << e.GetLocation() << endl; cout << "Description = " << e.GetDescription() << endl; } MeshFilterType::OutputImageType::Pointer binary = meshFilter->GetOutput(); vector<double> valueVoxels; typedef ImageType::IndexType IndexType; IndexType ind; ImageIterator it( binary, binary->GetRequestedRegion() ); it.GoToBegin(); while(!it.IsAtEnd()) { if (it.Get()==true) { ind = it.GetIndex(); valueVoxels.push_back(image->GetPixel(ind)); } ++it; } double mean = 0.0, sum = 0.0, std = 0.0, nbVoxels = valueVoxels.size(); for (int i=0; i<nbVoxels; i++) mean += valueVoxels[i]; mean /= nbVoxels; for (int i=0; i<nbVoxels; i++) { sum += valueVoxels[i]*valueVoxels[i]; } std = sqrt(sum/nbVoxels-mean*mean); /*ofstream myfile; myfile.open("StandardDeviation.txt", ios_base::app); myfile << ind[1] << " " << mean << " " << std << endl; myfile.close();*/ return mean; }
void MyImageClass::SaveDICOMSeries(QString save_path, std::string subfolder) { std::string output_directory = save_path.toStdString(); output_directory +=subfolder; itksys::SystemTools::MakeDirectory( output_directory.c_str() ); typedef signed short OutputPixelType; const unsigned int output_pixel_dimension = 2; typedef itk::Image < OutputPixelType, output_pixel_dimension > Image2Dtype; typedef itk::CastImageFilter<InternalImageType, ImageType> CastFilterType; typedef itk::ImageSeriesWriter < ImageType, Image2Dtype> SeriesWriterType; CastFilterType::Pointer caster = CastFilterType::New(); SeriesWriterType::Pointer series_writer = SeriesWriterType::New(); typedef itk::NumericSeriesFileNames NumericNamesGeneratorType; NumericNamesGeneratorType::Pointer namesGenerator = NumericNamesGeneratorType::New(); itk::MetaDataDictionary &dict = gdcmIO_->GetMetaDataDictionary(); std::string tagkey,value; tagkey = "0008|0060"; value = "MR"; itk::EncapsulateMetaData<std::string>(dict,tagkey,value); tagkey = "0008|0008"; value = "DERIVED\\SECONDARY"; itk::EncapsulateMetaData<std::string>(dict,tagkey,value); tagkey = "0008|0064"; value = "DV"; itk::EncapsulateMetaData<std::string>(dict,tagkey,value); caster->SetInput(reader_->GetOutput()); series_writer->SetInput( caster->GetOutput()); series_writer->SetImageIO(gdcmIO_); ImageType::RegionType region = reader_->GetOutput()->GetLargestPossibleRegion(); ImageType::IndexType start = region.GetIndex(); ImageType::SizeType size = region.GetSize(); std::string format = output_directory; format += "/image%03d.dcm"; namesGenerator->SetSeriesFormat(format.c_str()); namesGenerator->SetStartIndex(start[2]); namesGenerator->SetEndIndex(start[2]+size[2]-1); namesGenerator->SetIncrementIndex(1); series_writer->SetFileNames (namesGenerator->GetFileNames()); series_writer->SetMetaDataDictionaryArray(reader_->GetMetaDataDictionaryArray()); try { series_writer->Update(); } catch( itk::ExceptionObject &excp) { msg_box_.setText(excp.GetDescription()); msg_box_.exec(); } }