37 #include <vtkImageImport.h> 38 #include <vtkImageData.h> 39 #include <vtkImageShiftScale.h> 40 #include <ctkPluginContext.h> 41 #include <vtkImplicitModeller.h> 42 #include <vtkContourFilter.h> 59 #include "FAST/Algorithms/LungSegmentation/LungSegmentation.hpp" 60 #include "FAST/Algorithms/AirwaySegmentation/AirwaySegmentation.hpp" 61 #include "FAST/Algorithms/CenterlineExtraction/CenterlineExtraction.hpp" 62 #include "FAST/Importers/ImageFileImporter.hpp" 63 #include "FAST/Exporters/VTKImageExporter.hpp" 64 #include "FAST/Exporters/VTKMeshExporter.hpp" 65 #include "FAST/Data/Segmentation.hpp" 66 #include "FAST/SceneGraph.hpp" 72 mDefaultStraightCLTubesOption(false)
74 fast::Reporter::setGlobalReportMethod(fast::Reporter::COUT);
76 fast::ImageFileImporter::pointer importer = fast::ImageFileImporter::New();
86 return "Airway Segmentation Filter";
91 return "airways_filter";
97 "<h3>Airway Segmentation.</h3>" 98 "<p><i>Extracts segmentation and centerline from a CT volume. If method fails, try to crop volume. </br>Algorithm written by Erik Smistad.</i></p>" 104 return "_centerline";
120 Vector3D point = spaceProvider->getActiveToolTipPoint(
121 spaceProvider->getD(data));
125 double spacingX, spacingY, spacingZ;
127 point(0) = point(0) * (1.0 / spacingX);
128 point(1) = point(1) * (1.0 / spacingY);
129 point(2) = point(2) * (1.0 / spacingZ);
131 std::cout <<
"the selected seed point is: " << point(0) <<
" " << point(1)
132 <<
" " << point(2) <<
"\n";
139 ImagePtr image = boost::dynamic_pointer_cast<
Image>(inputImage);
143 bool AirwaysFilter::isSeedPointInsideImage(
Vector3D seedPoint,
DataPtr image)
146 std::cout <<
"size of image is: " << size[0] <<
" " << size[1] <<
" " 148 int x = (int) seedPoint(0);
149 int y = (int) seedPoint(1);
150 int z = (int) seedPoint(2);
151 bool result = x >= 0 && y >= 0 && z >= 0 && x < size[0] && y < size[1]
165 if (inputImage->getType() !=
"image")
171 std::string filename = (
patientService()->getActivePatientFolder()
172 +
"/" + inputImage->getFilename()).toStdString();
175 bool useManualSeedPoint = getManualSeedPointOption(
mOptions)->getValue();
176 if(useManualSeedPoint)
178 seedPoint = getSeedPointFromTool(
mServices->spaceProvider(), inputImage);
179 if(!isSeedPointInsideImage(seedPoint, inputImage)) {
180 CX_LOG_ERROR() <<
"Seed point is not inside image. Use cursor to set seed point inside trachea in the CT image.";
196 QString q_filename =
"";
197 QString activePatienFolder =
patientService()->getActivePatientFolder();
198 QString inputImageFileName = mInputImage->getFilename();
199 if(!activePatienFolder.isEmpty())
200 q_filename = activePatienFolder+
"/"+inputImageFileName;
202 q_filename = inputImageFileName;
204 std::string filename = q_filename.toStdString();
206 fast::Config::getTestDataPath();
208 fast::Config::setKernelBinaryPath(cacheDir.toStdString());
210 fast::Config::setKernelSourcePath(kernelDir.toStdString());
213 fast::ImageFileImporter::pointer importer = fast::ImageFileImporter::New();
214 importer->setFilename(filename);
218 fast::Image::pointer image = importer->getOutputData<fast::Image>();
221 fast::Segmentation::pointer segmentationData;
222 bool doLungSegmentation = getLungSegmentationOption(
mOptions)->getValue();
223 bool useManualSeedPoint = getManualSeedPointOption(
mOptions)->getValue();
225 if(doLungSegmentation) {
226 fast::LungSegmentation::pointer segmentation = fast::LungSegmentation::New();
227 if(useManualSeedPoint) {
228 CX_LOG_INFO() <<
"Using seed point: " << seedPoint.transpose();
229 segmentation->setAirwaySeedPoint(seedPoint(0), seedPoint(1), seedPoint(2));
231 segmentation->setInputConnection(importer->getOutputPort());
232 segmentation->update();
233 segmentationData = segmentation->getOutputData<fast::Segmentation>(1);
236 vtkSmartPointer<fast::VTKImageExporter> vtkExporter = fast::VTKImageExporter::New();
237 vtkExporter->setInputConnection(segmentation->getOutputPort(1));
238 vtkExporter->Update();
239 mAirwaySegmentationOutput = vtkExporter->GetOutput();
242 vtkSmartPointer<fast::VTKImageExporter> vtkExporter2 = fast::VTKImageExporter::New();
243 vtkExporter2->setInputConnection(segmentation->getOutputPort(0));
244 vtkExporter2->Update();
245 mLungSegmentationOutput = vtkExporter2->GetOutput();
248 fast::AirwaySegmentation::pointer segmentation = fast::AirwaySegmentation::New();
249 if(useManualSeedPoint) {
250 CX_LOG_INFO() <<
"Using seed point: " << seedPoint.transpose();
251 segmentation->setSeedPoint(seedPoint(0), seedPoint(1), seedPoint(2));
253 segmentation->setInputConnection(importer->getOutputPort());
254 segmentation->update();
255 segmentationData = segmentation->getOutputData<fast::Segmentation>(0);
258 vtkSmartPointer<fast::VTKImageExporter> vtkExporter = fast::VTKImageExporter::New();
259 vtkExporter->setInputConnection(segmentation->getOutputPort());
260 vtkExporter->Update();
261 mAirwaySegmentationOutput = vtkExporter->GetOutput();
263 }
catch(fast::Exception & e)
267 if(!useManualSeedPoint)
268 CX_LOG_ERROR() <<
"Try to set the seed point manually.";
276 Eigen::Affine3f T = fast::SceneGraph::getEigenAffineTransformationFromData(segmentationData);
277 mTransformation.matrix() = T.matrix().cast<
double>();
280 fast::CenterlineExtraction::pointer centerline = fast::CenterlineExtraction::New();
281 centerline->setInputData(segmentationData);
284 vtkSmartPointer<fast::VTKMeshExporter> vtkCenterlineExporter = fast::VTKMeshExporter::New();
285 vtkCenterlineExporter->setInputConnection(centerline->getOutputPort());
286 mCenterlineOutput = vtkCenterlineExporter->GetOutput();
287 vtkCenterlineExporter->Update();
289 }
catch(fast::Exception& e) {
290 std::string error = e.what();
294 }
catch(cl::Error& e) {
298 }
catch (std::exception& e){
303 reportError(
"Airway segmentation algorithm threw a unknown exception.");
312 if(!mAirwaySegmentationOutput)
315 std::cout <<
"POST PROCESS" << std::endl;
318 double threshold = 1;
320 mAirwaySegmentationOutput,
337 contour->get_rMd_History()->setRegistration(mTransformation);
342 if(getLungSegmentationOption(
mOptions)->getValue()) {
344 mLungSegmentationOutput,
363 contour->get_rMd_History()->setRegistration(mTransformation);
374 centerline->get_rMd_History()->setParentSpace(mInputImage->getUid());
375 centerline->get_rMd_History()->setRegistration(mTransformation);
380 if(getStraightCLTubesOption(
mOptions)->getValue())
382 this->createStraightCL();
405 void AirwaysFilter::createTubes()
415 vtkSmartPointer<vtkImplicitModeller> blobbyLogoImp =
416 vtkSmartPointer<vtkImplicitModeller>::New();
417 blobbyLogoImp->SetInputData(clPolyData);
418 blobbyLogoImp->SetMaximumDistance(0.1);
419 blobbyLogoImp->SetSampleDimensions(256, 256, 256);
420 blobbyLogoImp->SetAdjustDistance(0.1);
423 vtkSmartPointer<vtkContourFilter> blobbyLogoIso =
424 vtkSmartPointer<vtkContourFilter>::New();
425 blobbyLogoIso->SetInputConnection(blobbyLogoImp->GetOutputPort());
426 blobbyLogoIso->SetValue(1, 1.5);
427 blobbyLogoIso->Update();
434 centerline->get_rMd_History()->setParentSpace(mInputImage->getUid());
435 centerline->get_rMd_History()->setRegistration(mTransformation);
437 centerline->setColor(QColor(118, 178, 226, 200));
445 mDefaultStraightCLTubesOption = defaultStraightCLTubesOption;
448 void AirwaysFilter::createStraightCL()
457 bl->findBranchesInCenterline(CLpoints);
458 vtkPolyDataPtr retval = bl->createVtkPolyDataFromBranches(
false,
true);
460 centerline->setVtkPolyData(retval);
461 centerline->get_rMd_History()->setParentSpace(mInputImage->getUid());
462 centerline->get_rMd_History()->setRegistration(mTransformation);
479 temp->setValueName(
"Input");
480 temp->setHelp(
"Select input to run airway segmentation on.");
487 std::vector<std::pair<QString, QString>> valueHelpPairs;
488 valueHelpPairs.push_back(std::make_pair(tr(
"Airway Centerline"), tr(
"Generated centerline mesh (vtk-format).")));
489 valueHelpPairs.push_back(std::make_pair(tr(
"Airway Segmentation"), tr(
"Generated surface of the airway segmentation volume.")));
490 valueHelpPairs.push_back(std::make_pair(tr(
"Lung Segmentation"), tr(
"Generated surface of the lung segmentation volume.")));
491 valueHelpPairs.push_back(std::make_pair(tr(
"Straight Airway Centerline"), tr(
"A centerline with straight lines between the branch points.")));
492 valueHelpPairs.push_back(std::make_pair(tr(
"Straight Airway Tubes"), tr(
"Tubes based on the straight centerline")));
494 foreach(
auto pair, valueHelpPairs)
497 tempMeshStringAdapter->setValueName(pair.first);
498 tempMeshStringAdapter->setHelp(pair.second);
504 BoolPropertyPtr AirwaysFilter::getManualSeedPointOption(QDomElement root)
509 "If the automatic seed point detection algorithm fails you can use cursor to set the seed point " 510 "inside trachea of the patient. " 511 "Then tick this checkbox to use the manual seed point in the airways filter.",
517 BoolPropertyPtr AirwaysFilter::getLungSegmentationOption(QDomElement root)
522 "Selecting this option will also segment the two lung sacs",
528 BoolPropertyPtr AirwaysFilter::getStraightCLTubesOption(QDomElement root)
533 "Use this option to generate a centerline with straight branches between " 534 "the branch points. " 535 "You also get tubes based on this straight line.",
536 mDefaultStraightCLTubesOption, root);
boost::shared_ptr< class SpaceProvider > SpaceProviderPtr
QString qstring_cast(const T &val)
static BoolPropertyPtr initialize(const QString &uid, QString name, QString help, bool value, QDomNode root=QDomNode())
std::vector< SelectDataStringPropertyBasePtr > mInputTypes
void reportError(QString msg)
boost::shared_ptr< class VisServices > VisServicesPtr
boost::shared_ptr< class BranchList > BranchListPtr
boost::shared_ptr< class Image > ImagePtr
virtual vtkPolyDataPtr getVtkPolyData() const
virtual vtkImageDataPtr getBaseVtkImageData()
virtual void createOutputTypes()
virtual void createOptions()
virtual bool postProcess()
AirwaysFilter(VisServicesPtr services)
std::vector< PropertyPtr > mOptionsAdapters
boost::shared_ptr< class Data > DataPtr
static QString findConfigFolder(QString pathRelativeToConfigRoot, QString alternativeAbsolutePath="")
boost::shared_ptr< class SelectDataStringPropertyBase > SelectDataStringPropertyBasePtr
PatientModelServicePtr patientService()
static QString getCachePath()
return path to a folder that is used during execution, will be cleared at start and stop...
void setVtkPolyData(const vtkPolyDataPtr &polyData)
int * getImageSize(DataPtr inputImage)
virtual void createInputTypes()
virtual QString getType() const
vtkSmartPointer< vtkPolyData > vtkPolyDataPtr
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
std::vector< SelectDataStringPropertyBasePtr > mOutputTypes
static QString getNameSuffix()
static QString getNameSuffixStraight()
void setDefaultStraightCLTubesOption(bool defaultStraightCLTubesOption)
static StringPropertySelectMeshPtr New(PatientModelServicePtr patientModelService)
virtual bool postProcess()
static StringPropertySelectImagePtr New(PatientModelServicePtr patientModelService)
boost::shared_ptr< class BoolProperty > BoolPropertyPtr
boost::shared_ptr< class Mesh > MeshPtr
Eigen::MatrixXd makeTransformedMatrix(vtkPolyDataPtr linesPolyData, Transform3D rMd)
makeTransformedMatrix This method takes an vtkpolydata as input, runs it through a transform and retu...
static QString getNameSuffixTubes()
boost::shared_ptr< class StringPropertySelectMesh > StringPropertySelectMeshPtr
virtual QString getName() const
virtual QString getHelp() const
Namespace for all CustusX production code.