From 6986b996d66273ab7818c12f51cbf5ae049ac04e Mon Sep 17 00:00:00 2001 From: David Sarrut Date: Fri, 3 Feb 2012 07:57:12 +0100 Subject: [PATCH] First version to convert image to dicomrtstruct --- common/clitkDicomRTStruct2ImageFilter.cxx | 3 +- common/clitkImage2DicomRTStructFilter.h | 11 +- common/clitkImage2DicomRTStructFilter.txx | 159 +++++++++++++++++- itk/clitkBinaryImageToMeshFilter.h | 131 +++++++++++++++ itk/clitkBinaryImageToMeshFilter.txx | 194 ++++++++++++++++++++++ 5 files changed, 485 insertions(+), 13 deletions(-) create mode 100644 itk/clitkBinaryImageToMeshFilter.h create mode 100644 itk/clitkBinaryImageToMeshFilter.txx diff --git a/common/clitkDicomRTStruct2ImageFilter.cxx b/common/clitkDicomRTStruct2ImageFilter.cxx index fa66cfb..e52fc0f 100644 --- a/common/clitkDicomRTStruct2ImageFilter.cxx +++ b/common/clitkDicomRTStruct2ImageFilter.cxx @@ -160,6 +160,7 @@ void clitk::DicomRTStruct2ImageFilter::SetOutputSize(const unsigned long* size) //-------------------------------------------------------------------- void clitk::DicomRTStruct2ImageFilter::Update() { + DD("DicomRTStruct2ImageFilter::Update"); if (!mROI) { std::cerr << "Error. No ROI set, please use SetROI." << std::endl; exit(0); @@ -170,7 +171,7 @@ void clitk::DicomRTStruct2ImageFilter::Update() } // Get Mesh - vtkPolyData * mesh = mROI->GetMesh(); + vtkPolyData * mesh = mROI->GetMesh(); // Get bounds double *bounds=mesh->GetBounds(); diff --git a/common/clitkImage2DicomRTStructFilter.h b/common/clitkImage2DicomRTStructFilter.h index 749a0be..5eb6ddc 100644 --- a/common/clitkImage2DicomRTStructFilter.h +++ b/common/clitkImage2DicomRTStructFilter.h @@ -43,16 +43,19 @@ namespace clitk { // Set inputs itkSetMacro(Input, ImagePointer); itkGetConstMacro(Input, ImagePointer); + itkSetMacro(StructureSetFilename, std::string); + itkSetMacro(DicomFolder, std::string); + itkSetMacro(OutputFilename, std::string); // Run filter void Update(); - // Get output - itkGetConstMacro(DicomRTStruct, DicomRTStructPointer); - protected: ImagePointer m_Input; - DicomRTStructPointer m_DicomRTStruct; + std::string m_StructureSetFilename; + std::string m_DicomFolder; + std::string m_OutputFilename; + }; //-------------------------------------------------------------------- diff --git a/common/clitkImage2DicomRTStructFilter.txx b/common/clitkImage2DicomRTStructFilter.txx index 6ab72e2..cc90104 100644 --- a/common/clitkImage2DicomRTStructFilter.txx +++ b/common/clitkImage2DicomRTStructFilter.txx @@ -23,6 +23,7 @@ // clitk #include "clitkImage2DicomRTStructFilter.h" +#include "clitkBinaryImageToMeshFilter.h" #include "clitkImageCommon.h" #include "vvFromITK.h" @@ -34,10 +35,24 @@ #include #include +// FIXME to remove +#include "vtkPolyDataMapper.h" +#include "vtkPolyDataMapper2D.h" +#include "vtkRenderWindowInteractor.h" +#include "vtkPolyDataReader.h" +#include "vtkRenderWindow.h" +#include "vtkRenderer.h" +#include "vtkCamera.h" +#include "vtkProperty.h" +#include "vtkProperty2D.h" + // itk #include #include +// gdcm +#include + //-------------------------------------------------------------------- template clitk::Image2DicomRTStructFilter::Image2DicomRTStructFilter() @@ -62,23 +77,150 @@ void clitk::Image2DicomRTStructFilter::Update() { DD("Image2DicomRTStructFilter::GenerateData"); - // Read DicomRTStruct - std::string filename = "RS.zzQAnotmt_french01_.dcm"; - clitk::DicomRT_StructureSet::Pointer structset = clitk::DicomRT_StructureSet::New(); - structset->Read(filename); + // 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)); + + // 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()); + + // List of already present rois + vtkStringArray* roiNames = vtkStringArray::New(); + vtkStringArray* roiAlgorithms = vtkStringArray::New(); + vtkStringArray* roiTypes = vtkStringArray::New(); + roiNames->SetNumberOfValues(numMasks); + roiAlgorithms->SetNumberOfValues(numMasks); + roiTypes->SetNumberOfValues(numMasks); - DD(structset->GetName()); - clitk::DicomRT_ROI * roi = structset->GetROIFromROINumber(1); // Aorta + typedef clitk::BinaryImageToMeshFilter BinaryImageToMeshFilterType; + typename BinaryImageToMeshFilterType::Pointer convert = BinaryImageToMeshFilterType::New(); + 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); + roiNames->InsertValue(i, theString); + theString = reader->GetRTStructSetProperties()->GetStructureSetROIGenerationAlgorithm(i-1); + roiAlgorithms->InsertValue(i, theString); + theString = reader->GetRTStructSetProperties()->GetStructureSetRTROIInterpretedType(i-1); + roiTypes->InsertValue(i, theString); + } + + + /* + // Visu + vtkPolyDataMapper *cubeMapper = vtkPolyDataMapper::New(); + cubeMapper->SetInput( mesh ); + cubeMapper->SetScalarRange(0,7); + vtkActor *cubeActor = vtkActor::New(); + cubeActor->SetMapper(cubeMapper); + vtkProperty * property = cubeActor->GetProperty(); + property->SetRepresentationToWireframe(); + + vtkRenderer *renderer = vtkRenderer::New(); + vtkRenderWindow *renWin = vtkRenderWindow::New(); + renWin->AddRenderer(renderer); + + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + renderer->AddActor(cubeActor); + renderer->ResetCamera(); + renderer->SetBackground(1,1,1); + + renWin->SetSize(300,300); + + renWin->Render(); + iren->Start(); + */ + + + // End visu + + + vtkRTStructSetProperties* theProperties = vtkRTStructSetProperties::New(); + DD(p->GetStudyInstanceUID()); + writer->SetRTStructSetProperties(theProperties); + /*writer->InitializeRTStructSet2(p,"./", + reader->GetRTStructSetProperties()->GetStructureSetLabel(), + reader->GetRTStructSetProperties()->GetStructureSetName(), + roiNames, roiAlgorithms, roiTypes);*/ + writer->InitializeRTStructSet(m_DicomFolder, + reader->GetRTStructSetProperties()->GetStructureSetLabel(), + reader->GetRTStructSetProperties()->GetStructureSetName(), + roiNames, roiAlgorithms, roiTypes); + + DD("after init"); + 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->ComputeMeshFromImage(); + roi->ComputeContoursFromImage(); // FIXME do the set mesh for the moment (to change) + // roi->ComputeMeshFromContour(); vtkSmartPointer mesh = roi->GetMesh(); DD("done"); @@ -91,13 +233,14 @@ void clitk::Image2DicomRTStructFilter::Update() // points->SetPoint(i, p); // } roi->SetName("TOTO"); - roi->SetDicomUptodateFlag(false); // indicate that dicom info must be updated from the mesh. + 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 new file mode 100644 index 0000000..0a36c36 --- /dev/null +++ b/itk/clitkBinaryImageToMeshFilter.h @@ -0,0 +1,131 @@ +/*========================================================================= + Program: vv http://www.creatis.insa-lyon.fr/rio/vv + + Authors belong to: + - University of LYON http://www.universite-lyon.fr/ + - Léon Bérard cancer center http://www.centreleonberard.fr + - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the copyright notices for more information. + + It is distributed under dual licence + + - BSD See included LICENSE.txt file + - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html + ======================================================================-====*/ + +#ifndef CLITKBINARYIMAGETOMESHFILTER_H +#define CLITKMESHTOBINARYIMAGEFILTER_H + +// clitk +#include "clitkCommon.h" +#include "vvFromITK.h" + +// itk +#include + +// vtk +#include +#include +#include +#include +#include +#include +#include + +namespace clitk { + + /* -------------------------------------------------------------------- + Convert a 3D binary image into a list of 2D contours (vtkpolydata) + -------------------------------------------------------------------- */ + + template + class ITK_EXPORT BinaryImageToMeshFilter:public itk::Object //:public clitk::FilterBase + { + + public: + /** Standard class typedefs. */ + // typedef itk::ImageToMeshFilter Superclass; + typedef itk::ProcessObject Superclass; + typedef BinaryImageToMeshFilter Self; + typedef itk::SmartPointer Pointer; + typedef itk::SmartPointer ConstPointer; + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(BinaryImageToMeshFilter, Superclass); + + /** ImageDimension constants */ + 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); + + // virtual void GenerateOutputInformation(); + virtual void Update(); + + protected: + BinaryImageToMeshFilter(); + virtual ~BinaryImageToMeshFilter() {} + + ImagePointer m_Input; + vtkSmartPointer m_OutputMesh; + + private: + BinaryImageToMeshFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + }; // end class + //-------------------------------------------------------------------- + +} // end namespace clitk +//-------------------------------------------------------------------- + +#ifndef ITK_MANUAL_INSTANTIATION +#include "clitkBinaryImageToMeshFilter.txx" +#endif + +#endif diff --git a/itk/clitkBinaryImageToMeshFilter.txx b/itk/clitkBinaryImageToMeshFilter.txx new file mode 100644 index 0000000..9ffe4a2 --- /dev/null +++ b/itk/clitkBinaryImageToMeshFilter.txx @@ -0,0 +1,194 @@ +/*========================================================================= + Program: vv http://www.creatis.insa-lyon.fr/rio/vv + + Authors belong to: + - University of LYON http://www.universite-lyon.fr/ + - Léon Bérard cancer center http://www.centreleonberard.fr + - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the copyright notices for more information. + + It is distributed under dual licence + + - BSD See included LICENSE.txt file + - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html + ======================================================================-====*/ + + +//-------------------------------------------------------------------- +template +clitk::BinaryImageToMeshFilter:: +BinaryImageToMeshFilter()//:ProcessObject() +{ + 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); +} +//-------------------------------------------------------------------- + + +//-------------------------------------------------------------------- +/*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; + typename ConvertType::Pointer convert = ConvertType::New(); + convert->SetInput(im); + convert->Update(); + vtkImageData * input_vtk = convert->GetOutput(); + + // Get extend + 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; + 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()); + + vtkSmartPointer m = squares->GetOutput(); + + DD(m->GetMaxCellSize()); + DD(m->GetNumberOfVerts()); + DD(m->GetNumberOfLines()); + DD(m->GetNumberOfPolys()); + DD(m->GetNumberOfStrips()); + + // Decimate + if (false) { // FIXME + 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 + if (m->GetNumberOfLines() > 0) { + append->AddInput(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.45.2