NorMIT-nav  18.04
An IGT application
cxBinaryThresholdImageFilter.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 This file is part of CustusX, an Image Guided Therapy Application.
3 
4 Copyright (c) SINTEF Department of Medical Technology.
5 All rights reserved.
6 
7 CustusX is released under a BSD 3-Clause license.
8 
9 See Lisence.txt (https://github.com/SINTEFMedtek/CustusX/blob/master/License.txt) for details.
10 =========================================================================*/
11 
13 
14 #include "cxAlgorithmHelpers.h"
15 #include <itkBinaryThresholdImageFilter.h>
16 #include <vtkImageCast.h>
17 #include "cxUtilHelpers.h"
19 #include "cxStringProperty.h"
20 #include "cxColorProperty.h"
21 #include "cxBoolProperty.h"
22 #include "cxTypeConversions.h"
23 #include "cxDoublePairProperty.h"
24 #include "cxContourFilter.h"
25 #include "cxMesh.h"
26 #include "cxImage.h"
28 #include "cxPatientModelService.h"
29 #include "cxViewService.h"
30 #include "cxVolumeHelpers.h"
31 #include "cxVisServices.h"
32 
33 namespace cx
34 {
35 
37  FilterImpl(services)
38 {
39 }
40 
42 {
43  return "Segmentation";
44 }
45 
47 {
48  return "binary_threshold_image_filter";
49 }
50 
52 {
53  return "<html>"
54  "<h3>Binary Threshold Image Filter.</h3>"
55  "<p><i>Segment out areas from the selected image using a threshold.</i></p>"
56  "<p>This filter produces an output image whose pixels are either one of two values"
57  "( OutsideValue or InsideValue ), depending on whether the corresponding input"
58  "image pixels lie between the two thresholds ( LowerThreshold and UpperThreshold )."
59  "Values equal to either threshold is considered to be between the thresholds.<p>"
60  "</html>";
61 }
62 
64 {
65  DoublePairPropertyPtr retval = DoublePairProperty::initialize("Thresholds", "",
66  "Select the lower and upper thresholds for the segmentation", DoubleRange(0, 100, 1), 0,
67  root);
68  return retval;
69 }
70 
72 {
73  BoolPropertyPtr retval = BoolProperty::initialize("Generate Surface", "",
74  "Generate a surface of the output volume", true,
75  root);
76  return retval;
77 }
78 
80 {
81  return ColorProperty::initialize("Color", "",
82  "The color of the output model.",
83  QColor("green"), root);
84 }
85 
87 {
88  mThresholdOption = this->getThresholdOption(mOptions);
89  connect(mThresholdOption.get(), &Property::changed, this, &BinaryThresholdImageFilter::thresholdSlot);
90  mOptionsAdapters.push_back(mThresholdOption);
92  mOptionsAdapters.push_back(this->getColorOption(mOptions));
93 }
94 
96 {
98 
99  temp = StringPropertySelectImage::New(mServices->patient());
100  temp->setValueName("Input");
101  temp->setHelp("Select image input for thresholding");
102  connect(temp.get(), SIGNAL(dataChanged(QString)), this, SLOT(imageChangedSlot(QString)));
103  mInputTypes.push_back(temp);
104 }
105 
107 {
109 
110  temp = StringPropertySelectData::New(mServices->patient());
111  temp->setValueName("Output");
112  temp->setHelp("Output thresholded binary image");
113  mOutputTypes.push_back(temp);
114 
115  temp = StringPropertySelectData::New(mServices->patient());
116  temp->setValueName("Contour");
117  temp->setHelp("Output contour generated from thresholded binary image.");
118  mOutputTypes.push_back(temp);
119 }
120 
122 {
124 
125  if (!mActive)
126  this->stopPreview();
127 }
128 
129 void BinaryThresholdImageFilter::imageChangedSlot(QString uid)
130 {
131  this->stopPreview();
132  this->updateThresholdPairFromImageChange(uid, mThresholdOption);
133 }
134 
135 void BinaryThresholdImageFilter::stopPreview()
136 {
137  if(mPreviewImage)
138  mPreviewImage->stopThresholdPreview();
139  mPreviewImage.reset();
140 }
141 
143 {
144  if (mActive)
145  {
146  mPreviewImage = boost::dynamic_pointer_cast<Image>(mInputTypes[0]->getData());
147  if(!mPreviewImage)
148  return;
149  Eigen::Vector2d threshold = Eigen::Vector2d(mThresholdOption->getValue()[0], mThresholdOption->getValue()[1]);
150  mPreviewImage->startThresholdPreview(threshold);
151  }
152 }
153 
155 {
156  this->stopPreview();
157  return FilterImpl::preProcess();
158 
159 }
160 
162 {
163  ImagePtr input = this->getCopiedInputImage();
164  if (!input)
165  return false;
166 
169 
170  itkImageType::ConstPointer itkImage = AlgorithmHelper::getITKfromSSCImage(input);
171 
172  //Binary Thresholding
173  typedef itk::BinaryThresholdImageFilter<itkImageType, itkImageType> thresholdFilterType;
174  thresholdFilterType::Pointer thresholdFilter = thresholdFilterType::New();
175  thresholdFilter->SetInput(itkImage);
176  thresholdFilter->SetOutsideValue(0);
177  thresholdFilter->SetInsideValue(1);
178  thresholdFilter->SetLowerThreshold(thresholds->getValue()[0]);
179  thresholdFilter->SetUpperThreshold(thresholds->getValue()[1]);
180  thresholdFilter->Update();
181  itkImage = thresholdFilter->GetOutput();
182 
183  //Convert ITK to VTK
184  itkToVtkFilterType::Pointer itkToVtkFilter = itkToVtkFilterType::New();
185  itkToVtkFilter->SetInput(itkImage);
186  itkToVtkFilter->Update();
187 
188  vtkImageDataPtr rawResult = vtkImageDataPtr::New();
189  rawResult->DeepCopy(itkToVtkFilter->GetOutput());
190 
191  vtkImageCastPtr imageCast = vtkImageCastPtr::New();
192  imageCast->SetInputData(rawResult);
193  imageCast->SetOutputScalarTypeToUnsignedChar();
194  imageCast->Update();
195  rawResult = imageCast->GetOutput();
196 
197  // TODO: possible memory problem here - check debug mem system of itk/vtk
198 
199  mRawResult = rawResult;
200 
201  if (generateSurface->getValue())
202  {
203  double threshold = 1;
204  mRawContour = ContourFilter::execute(mRawResult, threshold);
205  }
206 
207  return true;
208 }
209 
211 {
212  if (!mRawResult)
213  return false;
214 
215  ImagePtr input = this->getCopiedInputImage();
216 
217  if (!input)
218  return false;
219 
220  QString uid = input->getUid() + "_seg%1";
221  QString name = input->getName()+" seg%1";
222  ImagePtr output = createDerivedImage(mServices->patient(),
223  uid, name,
224  mRawResult, input);
225 
226  mRawResult = NULL;
227 
228  output->setInitialWindowLevel(-1, -1);
229  output->resetTransferFunctions();
230  mServices->patient()->insertData(output);
231 
232  // set output
233  mOutputTypes.front()->setValue(output->getUid());
234 
235  // set contour output
236  if (mRawContour!=NULL)
237  {
238  ColorPropertyPtr colorOption = this->getColorOption(mOptions);
239  MeshPtr contour = ContourFilter::postProcess(mServices->patient(), mRawContour, output, colorOption->getValue());
240  mOutputTypes[1]->setValue(contour->getUid());
241  mRawContour = vtkPolyDataPtr();
242  }
243 
244  return true;
245 }
246 
247 
248 }//namespace cx
static BoolPropertyPtr initialize(const QString &uid, QString name, QString help, bool value, QDomNode root=QDomNode())
std::vector< SelectDataStringPropertyBasePtr > mInputTypes
Definition: cxFilterImpl.h:73
QDomElement mCopiedOptions
Definition: cxFilterImpl.h:80
boost::shared_ptr< class ColorProperty > ColorPropertyPtr
boost::shared_ptr< class VisServices > VisServicesPtr
Definition: cxMainWindow.h:40
virtual bool preProcess()
void updateThresholdPairFromImageChange(QString uid, DoublePairPropertyPtr threshold)
static StringPropertySelectDataPtr New(PatientModelServicePtr patientModelService, QString typeRegexp=".*")
Utility class for describing a bounded numeric range.
Definition: cxDoubleRange.h:32
boost::shared_ptr< class Image > ImagePtr
Definition: cxDicomWidget.h:27
BoolPropertyPtr getGenerateSurfaceOption(QDomElement root)
std::vector< PropertyPtr > mOptionsAdapters
Definition: cxFilterImpl.h:75
VisServicesPtr mServices
Definition: cxFilterImpl.h:82
ImagePtr createDerivedImage(PatientModelServicePtr dataManager, QString uid, QString name, vtkImageDataPtr raw, ImagePtr parent)
boost::shared_ptr< class SelectDataStringPropertyBase > SelectDataStringPropertyBasePtr
virtual bool execute()
A volumetric data set.
Definition: cxImage.h:45
DoublePairPropertyPtr getThresholdOption(QDomElement root)
ImagePtr getCopiedInputImage(int index=0)
virtual void setActive(bool on)
QDomElement mOptions
Definition: cxFilterImpl.h:76
vtkSmartPointer< class vtkImageCast > vtkImageCastPtr
void changed()
emit when the underlying data value is changed: The user interface will be updated.
ColorPropertyPtr getColorOption(QDomElement root)
vtkSmartPointer< vtkPolyData > vtkPolyDataPtr
std::vector< SelectDataStringPropertyBasePtr > mOutputTypes
Definition: cxFilterImpl.h:74
boost::shared_ptr< class DoublePairProperty > DoublePairPropertyPtr
static DoublePairPropertyPtr initialize(const QString &uid, QString name, QString help, DoubleRange range, int decimals, QDomNode root=QDomNode())
virtual bool postProcess()
static itkImageType::ConstPointer getITKfromSSCImage(ImagePtr image)
static StringPropertySelectImagePtr New(PatientModelServicePtr patientModelService)
BinaryThresholdImageFilter(VisServicesPtr services)
static ColorPropertyPtr initialize(const QString &uid, QString name, QString help, QColor value, QDomNode root=QDomNode())
boost::shared_ptr< class BoolProperty > BoolPropertyPtr
boost::shared_ptr< class Mesh > MeshPtr
vtkSmartPointer< class vtkImageData > vtkImageDataPtr
Namespace for all CustusX production code.