16 #include <vtkImageImport.h> 17 #include <vtkImageData.h> 18 #include <vtkImageShiftScale.h> 19 #include <ctkPluginContext.h> 20 #include <vtkImplicitModeller.h> 21 #include <vtkContourFilter.h> 38 #include "FAST/Algorithms/LungSegmentation/LungSegmentation.hpp" 39 #include "FAST/Algorithms/AirwaySegmentation/AirwaySegmentation.hpp" 40 #include "FAST/Algorithms/CenterlineExtraction/CenterlineExtraction.hpp" 41 #include "FAST/Importers/ImageFileImporter.hpp" 42 #include "FAST/Exporters/VTKImageExporter.hpp" 43 #include "FAST/Exporters/VTKMeshExporter.hpp" 44 #include "FAST/Data/Segmentation.hpp" 45 #include "FAST/SceneGraph.hpp" 51 mDefaultStraightCLTubesOption(false)
53 fast::Reporter::setGlobalReportMethod(fast::Reporter::COUT);
55 fast::ImageFileImporter::pointer importer = fast::ImageFileImporter::New();
65 return "Airway Segmentation Filter";
70 return "airways_filter";
76 "<h3>Airway Segmentation.</h3>" 77 "<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>" 99 Vector3D point = spaceProvider->getActiveToolTipPoint(
100 spaceProvider->getD(data));
104 double spacingX, spacingY, spacingZ;
106 point(0) = point(0) * (1.0 / spacingX);
107 point(1) = point(1) * (1.0 / spacingY);
108 point(2) = point(2) * (1.0 / spacingZ);
110 std::cout <<
"the selected seed point is: " << point(0) <<
" " << point(1)
111 <<
" " << point(2) <<
"\n";
118 ImagePtr image = boost::dynamic_pointer_cast<
Image>(inputImage);
122 bool AirwaysFilter::isSeedPointInsideImage(
Vector3D seedPoint,
DataPtr image)
125 std::cout <<
"size of image is: " << size[0] <<
" " << size[1] <<
" " 127 int x = (int) seedPoint(0);
128 int y = (int) seedPoint(1);
129 int z = (int) seedPoint(2);
130 bool result = x >= 0 && y >= 0 && z >= 0 && x < size[0] && y < size[1]
144 if (inputImage->getType() !=
"image")
150 std::string filename = (
patientService()->getActivePatientFolder()
151 +
"/" + inputImage->getFilename()).toStdString();
154 bool useManualSeedPoint = getManualSeedPointOption(
mOptions)->getValue();
155 if(useManualSeedPoint)
157 seedPoint = getSeedPointFromTool(
mServices->spaceProvider(), inputImage);
158 if(!isSeedPointInsideImage(seedPoint, inputImage)) {
159 CX_LOG_ERROR() <<
"Seed point is not inside image. Use cursor to set seed point inside trachea in the CT image.";
175 QString q_filename =
"";
176 QString activePatienFolder =
patientService()->getActivePatientFolder();
177 QString inputImageFileName = mInputImage->getFilename();
178 if(!activePatienFolder.isEmpty())
179 q_filename = activePatienFolder+
"/"+inputImageFileName;
181 q_filename = inputImageFileName;
183 std::string filename = q_filename.toStdString();
185 fast::Config::getTestDataPath();
187 fast::Config::setKernelBinaryPath(cacheDir.toStdString());
189 fast::Config::setKernelSourcePath(kernelDir.toStdString());
192 fast::ImageFileImporter::pointer importer = fast::ImageFileImporter::New();
193 importer->setFilename(filename);
197 fast::Image::pointer image = importer->getOutputData<fast::Image>();
200 fast::Segmentation::pointer segmentationData;
201 bool doLungSegmentation = getLungSegmentationOption(
mOptions)->getValue();
202 bool useManualSeedPoint = getManualSeedPointOption(
mOptions)->getValue();
204 if(doLungSegmentation) {
205 fast::LungSegmentation::pointer segmentation = fast::LungSegmentation::New();
206 if(useManualSeedPoint) {
207 CX_LOG_INFO() <<
"Using seed point: " << seedPoint.transpose();
208 segmentation->setAirwaySeedPoint(seedPoint(0), seedPoint(1), seedPoint(2));
210 segmentation->setInputConnection(importer->getOutputPort());
211 segmentation->update();
212 segmentationData = segmentation->getOutputData<fast::Segmentation>(1);
215 vtkSmartPointer<fast::VTKImageExporter> vtkExporter = fast::VTKImageExporter::New();
216 vtkExporter->setInputConnection(segmentation->getOutputPort(1));
217 vtkExporter->Update();
218 mAirwaySegmentationOutput = vtkExporter->GetOutput();
221 vtkSmartPointer<fast::VTKImageExporter> vtkExporter2 = fast::VTKImageExporter::New();
222 vtkExporter2->setInputConnection(segmentation->getOutputPort(0));
223 vtkExporter2->Update();
224 mLungSegmentationOutput = vtkExporter2->GetOutput();
227 fast::AirwaySegmentation::pointer segmentation = fast::AirwaySegmentation::New();
228 if(useManualSeedPoint) {
229 CX_LOG_INFO() <<
"Using seed point: " << seedPoint.transpose();
230 segmentation->setSeedPoint(seedPoint(0), seedPoint(1), seedPoint(2));
232 segmentation->setInputConnection(importer->getOutputPort());
233 segmentation->update();
234 segmentationData = segmentation->getOutputData<fast::Segmentation>(0);
237 vtkSmartPointer<fast::VTKImageExporter> vtkExporter = fast::VTKImageExporter::New();
238 vtkExporter->setInputConnection(segmentation->getOutputPort());
239 vtkExporter->Update();
240 mAirwaySegmentationOutput = vtkExporter->GetOutput();
242 }
catch(fast::Exception & e)
246 if(!useManualSeedPoint)
247 CX_LOG_ERROR() <<
"Try to set the seed point manually.";
255 Eigen::Affine3f T = fast::SceneGraph::getEigenAffineTransformationFromData(segmentationData);
256 mTransformation.matrix() = T.matrix().cast<
double>();
259 fast::CenterlineExtraction::pointer centerline = fast::CenterlineExtraction::New();
260 centerline->setInputData(segmentationData);
263 vtkSmartPointer<fast::VTKMeshExporter> vtkCenterlineExporter = fast::VTKMeshExporter::New();
264 vtkCenterlineExporter->setInputConnection(centerline->getOutputPort());
265 mCenterlineOutput = vtkCenterlineExporter->GetOutput();
266 vtkCenterlineExporter->Update();
268 }
catch(fast::Exception& e) {
269 std::string error = e.what();
273 }
catch(cl::Error& e) {
277 }
catch (std::exception& e){
282 reportError(
"Airway segmentation algorithm threw a unknown exception.");
291 if(!mAirwaySegmentationOutput)
294 std::cout <<
"POST PROCESS" << std::endl;
297 double threshold = 1;
299 mAirwaySegmentationOutput,
316 contour->get_rMd_History()->setRegistration(mTransformation);
321 if(getLungSegmentationOption(
mOptions)->getValue()) {
323 mLungSegmentationOutput,
342 contour->get_rMd_History()->setRegistration(mTransformation);
353 centerline->get_rMd_History()->setParentSpace(mInputImage->getUid());
354 centerline->get_rMd_History()->setRegistration(mTransformation);
359 if(getStraightCLTubesOption(
mOptions)->getValue())
361 this->createStraightCL();
384 void AirwaysFilter::createTubes()
394 vtkSmartPointer<vtkImplicitModeller> blobbyLogoImp =
395 vtkSmartPointer<vtkImplicitModeller>::New();
396 blobbyLogoImp->SetInputData(clPolyData);
397 blobbyLogoImp->SetMaximumDistance(0.1);
398 blobbyLogoImp->SetSampleDimensions(256, 256, 256);
399 blobbyLogoImp->SetAdjustDistance(0.1);
402 vtkSmartPointer<vtkContourFilter> blobbyLogoIso =
403 vtkSmartPointer<vtkContourFilter>::New();
404 blobbyLogoIso->SetInputConnection(blobbyLogoImp->GetOutputPort());
405 blobbyLogoIso->SetValue(1, 1.5);
406 blobbyLogoIso->Update();
413 centerline->get_rMd_History()->setParentSpace(mInputImage->getUid());
414 centerline->get_rMd_History()->setRegistration(mTransformation);
416 centerline->setColor(QColor(118, 178, 226, 200));
424 mDefaultStraightCLTubesOption = defaultStraightCLTubesOption;
427 void AirwaysFilter::createStraightCL()
436 bl->findBranchesInCenterline(CLpoints);
437 vtkPolyDataPtr retval = bl->createVtkPolyDataFromBranches(
false,
true);
439 centerline->setVtkPolyData(retval);
440 centerline->get_rMd_History()->setParentSpace(mInputImage->getUid());
441 centerline->get_rMd_History()->setRegistration(mTransformation);
458 temp->setValueName(
"Input");
459 temp->setHelp(
"Select input to run airway segmentation on.");
466 std::vector<std::pair<QString, QString>> valueHelpPairs;
467 valueHelpPairs.push_back(std::make_pair(tr(
"Airway Centerline"), tr(
"Generated centerline mesh (vtk-format).")));
468 valueHelpPairs.push_back(std::make_pair(tr(
"Airway Segmentation"), tr(
"Generated surface of the airway segmentation volume.")));
469 valueHelpPairs.push_back(std::make_pair(tr(
"Lung Segmentation"), tr(
"Generated surface of the lung segmentation volume.")));
470 valueHelpPairs.push_back(std::make_pair(tr(
"Straight Airway Centerline"), tr(
"A centerline with straight lines between the branch points.")));
471 valueHelpPairs.push_back(std::make_pair(tr(
"Straight Airway Tubes"), tr(
"Tubes based on the straight centerline")));
473 foreach(
auto pair, valueHelpPairs)
476 tempMeshStringAdapter->setValueName(pair.first);
477 tempMeshStringAdapter->setHelp(pair.second);
483 BoolPropertyPtr AirwaysFilter::getManualSeedPointOption(QDomElement root)
488 "If the automatic seed point detection algorithm fails you can use cursor to set the seed point " 489 "inside trachea of the patient. " 490 "Then tick this checkbox to use the manual seed point in the airways filter.",
496 BoolPropertyPtr AirwaysFilter::getLungSegmentationOption(QDomElement root)
501 "Selecting this option will also segment the two lung sacs",
507 BoolPropertyPtr AirwaysFilter::getStraightCLTubesOption(QDomElement root)
512 "Use this option to generate a centerline with straight branches between " 513 "the branch points. " 514 "You also get tubes based on this straight line.",
515 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.