CustusX  16.5
An IGT application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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) 2008-2014, SINTEF Department of Medical Technology
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9 
10 1. Redistributions of source code must retain the above copyright notice,
11  this list of conditions and the following disclaimer.
12 
13 2. Redistributions in binary form must reproduce the above copyright notice,
14  this list of conditions and the following disclaimer in the documentation
15  and/or other materials provided with the distribution.
16 
17 3. Neither the name of the copyright holder nor the names of its contributors
18  may be used to endorse or promote products derived from this software
19  without specific prior written permission.
20 
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 =========================================================================*/
32 
34 
35 #include "cxAlgorithmHelpers.h"
36 #include <itkBinaryThresholdImageFilter.h>
37 #include <vtkImageCast.h>
38 #include "cxUtilHelpers.h"
40 #include "cxStringProperty.h"
41 #include "cxColorProperty.h"
42 #include "cxBoolProperty.h"
43 #include "cxTypeConversions.h"
44 #include "cxDoublePairProperty.h"
45 #include "cxContourFilter.h"
46 #include "cxMesh.h"
47 #include "cxImage.h"
49 #include "cxPatientModelService.h"
50 #include "cxViewService.h"
51 #include "cxVolumeHelpers.h"
52 #include "cxVisServices.h"
53 
54 namespace cx
55 {
56 
58  FilterImpl(services)
59 {
60 }
61 
63 {
64  return "Segmentation";
65 }
66 
68 {
69  return "BinaryThresholdImageFilter";
70 }
71 
73 {
74  return "<html>"
75  "<h3>Binary Threshold Image Filter.</h3>"
76  "<p><i>Segment out areas from the selected image using a threshold.</i></p>"
77  "<p>This filter produces an output image whose pixels are either one of two values"
78  "( OutsideValue or InsideValue ), depending on whether the corresponding input"
79  "image pixels lie between the two thresholds ( LowerThreshold and UpperThreshold )."
80  "Values equal to either threshold is considered to be between the thresholds.<p>"
81  "</html>";
82 }
83 
85 {
86  DoublePairPropertyPtr retval = DoublePairProperty::initialize("Thresholds", "",
87  "Select the lower and upper thresholds for the segmentation", DoubleRange(0, 100, 1), 0,
88  root);
89  return retval;
90 }
91 
93 {
94  BoolPropertyPtr retval = BoolProperty::initialize("Generate Surface", "",
95  "Generate a surface of the output volume", true,
96  root);
97  return retval;
98 }
99 
101 {
102  return ColorProperty::initialize("Color", "",
103  "The color of the output model.",
104  QColor("green"), root);
105 }
106 
108 {
109  mThresholdOption = this->getThresholdOption(mOptions);
110  connect(mThresholdOption.get(), &Property::changed, this, &BinaryThresholdImageFilter::thresholdSlot);
111  mOptionsAdapters.push_back(mThresholdOption);
113  mOptionsAdapters.push_back(this->getColorOption(mOptions));
114 }
115 
117 {
119 
120  temp = StringPropertySelectImage::New(mServices->patient());
121  temp->setValueName("Input");
122  temp->setHelp("Select image input for thresholding");
123  connect(temp.get(), SIGNAL(dataChanged(QString)), this, SLOT(imageChangedSlot(QString)));
124  mInputTypes.push_back(temp);
125 }
126 
128 {
130 
131  temp = StringPropertySelectData::New(mServices->patient());
132  temp->setValueName("Output");
133  temp->setHelp("Output thresholded binary image");
134  mOutputTypes.push_back(temp);
135 
136  temp = StringPropertySelectData::New(mServices->patient());
137  temp->setValueName("Contour");
138  temp->setHelp("Output contour generated from thresholded binary image.");
139  mOutputTypes.push_back(temp);
140 }
141 
143 {
145 
146  if (!mActive)
147  this->stopPreview();
148 }
149 
150 void BinaryThresholdImageFilter::imageChangedSlot(QString uid)
151 {
152  this->stopPreview();
153  this->updateThresholdPairFromImageChange(uid, mThresholdOption);
154 }
155 
156 void BinaryThresholdImageFilter::stopPreview()
157 {
158  if(mPreviewImage)
159  mPreviewImage->stopThresholdPreview();
160  mPreviewImage.reset();
161 }
162 
164 {
165  if (mActive)
166  {
167  mPreviewImage = boost::dynamic_pointer_cast<Image>(mInputTypes[0]->getData());
168  if(!mPreviewImage)
169  return;
170  Eigen::Vector2d threshold = Eigen::Vector2d(mThresholdOption->getValue()[0], mThresholdOption->getValue()[1]);
171  mPreviewImage->startThresholdPreview(threshold);
172  }
173 }
174 
176 {
177  this->stopPreview();
178  return FilterImpl::preProcess();
179 
180 }
181 
183 {
184  ImagePtr input = this->getCopiedInputImage();
185  if (!input)
186  return false;
187 
190 
191  itkImageType::ConstPointer itkImage = AlgorithmHelper::getITKfromSSCImage(input);
192 
193  //Binary Thresholding
194  typedef itk::BinaryThresholdImageFilter<itkImageType, itkImageType> thresholdFilterType;
195  thresholdFilterType::Pointer thresholdFilter = thresholdFilterType::New();
196  thresholdFilter->SetInput(itkImage);
197  thresholdFilter->SetOutsideValue(0);
198  thresholdFilter->SetInsideValue(1);
199  thresholdFilter->SetLowerThreshold(thresholds->getValue()[0]);
200  thresholdFilter->SetUpperThreshold(thresholds->getValue()[1]);
201  thresholdFilter->Update();
202  itkImage = thresholdFilter->GetOutput();
203 
204  //Convert ITK to VTK
205  itkToVtkFilterType::Pointer itkToVtkFilter = itkToVtkFilterType::New();
206  itkToVtkFilter->SetInput(itkImage);
207  itkToVtkFilter->Update();
208 
209  vtkImageDataPtr rawResult = vtkImageDataPtr::New();
210  rawResult->DeepCopy(itkToVtkFilter->GetOutput());
211 
212  vtkImageCastPtr imageCast = vtkImageCastPtr::New();
213  imageCast->SetInputData(rawResult);
214  imageCast->SetOutputScalarTypeToUnsignedChar();
215  imageCast->Update();
216  rawResult = imageCast->GetOutput();
217 
218  // TODO: possible memory problem here - check debug mem system of itk/vtk
219 
220  mRawResult = rawResult;
221 
222  if (generateSurface->getValue())
223  {
224  double threshold = 1;
225  mRawContour = ContourFilter::execute(mRawResult, threshold);
226  }
227 
228  return true;
229 }
230 
232 {
233  if (!mRawResult)
234  return false;
235 
236  ImagePtr input = this->getCopiedInputImage();
237 
238  if (!input)
239  return false;
240 
241  QString uid = input->getUid() + "_seg%1";
242  QString name = input->getName()+" seg%1";
243  ImagePtr output = createDerivedImage(mServices->patient(),
244  uid, name,
245  mRawResult, input);
246 
247  mRawResult = NULL;
248 
249  output->setInitialWindowLevel(-1, -1);
250  output->resetTransferFunctions();
251  mServices->patient()->insertData(output);
252 
253  // set output
254  mOutputTypes.front()->setValue(output->getUid());
255 
256  // set contour output
257  if (mRawContour!=NULL)
258  {
259  ColorPropertyPtr colorOption = this->getColorOption(mOptions);
260  MeshPtr contour = ContourFilter::postProcess(mServices->patient(), mRawContour, output, colorOption->getValue());
261  mOutputTypes[1]->setValue(contour->getUid());
262  mRawContour = vtkPolyDataPtr();
263  }
264 
265  return true;
266 }
267 
268 
269 }//namespace cx
static BoolPropertyPtr initialize(const QString &uid, QString name, QString help, bool value, QDomNode root=QDomNode())
std::vector< SelectDataStringPropertyBasePtr > mInputTypes
Definition: cxFilterImpl.h:94
QDomElement mCopiedOptions
Definition: cxFilterImpl.h:101
boost::shared_ptr< class ColorProperty > ColorPropertyPtr
boost::shared_ptr< class VisServices > VisServicesPtr
Definition: cxMainWindow.h:62
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:53
boost::shared_ptr< class Image > ImagePtr
Definition: cxDicomWidget.h:48
BoolPropertyPtr getGenerateSurfaceOption(QDomElement root)
std::vector< PropertyPtr > mOptionsAdapters
Definition: cxFilterImpl.h:96
vtkSmartPointer< class vtkPolyData > vtkPolyDataPtr
VisServicesPtr mServices
Definition: cxFilterImpl.h:103
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:66
DoublePairPropertyPtr getThresholdOption(QDomElement root)
ImagePtr getCopiedInputImage(int index=0)
virtual void setActive(bool on)
QDomElement mOptions
Definition: cxFilterImpl.h:97
vtkSmartPointer< class vtkImageCast > vtkImageCastPtr
void changed()
emit when the underlying data value is changed: The user interface will be updated.
ColorPropertyPtr getColorOption(QDomElement root)
std::vector< SelectDataStringPropertyBasePtr > mOutputTypes
Definition: cxFilterImpl.h:95
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