diff --git a/install/cx/build/cxComponents.py b/install/cx/build/cxComponents.py index 13921c0c38..be8b7a0d72 100755 --- a/install/cx/build/cxComponents.py +++ b/install/cx/build/cxComponents.py @@ -531,7 +531,7 @@ def repository(self): return 'git@github.com:smistad/FAST' def update(self): self._getBuilder().gitSetRemoteURL(self.repository()) - self._getBuilder().gitCheckout('f81836597db0529f2b8e23d5ee9236cef7377b48') + self._getBuilder().gitCheckout('5e3ccf7f45d23c7aef2515a43e48323395a37f68') # branch = 'set_kernel_root_dir' # self._getBuilder()._changeDirToSource() # runShell('git checkout %s' % branch, ignoreFailure=False) diff --git a/source/plugins/org.custusx.filter.airways/cxAirwaysFilterService.cpp b/source/plugins/org.custusx.filter.airways/cxAirwaysFilterService.cpp index cb2f0032d7..e6e5c82935 100644 --- a/source/plugins/org.custusx.filter.airways/cxAirwaysFilterService.cpp +++ b/source/plugins/org.custusx.filter.airways/cxAirwaysFilterService.cpp @@ -52,7 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "cxPatientModelServiceProxy.h" #include "cxVisServices.h" #include "cxUtilHelpers.h" -// Test +#include "FAST/Algorithms/LungSegmentation/LungSegmentation.hpp" #include "FAST/Algorithms/AirwaySegmentation/AirwaySegmentation.hpp" #include "FAST/Algorithms/CenterlineExtraction/CenterlineExtraction.hpp" #include "FAST/Importers/ImageFileImporter.hpp" @@ -197,33 +197,58 @@ bool AirwaysFilter::execute() fast::Image::pointer image = importer->getOutputData(); // Do segmentation - fast::AirwaySegmentation::pointer segmentation = fast::AirwaySegmentation::New(); + fast::Segmentation::pointer segmentationData; + bool doLungSegmentation = getLungSegmentationOption(mOptions)->getValue(); bool useManualSeedPoint = getManualSeedPointOption(mOptions)->getValue(); - if(useManualSeedPoint) - { - CX_LOG_INFO() << "Using seed point: " << seedPoint.transpose(); - segmentation->setSeedPoint(seedPoint(0), seedPoint(1), seedPoint(2)); - } - segmentation->setInputConnection(importer->getOutputPort()); - try { - segmentation->update(); - } catch(fast::Exception &e) { - - CX_LOG_ERROR() << "The airways filter failed."; - if(!useManualSeedPoint) + try { + if(doLungSegmentation) { + fast::LungSegmentation::pointer segmentation = fast::LungSegmentation::New(); + if(useManualSeedPoint) { + CX_LOG_INFO() << "Using seed point: " << seedPoint.transpose(); + segmentation->setAirwaySeedPoint(seedPoint(0), seedPoint(1), seedPoint(2)); + } + segmentation->setInputConnection(importer->getOutputPort()); + segmentation->update(); + segmentationData = segmentation->getOutputData(1); + + // Convert fast segmentation data to VTK data which CX can use (Airways) + vtkSmartPointer vtkExporter = fast::VTKImageExporter::New(); + vtkExporter->setInputConnection(segmentation->getOutputPort(1)); + vtkExporter->Update(); + mAirwaySegmentationOutput = vtkExporter->GetOutput(); + + // Convert fast segmentation data to VTK data which CX can use (Lungs) + vtkSmartPointer vtkExporter2 = fast::VTKImageExporter::New(); + vtkExporter2->setInputConnection(segmentation->getOutputPort(0)); + vtkExporter2->Update(); + mLungSegmentationOutput = vtkExporter2->GetOutput(); + } else { + + fast::AirwaySegmentation::pointer segmentation = fast::AirwaySegmentation::New(); + if(useManualSeedPoint) { + CX_LOG_INFO() << "Using seed point: " << seedPoint.transpose(); + segmentation->setSeedPoint(seedPoint(0), seedPoint(1), seedPoint(2)); + } + segmentation->setInputConnection(importer->getOutputPort()); + segmentation->update(); + segmentationData = segmentation->getOutputData(0); + + // Convert fast segmentation data to VTK data which CX can use + vtkSmartPointer vtkExporter = fast::VTKImageExporter::New(); + vtkExporter->setInputConnection(segmentation->getOutputPort()); + vtkExporter->Update(); + mAirwaySegmentationOutput = vtkExporter->GetOutput(); + } + } catch(fast::Exception & e) + { + CX_LOG_ERROR() << "The airways filter failed."; + if(!useManualSeedPoint) CX_LOG_ERROR() << "Try to set the seed point manually."; - return false; - } + return false; + } - // Convert fast segmentation data to VTK data which CX can use - vtkSmartPointer vtkExporter = fast::VTKImageExporter::New(); - vtkExporter->setInputConnection(segmentation->getOutputPort()); - vtkExporter->Update(); - mSegmentationOutput = vtkExporter->GetOutput(); - CX_LOG_SUCCESS() << "FINISHED AIRWAY SEGMENTATION"; + CX_LOG_SUCCESS() << "FINISHED AIRWAY SEGMENTATION"; - // Get output segmentation data - fast::Segmentation::pointer segmentationData = segmentation->getOutputData(0); // Get the transformation of the segmentation Eigen::Affine3f T = fast::SceneGraph::getEigenAffineTransformationFromData(segmentationData); @@ -231,7 +256,7 @@ bool AirwaysFilter::execute() // Extract centerline fast::CenterlineExtraction::pointer centerline = fast::CenterlineExtraction::New(); - centerline->setInputConnection(segmentation->getOutputPort()); + centerline->setInputData(segmentationData); // Get centerline vtkSmartPointer vtkCenterlineExporter = fast::VTKMeshExporter::New(); @@ -262,7 +287,7 @@ bool AirwaysFilter::execute() bool AirwaysFilter::postProcess() { - if(!mSegmentationOutput) + if(!mAirwaySegmentationOutput) return false; std::cout << "POST PROCESS" << std::endl; @@ -270,7 +295,7 @@ bool AirwaysFilter::postProcess() // Make contour of segmented volume double threshold = 1; /// because the segmented image is 0..1 vtkPolyDataPtr rawContour = ContourFilter::execute( - mSegmentationOutput, + mAirwaySegmentationOutput, threshold, false, // reduce resolution true, // smoothing @@ -292,6 +317,34 @@ bool AirwaysFilter::postProcess() // Set output mOutputTypes[1]->setValue(contour->getUid()); + if(getLungSegmentationOption(mOptions)->getValue()) { + vtkPolyDataPtr rawContour = ContourFilter::execute( + mLungSegmentationOutput, + threshold, + false, // reduce resolution + true, // smoothing + true, // keep topology + 0 // target decimation + ); + //outputSegmentation->get_rMd_History()->setRegistration(rMd_i); + //patientService()->insertData(outputSegmentation); + + // Add contour internally to cx + QColor color("red"); + color.setAlpha(100); + MeshPtr contour = ContourFilter::postProcess( + patientService(), + rawContour, + mInputImage, + color + ); + contour->get_rMd_History()->setRegistration(mTransformation); + + // Set output + mOutputTypes[2]->setValue(contour->getUid()); + } + + // Centerline QString uid = mInputImage->getUid() + "_centerline%1"; QString name = mInputImage->getName() + " centerline%1"; MeshPtr centerline = patientService()->createSpecificData(uid, name); @@ -307,6 +360,7 @@ bool AirwaysFilter::postProcess() void AirwaysFilter::createOptions() { mOptionsAdapters.push_back(this->getManualSeedPointOption(mOptions)); + mOptionsAdapters.push_back(this->getLungSegmentationOption(mOptions)); } void AirwaysFilter::createInputTypes() @@ -325,16 +379,20 @@ void AirwaysFilter::createOutputTypes() //0 tempMeshStringAdapter = StringPropertySelectMesh::New(patientService()); - tempMeshStringAdapter->setValueName("Centerline"); + tempMeshStringAdapter->setValueName("Airway Centerline"); tempMeshStringAdapter->setHelp("Generated centerline mesh (vtk-format)."); mOutputTypes.push_back(tempMeshStringAdapter); //1 tempMeshStringAdapter = StringPropertySelectMesh::New(patientService()); - tempMeshStringAdapter->setValueName("Segmentation"); - tempMeshStringAdapter->setHelp("Generated surface of the segmented volume."); + tempMeshStringAdapter->setValueName("Airway Segmentation"); + tempMeshStringAdapter->setHelp("Generated surface of the airway segmentation volume."); mOutputTypes.push_back(tempMeshStringAdapter); + tempMeshStringAdapter = StringPropertySelectMesh::New(patientService()); + tempMeshStringAdapter->setValueName("Lung Segmentation"); + tempMeshStringAdapter->setHelp("Generated surface of the lung segmentation volume."); + mOutputTypes.push_back(tempMeshStringAdapter); } @@ -351,6 +409,17 @@ BoolPropertyPtr AirwaysFilter::getManualSeedPointOption(QDomElement root) } +BoolPropertyPtr AirwaysFilter::getLungSegmentationOption(QDomElement root) +{ + BoolPropertyPtr retval = + BoolProperty::initialize("Lung segmentation", + "", + "Selecting this option will also segment the two lung sacs", + false, root); + return retval; + +} + } /* namespace cx */ diff --git a/source/plugins/org.custusx.filter.airways/cxAirwaysFilterService.h b/source/plugins/org.custusx.filter.airways/cxAirwaysFilterService.h index e4188950a2..5fd3ad4ea2 100644 --- a/source/plugins/org.custusx.filter.airways/cxAirwaysFilterService.h +++ b/source/plugins/org.custusx.filter.airways/cxAirwaysFilterService.h @@ -85,7 +85,9 @@ Q_INTERFACES(cx::Filter) static Vector3D getSeedPointFromTool(SpaceProviderPtr spaceProvider, DataPtr image); static bool isSeedPointInsideImage(Vector3D, DataPtr); BoolPropertyPtr getManualSeedPointOption(QDomElement root); - vtkImageDataPtr mSegmentationOutput; + BoolPropertyPtr getLungSegmentationOption(QDomElement root); + vtkImageDataPtr mAirwaySegmentationOutput; + vtkImageDataPtr mLungSegmentationOutput; vtkPolyDataPtr mCenterlineOutput; Transform3D mTransformation; ImagePtr mInputImage;