Skip to content

Commit

Permalink
Merge pull request #9 from smistad/upgrade-fast
Browse files Browse the repository at this point in the history
Added optional lung segmentation to airways filter
  • Loading branch information
olevs authored May 29, 2017
2 parents 8e0b83a + 9a673e0 commit d2df94b
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 32 deletions.
2 changes: 1 addition & 1 deletion install/cx/build/cxComponents.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
129 changes: 99 additions & 30 deletions source/plugins/org.custusx.filter.airways/cxAirwaysFilterService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -197,41 +197,66 @@ bool AirwaysFilter::execute()
fast::Image::pointer image = importer->getOutputData<fast::Image>();

// 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<fast::Segmentation>(1);

// Convert fast segmentation data to VTK data which CX can use (Airways)
vtkSmartPointer<fast::VTKImageExporter> 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<fast::VTKImageExporter> 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<fast::Segmentation>(0);

// Convert fast segmentation data to VTK data which CX can use
vtkSmartPointer<fast::VTKImageExporter> 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<fast::VTKImageExporter> 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<fast::Segmentation>(0);

// Get the transformation of the segmentation
Eigen::Affine3f T = fast::SceneGraph::getEigenAffineTransformationFromData(segmentationData);
mTransformation.matrix() = T.matrix().cast<double>(); // cast to double

// Extract centerline
fast::CenterlineExtraction::pointer centerline = fast::CenterlineExtraction::New();
centerline->setInputConnection(segmentation->getOutputPort());
centerline->setInputData(segmentationData);

// Get centerline
vtkSmartPointer<fast::VTKMeshExporter> vtkCenterlineExporter = fast::VTKMeshExporter::New();
Expand Down Expand Up @@ -262,15 +287,15 @@ bool AirwaysFilter::execute()

bool AirwaysFilter::postProcess()
{
if(!mSegmentationOutput)
if(!mAirwaySegmentationOutput)
return false;

std::cout << "POST PROCESS" << std::endl;

// 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
Expand All @@ -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<Mesh>(uid, name);
Expand All @@ -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()
Expand All @@ -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);
}


Expand All @@ -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 */

Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit d2df94b

Please sign in to comment.