From 93b8df062a36ca152f3cb20d08ea9b9ce9c1e45f Mon Sep 17 00:00:00 2001 From: David Sarrut Date: Fri, 3 Feb 2012 07:57:12 +0100 Subject: [PATCH] First working version (allow to write rt-struct) --- common/clitkImage2DicomRTStructFilter.h | 6 +- common/clitkImage2DicomRTStructFilter.txx | 144 +++++++--------------- itk/clitkBinaryImageToMeshFilter.h | 42 +------ itk/clitkBinaryImageToMeshFilter.txx | 132 ++------------------ 4 files changed, 68 insertions(+), 256 deletions(-) diff --git a/common/clitkImage2DicomRTStructFilter.h b/common/clitkImage2DicomRTStructFilter.h index 5eb6ddc..924bcc0 100644 --- a/common/clitkImage2DicomRTStructFilter.h +++ b/common/clitkImage2DicomRTStructFilter.h @@ -46,6 +46,8 @@ namespace clitk { itkSetMacro(StructureSetFilename, std::string); itkSetMacro(DicomFolder, std::string); itkSetMacro(OutputFilename, std::string); + void SetROIName(std::string name, std::string type); + itkSetMacro(ThresholdValue, PixelType); // Run filter void Update(); @@ -55,7 +57,9 @@ namespace clitk { std::string m_StructureSetFilename; std::string m_DicomFolder; std::string m_OutputFilename; - + std::string m_ROIName; + std::string m_ROIType; + PixelType m_ThresholdValue; }; //-------------------------------------------------------------------- diff --git a/common/clitkImage2DicomRTStructFilter.txx b/common/clitkImage2DicomRTStructFilter.txx index cc90104..051211b 100644 --- a/common/clitkImage2DicomRTStructFilter.txx +++ b/common/clitkImage2DicomRTStructFilter.txx @@ -57,7 +57,10 @@ template clitk::Image2DicomRTStructFilter::Image2DicomRTStructFilter() { - DD("Image2DicomRTStructFilter Const"); + m_StructureSetFilename = ""; + m_DicomFolder = ""; + m_OutputFilename = "default-output.dcm"; + m_ThresholdValue = 0.5; } //-------------------------------------------------------------------- @@ -66,36 +69,40 @@ clitk::Image2DicomRTStructFilter::Image2DicomRTStructFilter() template clitk::Image2DicomRTStructFilter::~Image2DicomRTStructFilter() { - DD("Image2DicomRTStructFilter Destructor"); } //-------------------------------------------------------------------- //-------------------------------------------------------------------- template -void clitk::Image2DicomRTStructFilter::Update() +void +clitk::Image2DicomRTStructFilter::SetROIName(std::string name, std::string type) { - DD("Image2DicomRTStructFilter::GenerateData"); + m_ROIName = name; + m_ROIType = type; +} +//-------------------------------------------------------------------- + +//-------------------------------------------------------------------- +template +void clitk::Image2DicomRTStructFilter::Update() +{ // Read rt struct vtkSmartPointer reader = vtkGDCMPolyDataReader::New(); reader->SetFileName(m_StructureSetFilename.c_str()); reader->Update(); - DD("reader done"); // Get properties vtkRTStructSetProperties * p = reader->GetRTStructSetProperties(); - DD(p->GetNumberOfStructureSetROIs()); - DD(p->GetStructureSetROIName(0)); - DD(p->GetStructureSetROINumber(0)); + if (GetVerboseFlag()) { + std::cout << "Number of structures in the dicom-rt-struct : " + << p->GetNumberOfStructureSetROIs() << std::endl; + } // Init writer vtkGDCMPolyDataWriter * writer = vtkGDCMPolyDataWriter::New(); int numMasks = reader->GetNumberOfOutputPorts() + 1;//add one more - DD(numMasks); - - // numMasks = 3; //FIXME temporary - writer->SetNumberOfInputPorts(numMasks); writer->SetFileName(m_OutputFilename.c_str()); writer->SetMedicalImageProperties(reader->GetMedicalImageProperties()); @@ -108,41 +115,37 @@ void clitk::Image2DicomRTStructFilter::Update() roiAlgorithms->SetNumberOfValues(numMasks); roiTypes->SetNumberOfValues(numMasks); + // Convert the image into a mesh typedef clitk::BinaryImageToMeshFilter BinaryImageToMeshFilterType; typename BinaryImageToMeshFilterType::Pointer convert = BinaryImageToMeshFilterType::New(); + convert->SetThresholdValue(m_ThresholdValue); convert->SetInput(m_Input); - DD("Update"); convert->Update(); - DD("here"); - DD("end update"); vtkPolyData* mesh = convert->GetOutputMesh(); - DD(mesh->GetNumberOfVerts()); - DD(mesh->GetNumberOfLines()); - DD(mesh->GetNumberOfPolys()); - DD(mesh->GetNumberOfStrips()); - - // Add on (FIXME) to replace with binary image - // vtkPolyData* blank = vtkPolyData::New(); - // writer->SetInput(0, blank); - writer->SetInput(0, mesh); - roiNames->InsertValue(0, "blank"); - roiAlgorithms->InsertValue(0, "blank"); - roiTypes->InsertValue(0, "ORGAN"); - - for (unsigned int i = 1; i < numMasks; ++i) { - // DD(i); - writer->SetInput(i, reader->GetOutput(i-1)); - std::string theString = reader->GetRTStructSetProperties()->GetStructureSetROIName(i-1); + if (GetVerboseFlag()) { + std::cout << "Mesh has " << mesh->GetNumberOfLines() << " lines." << std::endl; + } + + // Copy previous contours + for (unsigned int i = 0; i < numMasks-1; ++i) { + writer->SetInput(i, reader->GetOutput(i)); + std::string theString = reader->GetRTStructSetProperties()->GetStructureSetROIName(i); roiNames->InsertValue(i, theString); - theString = reader->GetRTStructSetProperties()->GetStructureSetROIGenerationAlgorithm(i-1); + theString = reader->GetRTStructSetProperties()->GetStructureSetROIGenerationAlgorithm(i); roiAlgorithms->InsertValue(i, theString); - theString = reader->GetRTStructSetProperties()->GetStructureSetRTROIInterpretedType(i-1); + theString = reader->GetRTStructSetProperties()->GetStructureSetRTROIInterpretedType(i); roiTypes->InsertValue(i, theString); - } - + } + + // Add new one + int last = numMasks-1; + writer->SetInput(last, mesh); + roiNames->InsertValue(last, m_ROIName); + roiAlgorithms->InsertValue(last, "CLITK_CREATED"); + roiTypes->InsertValue(last, m_ROIType); /* - // Visu + // Visu DEBUG vtkPolyDataMapper *cubeMapper = vtkPolyDataMapper::New(); cubeMapper->SetInput( mesh ); cubeMapper->SetScalarRange(0,7); @@ -167,80 +170,25 @@ void clitk::Image2DicomRTStructFilter::Update() renWin->Render(); iren->Start(); */ - - // End visu - + // Write (need to read dicom for slice id) vtkRTStructSetProperties* theProperties = vtkRTStructSetProperties::New(); - DD(p->GetStudyInstanceUID()); writer->SetRTStructSetProperties(theProperties); - /*writer->InitializeRTStructSet2(p,"./", - reader->GetRTStructSetProperties()->GetStructureSetLabel(), - reader->GetRTStructSetProperties()->GetStructureSetName(), - roiNames, roiAlgorithms, roiTypes);*/ + if (GetVerboseFlag()) { + std::cout << "Looking for dicom info, study instance " + << p->GetStudyInstanceUID() << std::endl; + } writer->InitializeRTStructSet(m_DicomFolder, reader->GetRTStructSetProperties()->GetStructureSetLabel(), reader->GetRTStructSetProperties()->GetStructureSetName(), - roiNames, roiAlgorithms, roiTypes); - - DD("after init"); + roiNames, roiAlgorithms, roiTypes); writer->Write(); - DD("write done"); - reader->Delete(); roiNames->Delete(); roiTypes->Delete(); - //theProperties->Delete(); roiAlgorithms->Delete(); - //blank->Delete(); writer->Delete(); - - //////////////////// - - - /* - - // DicomRTStruct - DD(m_StructureSet->GetName()); - clitk::DicomRT_ROI * roi = m_StructureSet->GetROIFromROINumber(1); // Aorta - DD(roi->GetName()); - DD(roi->GetROINumber()); - - - // Get - - - - - // Add an image to the roi - vvImage::Pointer im = vvImageFromITK<3, PixelType>(m_Input); - roi->SetImage(im); - - // Get one contour - DD("Compute Mesh"); - roi->ComputeContoursFromImage(); // FIXME do the set mesh for the moment (to change) - // roi->ComputeMeshFromContour(); - vtkSmartPointer mesh = roi->GetMesh(); - DD("done"); - - // Change the mesh (shift by 10); - // const vtkSmartPointer & points = mesh->GetPoints(); - // for(uint i=0; iGetNumberOfVerts (); i++) { - // DD(i); - // double * p = points->GetPoint(i); - // p[0] += 30; - // points->SetPoint(i, p); - // } - roi->SetName("TOTO"); - roi->SetDicomUptodateFlag(true); // indicate that dicom info must be updated from the mesh. - - // Convert to dicom ? - DD("TODO"); - - // Write - structset->Write("toto.dcm"); - */ } //-------------------------------------------------------------------- diff --git a/itk/clitkBinaryImageToMeshFilter.h b/itk/clitkBinaryImageToMeshFilter.h index 0a36c36..e2b2198 100644 --- a/itk/clitkBinaryImageToMeshFilter.h +++ b/itk/clitkBinaryImageToMeshFilter.h @@ -42,13 +42,12 @@ namespace clitk { -------------------------------------------------------------------- */ template - class ITK_EXPORT BinaryImageToMeshFilter:public itk::Object //:public clitk::FilterBase + class ITK_EXPORT BinaryImageToMeshFilter:public itk::Object { public: /** Standard class typedefs. */ - // typedef itk::ImageToMeshFilter Superclass; - typedef itk::ProcessObject Superclass; + typedef itk::ProcessObject Superclass; typedef BinaryImageToMeshFilter Self; typedef itk::SmartPointer Pointer; typedef itk::SmartPointer ConstPointer; @@ -63,48 +62,14 @@ namespace clitk { itkStaticConstMacro(ImageDimension, unsigned int, ImageType::ImageDimension); // /** Some convenient typedefs. */ - // typedef typename ImageType::ConstPointer ImageConstPointer; typedef typename ImageType::Pointer ImagePointer; - // typedef typename ImageType::RegionType RegionType; typedef typename ImageType::PixelType PixelType; - // typedef typename ImageType::SpacingType SpacingType; - // typedef typename ImageType::SizeType SizeType; - // typedef typename ImageType::PointType PointType; - //typedef itk::ProcessObject::DataObjectPointerArraySizeType DataObjectPointerArraySizeType; - // typedef vtkSmartPointer DataObjectPointer; - - // using Superclass::SetInput; - // void SetInput(unsigned int idx, const ImageType *input); - // void SetInput(const ImageType *input) - // { - // m_this->SetInput(0, input); - // } - - // const ImageType * GetInput(unsigned int idx); - // const ImageType * GetInput() - // { - // return this->GetInput(0); - // } - - //virtual DataObjectPointer MakeOutput(DataObjectPointerArraySizeType idx); - // virtual void GenerateData(); - // virtual void GenerateOutputInformation(); - - /** Input : initial image and object */ - // itkSetMacro(Mesh, vtkSmartPointer); - // itkGetConstMacro(Mesh, vtkSmartPointer); - - // itkSetMacro(LikeImage, ImagePointer); - // itkGetConstMacro(LikeImage, ImagePointer); - // itkSetMacro(Extrude, bool); - // itkGetMacro(Extrude, bool); - // itkBooleanMacro(Extrude); itkSetMacro(Input, ImagePointer); itkGetConstMacro(Input, ImagePointer); itkGetMacro(OutputMesh, vtkSmartPointer); + itkSetMacro(ThresholdValue, PixelType); - // virtual void GenerateOutputInformation(); virtual void Update(); protected: @@ -113,6 +78,7 @@ namespace clitk { ImagePointer m_Input; vtkSmartPointer m_OutputMesh; + PixelType m_ThresholdValue; private: BinaryImageToMeshFilter(const Self&); //purposely not implemented diff --git a/itk/clitkBinaryImageToMeshFilter.txx b/itk/clitkBinaryImageToMeshFilter.txx index 9ffe4a2..8a14edc 100644 --- a/itk/clitkBinaryImageToMeshFilter.txx +++ b/itk/clitkBinaryImageToMeshFilter.txx @@ -20,81 +20,19 @@ //-------------------------------------------------------------------- template clitk::BinaryImageToMeshFilter:: -BinaryImageToMeshFilter()//:ProcessObject() +BinaryImageToMeshFilter():itk::Object() { - DD("BinaryImageToMeshFilter constructor"); - // this->ProcessObject::SetNumberOfRequiredInputs(1); - // this->ProcessObject::SetNumberOfRequiredOutputs(1); - - // //m_OutputMesh = vtkPolyData::New(); - - // this->ProcessObject::SetNumberOfRequiredOutputs(1); - // itk::DataObject::Pointer a = itk::DataObject::New(); - // this->ProcessObject::SetNthOutput( 0, a); + m_ThresholdValue = 0.5; // (for image with 0=background and 1=foreground) } //-------------------------------------------------------------------- -//-------------------------------------------------------------------- -/*template - void - clitk::BinaryImageToMeshFilter:: - GenerateOutputInformation() - { - DD("GenerateOutputInformation"); - // ImagePointer output = this->GetOutput(0); - - // // Set the region to output - // typename ImageType::RegionType m_Region = m_LikeImage->GetLargestPossibleRegion(); - // typename ImageType::SizeType size = m_Region.GetSize(); - // size[0]++; - // size[1]++; - // size[2]++; - // m_Region.SetSize(size); - // output->SetLargestPossibleRegion(m_Region); - // output->SetRequestedRegion(m_Region); - // output->SetBufferedRegion(m_Region); - // output->SetRegions(m_Region); - // output->Allocate(); - } -*/ -//-------------------------------------------------------------------- - - -// template -// void -// clitk::BinaryImageToMeshFilter:: -// SetInput(unsigned int idx, const ImageType *input) -// { -// DD(idx); -// // process object is not const-correct, the const_cast -// // is required here. -// this->ProcessObject::SetNthInput( idx, -// const_cast< ImageType * >( input ) ); -// DD("end"); -// } - -// template -// const ImageType * -// clitk::BinaryImageToMeshFilter:: -// GetInput(unsigned int idx) -// { -// DD("GetInput"); -// DD(idx); -// return dynamic_cast< const ImageType * > -// ( this->ProcessObject::GetInput(idx) ); -// } - - //-------------------------------------------------------------------- template void clitk::BinaryImageToMeshFilter:: Update() -//GenerateOutputInformation() { - DD("Update"); - // Convert itk image into vtk image const ImageType * im = this->GetInput(); typedef itk::ImageToVTKImageFilter ConvertType; @@ -107,88 +45,44 @@ Update() vtkSmartPointer clipper = vtkSmartPointer::New(); clipper->SetInput(input_vtk); int* extent = input_vtk->GetExtent(); - DDV(extent, 6); // Loop on slices vtkSmartPointer append = vtkSmartPointer::New(); uint n = input_vtk->GetDimensions()[2]; - DD(n); - std::vector > contours; + // std::vector > contours; for(uint i=0; i squares = vtkSmartPointer::New(); squares->SetInput(input_vtk); squares->SetImageRange(extent[0], extent[1], extent[2], extent[3], i, i); squares->SetNumberOfContours(1); - squares->SetValue(0, 0.5); // FIXME background (?) - squares->Update(); - // DD(squares->GetNumberOfContours()); - + squares->SetValue(0, m_ThresholdValue); + squares->Update(); vtkSmartPointer m = squares->GetOutput(); - DD(m->GetMaxCellSize()); - DD(m->GetNumberOfVerts()); - DD(m->GetNumberOfLines()); - DD(m->GetNumberOfPolys()); - DD(m->GetNumberOfStrips()); + // Strip (needed) + vtkSmartPointer vs = vtkSmartPointer::New(); + vs->SetInput(squares->GetOutput()); + vs->Update(); + m = vs->GetOutput(); // Decimate - if (false) { // FIXME + if (false) { // FIXME (do not work) vtkSmartPointer psurface = vtkDecimatePro::New(); psurface->SetInputConnection(squares->GetOutputPort()); psurface->SetTargetReduction(0.5); psurface->Update(); m = psurface->GetOutput(); } - if (true) { - vtkSmartPointer vs = vtkSmartPointer::New(); - vs->SetInput(squares->GetOutput()); - vs->Update(); - m = vs->GetOutput(); - } - - //vtkSmartPointer m = squares->GetOutput(); - contours.push_back(m); - DD(m->GetMaxCellSize()); - DD(m->GetNumberOfVerts()); - DD(m->GetNumberOfLines()); - DD(m->GetNumberOfPolys()); - DD(m->GetNumberOfStrips()); - // m->Print(std::cout); - // FIXME : only add if lines>0 + // only add if lines>0 if (m->GetNumberOfLines() > 0) { - append->AddInput(contours[i]); + append->AddInput(m);//contours[i]); } } - DD("done"); - - DD("now append"); - // for(unsigned int i=0; iAddInput(contours[i]); - // } append->Update(); - DD(" copy"); m_OutputMesh = vtkSmartPointer::New(); m_OutputMesh->DeepCopy(append->GetOutput()); - - /* // NO (3D) - vtkSmartPointer pcontour = vtkContourFilter::New(); - pcontour->SetValue(0, 0.5); - pcontour->SetInput(input_vtk); - pcontour->Update(); - // vtkAlgorithmOutput *data = pcontour->GetOutputPort(); - // vtkSmartPointer skinMapper = vtkPolyDataMapper::New(); - // skinMapper->SetInputConnection(data); //psurface->GetOutputPort() - // skinMapper->ScalarVisibilityOff(); - m_OutputMesh = pcontour->GetOutput();//data - */ - - DD("end"); - int a=12; - DD("erelre"); } //-------------------------------------------------------------------- -- 2.46.0