20 #include "vtkCellArray.h"
21 #include "vtkCellData.h"
22 #include "vtkDoubleArray.h"
23 #include "vtkPolyData.h"
24 #include "vtkSmartPointer.h"
26 #include "itkImageRegionIteratorWithIndex.h"
27 #include "itkNeighborhoodIterator.h"
31 void mitk::CreateDistanceImageFromSurfaceFilter::CreateEmptyDistanceImage()
35 DistanceImageType::IndexType minPointInIndexCoordinates, maxPointInIndexCoordinates;
38 minPointInWorldCoordinates, maxPointInWorldCoordinates, minPointInIndexCoordinates, maxPointInIndexCoordinates);
45 for (
unsigned int dim = 0; dim < 3; ++dim)
47 extentMM[dim] = (std::abs(maxPointInIndexCoordinates[dim] - minPointInIndexCoordinates[dim])) *
48 m_ReferenceImage->GetSpacing()[dim];
58 double basis = (extentMM[0] * extentMM[1] * extentMM[2]) / m_DistanceImageVolume;
59 double exponent = 1.0 / 3.0;
60 m_DistanceImageSpacing = pow(basis, exponent);
63 unsigned int numberOfXPixel = extentMM[0] / m_DistanceImageSpacing;
64 unsigned int numberOfYPixel = extentMM[1] / m_DistanceImageSpacing;
65 unsigned int numberOfZPixel = extentMM[2] / m_DistanceImageSpacing;
70 DistanceImageType::SizeType sizeOfRegion;
71 sizeOfRegion[0] = numberOfXPixel + 8;
72 sizeOfRegion[1] = numberOfYPixel + 8;
73 sizeOfRegion[2] = numberOfZPixel + 8;
76 DistanceImageType::IndexType initialOriginAsIndex;
77 initialOriginAsIndex.Fill(0);
81 DistanceImageType::RegionType lpRegion;
82 lpRegion.SetSize(sizeOfRegion);
83 lpRegion.SetIndex(initialOriginAsIndex);
90 m_DistanceImageITK->SetOrigin(originAsWorld);
91 m_DistanceImageITK->SetDirection(m_ReferenceImage->GetDirection());
92 m_DistanceImageITK->SetRegions(lpRegion);
93 m_DistanceImageITK->SetSpacing(m_DistanceImageSpacing);
94 m_DistanceImageITK->Allocate();
97 m_DistanceImageDefaultBufferValue = 10 * m_DistanceImageSpacing;
98 m_DistanceImageITK->FillBuffer(m_DistanceImageDefaultBufferValue);
102 DistanceImageType::IndexType originAsIndex;
103 m_DistanceImageITK->TransformPhysicalPointToIndex(originAsWorld, originAsIndex);
104 originAsIndex[0] -= 2;
105 originAsIndex[1] -= 2;
106 originAsIndex[2] -= 2;
107 m_DistanceImageITK->TransformIndexToPhysicalPoint(originAsIndex, originAsWorld);
108 m_DistanceImageITK->SetOrigin(originAsWorld);
113 m_DistanceImageVolume = 50000;
114 this->m_UseProgressBar =
false;
115 this->m_ProgressStepSize = 5;
118 this->SetNthOutput(0, output.GetPointer());
127 this->PreprocessContourPoints();
128 this->CreateEmptyDistanceImage();
131 this->CreateSolutionMatrixAndFunctionValues();
133 if (this->m_UseProgressBar)
136 m_Weights = m_SolutionMatrix.partialPivLu().solve(m_FunctionValues);
138 if (this->m_UseProgressBar)
142 this->FillDistanceImage();
144 if (this->m_UseProgressBar)
151 void mitk::CreateDistanceImageFromSurfaceFilter::PreprocessContourPoints()
153 unsigned int numberOfInputs = this->GetNumberOfIndexedInputs();
155 if (numberOfInputs == 0)
157 MITK_ERROR <<
"mitk::CreateDistanceImageFromSurfaceFilter: No input available. Please set an input!" << std::endl;
158 itkExceptionMacro(
"mitk::CreateDistanceImageFromSurfaceFilter: No input available. Please set an input!");
165 Surface *currentSurface;
166 vtkSmartPointer<vtkPolyData> polyData;
167 vtkSmartPointer<vtkDoubleArray> currentCellNormals;
168 vtkSmartPointer<vtkCellArray> existingPolys;
169 vtkSmartPointer<vtkPoints> existingPoints;
175 for (
unsigned int i = 0; i < numberOfInputs; i++)
177 currentSurface =
const_cast<Surface *
>(this->GetInput(i));
178 polyData = currentSurface->GetVtkPolyData();
180 if (polyData->GetNumberOfPolys() == 0)
182 MITK_INFO <<
"mitk::CreateDistanceImageFromSurfaceFilter: No input-polygons available. Please be sure the input "
183 "surface consists of polygons!"
187 currentCellNormals = vtkDoubleArray::SafeDownCast(polyData->GetCellData()->GetNormals());
189 existingPolys = polyData->GetPolys();
191 existingPoints = polyData->GetPoints();
193 existingPolys->InitTraversal();
195 vtkIdType *cell(
nullptr);
196 vtkIdType cellSize(0);
198 for (existingPolys->InitTraversal(); existingPolys->GetNextCell(cellSize, cell);)
200 for (vtkIdType j = 0; j < cellSize; j++)
202 existingPoints->GetPoint(cell[j], p);
204 currentPoint.copy_in(p);
206 int count = std::count(m_Centers.begin(), m_Centers.end(), currentPoint);
210 double currentNormal[3];
211 currentCellNormals->GetTuple(cell[j], currentNormal);
213 normal.copy_in(currentNormal);
215 m_Normals.push_back(normal);
217 m_Centers.push_back(currentPoint);
225 void mitk::CreateDistanceImageFromSurfaceFilter::CreateSolutionMatrixAndFunctionValues()
228 unsigned int numberOfCenters = m_Centers.size();
229 m_Centers.reserve(numberOfCenters * 3);
231 m_FunctionValues.resize(numberOfCenters * 3);
233 m_FunctionValues.fill(0);
239 for (
unsigned int i = 0; i < numberOfCenters; i++)
241 currentPoint = m_Centers.at(i);
242 normal = m_Normals.at(i);
244 currentPoint[0] = currentPoint[0] - normal[0] * m_DistanceImageSpacing;
245 currentPoint[1] = currentPoint[1] - normal[1] * m_DistanceImageSpacing;
246 currentPoint[2] = currentPoint[2] - normal[2] * m_DistanceImageSpacing;
248 m_Centers.push_back(currentPoint);
250 m_FunctionValues[numberOfCenters + i] = -m_DistanceImageSpacing;
254 for (
unsigned int i = 0; i < numberOfCenters; i++)
256 currentPoint = m_Centers.at(i);
257 normal = m_Normals.at(i);
259 currentPoint[0] = currentPoint[0] + normal[0] * m_DistanceImageSpacing;
260 currentPoint[1] = currentPoint[1] + normal[1] * m_DistanceImageSpacing;
261 currentPoint[2] = currentPoint[2] + normal[2] * m_DistanceImageSpacing;
263 m_Centers.push_back(currentPoint);
265 m_FunctionValues[numberOfCenters * 2 + i] = m_DistanceImageSpacing;
269 numberOfCenters = m_Centers.size();
271 m_SolutionMatrix.resize(numberOfCenters, numberOfCenters);
273 m_Weights.resize(numberOfCenters);
279 for (
unsigned int i = 0; i < numberOfCenters; i++)
281 for (
unsigned int j = 0; j < numberOfCenters; j++)
284 p1 = m_Centers.at(i);
285 p2 = m_Centers.at(j);
287 norm = p1.two_norm();
288 m_SolutionMatrix(i, j) = norm;
293 void mitk::CreateDistanceImageFromSurfaceFilter::FillDistanceImage()
306 typedef itk::ImageRegionIteratorWithIndex<DistanceImageType> ImageIterator;
307 typedef itk::NeighborhoodIterator<DistanceImageType> NeighborhoodImageIterator;
309 std::queue<DistanceImageType::IndexType> narrowbandPoints;
310 PointType currentPoint = m_Centers.at(0);
311 double distance = this->CalculateDistanceValue(currentPoint);
315 currentPointAsPoint[0] = currentPoint[0];
316 currentPointAsPoint[1] = currentPoint[1];
317 currentPointAsPoint[2] = currentPoint[2];
320 DistanceImageType::IndexType currentIndex;
321 m_DistanceImageITK->TransformPhysicalPointToIndex(currentPointAsPoint, currentIndex);
324 m_DistanceImageITK->GetLargestPossibleRegion().IsInside(currentIndex));
326 narrowbandPoints.push(currentIndex);
327 m_DistanceImageITK->SetPixel(currentIndex, distance);
329 NeighborhoodImageIterator::RadiusType radius;
331 NeighborhoodImageIterator nIt(radius, m_DistanceImageITK, m_DistanceImageITK->GetLargestPossibleRegion());
332 unsigned int relativeNbIdx[] = {4, 10, 12, 14, 16, 22};
334 bool isInBounds =
false;
335 while (!narrowbandPoints.empty())
337 nIt.SetLocation(narrowbandPoints.front());
338 narrowbandPoints.pop();
340 unsigned int *relativeNb = &relativeNbIdx[0];
341 for (
int i = 0; i < 6; i++)
343 nIt.GetPixel(*relativeNb, isInBounds);
344 if (isInBounds && nIt.GetPixel(*relativeNb) == m_DistanceImageDefaultBufferValue)
346 currentIndex = nIt.GetIndex(*relativeNb);
350 m_DistanceImageITK->TransformIndexToPhysicalPoint(currentIndex, currentPointAsPoint);
353 currentPoint[0] = currentPointAsPoint[0];
354 currentPoint[1] = currentPointAsPoint[1];
355 currentPoint[2] = currentPointAsPoint[2];
358 distance = this->CalculateDistanceValue(currentPoint);
359 if (std::fabs(distance) <= m_DistanceImageSpacing * 2)
361 nIt.SetPixel(*relativeNb, distance);
362 narrowbandPoints.push(currentIndex);
369 ImageIterator imgRegionIterator(m_DistanceImageITK, m_DistanceImageITK->GetLargestPossibleRegion());
370 imgRegionIterator.GoToBegin();
372 double prevPixelVal = 1;
374 DistanceImageType::IndexType _size;
376 _size += m_DistanceImageITK->GetLargestPossibleRegion().GetSize();
380 while (!imgRegionIterator.IsAtEnd())
382 if (imgRegionIterator.Get() == m_DistanceImageDefaultBufferValue && prevPixelVal < 0)
384 while (imgRegionIterator.Get() == m_DistanceImageDefaultBufferValue)
386 if (imgRegionIterator.GetIndex()[0] == _size[0] || imgRegionIterator.GetIndex()[1] == _size[1] ||
387 imgRegionIterator.GetIndex()[2] == _size[2] || imgRegionIterator.GetIndex()[0] == 0U ||
388 imgRegionIterator.GetIndex()[1] == 0U || imgRegionIterator.GetIndex()[2] == 0U)
390 imgRegionIterator.Set(m_DistanceImageDefaultBufferValue);
391 prevPixelVal = m_DistanceImageDefaultBufferValue;
397 imgRegionIterator.Set((-1) * m_DistanceImageDefaultBufferValue);
399 prevPixelVal = (-1) * m_DistanceImageDefaultBufferValue;
403 else if (imgRegionIterator.GetIndex()[0] == _size[0] || imgRegionIterator.GetIndex()[1] == _size[1] ||
404 imgRegionIterator.GetIndex()[2] == _size[2] || imgRegionIterator.GetIndex()[0] == 0U ||
405 imgRegionIterator.GetIndex()[1] == 0U || imgRegionIterator.GetIndex()[2] == 0U)
408 imgRegionIterator.Set(m_DistanceImageDefaultBufferValue);
409 prevPixelVal = m_DistanceImageDefaultBufferValue;
414 prevPixelVal = imgRegionIterator.Get();
426 double mitk::CreateDistanceImageFromSurfaceFilter::CalculateDistanceValue(
PointType p)
428 double distanceValue(0);
433 CenterList::iterator centerIter;
435 unsigned int count(0);
436 for (centerIter = m_Centers.begin(); centerIter != m_Centers.end(); centerIter++)
440 norm = p2.two_norm();
441 distanceValue = distanceValue + (norm * m_Weights[count]);
444 return distanceValue;
453 std::stringstream out;
454 out <<
"Nummber of rows: " << m_SolutionMatrix.rows() <<
" ****** Number of columns: " << m_SolutionMatrix.cols()
457 for (
int i = 0; i < m_SolutionMatrix.rows(); i++)
459 for (
int j = 0; j < m_SolutionMatrix.cols(); j++)
461 out << m_SolutionMatrix(i, j) <<
" ";
467 for (
unsigned int i = 0; i < m_Centers.size(); i++)
469 out << m_Centers.at(i) <<
";" << endl;
471 std::cout <<
"Equation system: \n\n\n" << out.str();
476 this->SetInput(0, const_cast<mitk::Surface *>(surface));
481 if (this->GetInput(idx) != surface)
483 this->SetNthInput(idx, const_cast<mitk::Surface *>(surface));
490 if (this->GetNumberOfIndexedInputs() < 1)
493 return static_cast<const mitk::Surface *
>(this->ProcessObject::GetInput(0));
498 if (this->GetNumberOfIndexedInputs() < 1)
501 return static_cast<const mitk::Surface *
>(this->ProcessObject::GetInput(idx));
506 DataObjectPointerArraySizeType nb = this->GetNumberOfIndexedInputs();
508 for (DataObjectPointerArraySizeType i = 0; i < nb; i++)
510 if (this->GetInput(i) == input)
512 this->RemoveInput(i);
520 for (
unsigned int i = 0; i < this->GetNumberOfIndexedInputs(); i++)
522 this->PopBackInput();
524 this->SetNumberOfIndexedInputs(0);
525 this->SetNumberOfIndexedOutputs(1);
528 this->SetNthOutput(0, output.GetPointer());
533 this->m_UseProgressBar = status;
538 this->m_ProgressStepSize = stepSize;
543 m_ReferenceImage = referenceImage;
546 void mitk::CreateDistanceImageFromSurfaceFilter::DetermineBounds(
549 DistanceImageType::IndexType &minPointInIndexCoordinates,
550 DistanceImageType::IndexType &maxPointInIndexCoordinates)
554 tmpPoint[0] = firstCenter[0];
555 tmpPoint[1] = firstCenter[1];
556 tmpPoint[2] = firstCenter[2];
559 itk::ContinuousIndex<double, 3> tmpIndex;
560 m_ReferenceImage->TransformPhysicalPointToContinuousIndex(tmpPoint, tmpIndex);
563 DistanceImageType::IndexValueType xmin = tmpIndex[0];
564 DistanceImageType::IndexValueType ymin = tmpIndex[1];
565 DistanceImageType::IndexValueType zmin = tmpIndex[2];
566 DistanceImageType::IndexValueType xmax = tmpIndex[0];
567 DistanceImageType::IndexValueType ymax = tmpIndex[1];
568 DistanceImageType::IndexValueType zmax = tmpIndex[2];
571 auto centerIter = m_Centers.begin();
572 for (++centerIter; centerIter != m_Centers.end(); centerIter++)
574 tmpPoint[0] = (*centerIter)[0];
575 tmpPoint[1] = (*centerIter)[1];
576 tmpPoint[2] = (*centerIter)[2];
579 m_ReferenceImage->TransformPhysicalPointToContinuousIndex(tmpPoint, tmpIndex);
583 if (xmin > tmpIndex[0])
587 if (ymin > tmpIndex[1])
591 if (zmin > tmpIndex[2])
595 if (xmax < tmpIndex[0])
599 if (ymax < tmpIndex[1])
603 if (zmax < tmpIndex[2])
610 minPointInIndexCoordinates[0] = xmin;
611 minPointInIndexCoordinates[1] = ymin;
612 minPointInIndexCoordinates[2] = zmin;
614 maxPointInIndexCoordinates[0] = xmax;
615 maxPointInIndexCoordinates[1] = ymax;
616 maxPointInIndexCoordinates[2] = zmax;
619 m_ReferenceImage->TransformIndexToPhysicalPoint(minPointInIndexCoordinates, minPointInWorldCoordinates);
620 m_ReferenceImage->TransformIndexToPhysicalPoint(maxPointInIndexCoordinates, maxPointInWorldCoordinates);
void Progress(unsigned int steps=1)
Sets the current amount of progress to current progress + steps.
Class for storing surfaces (vtkPolyData).
itk::SmartPointer< Self > Pointer
virtual ~CreateDistanceImageFromSurfaceFilter()
itk::SmartPointer< Self > Pointer
virtual void RemoveInputs(mitk::Surface *input)
static ProgressBar * GetInstance()
static method to get the GUI dependent ProgressBar-instance so the methods for steps to do and progre...
void SetReferenceImage(itk::ImageBase< 3 >::Pointer referenceImage)
void PrintEquationSystem()
void SetProgressStepSize(unsigned int stepSize)
Set the stepsize which the progress bar should proceed.
Vector< ScalarType, 3 > Vector3D
virtual const mitk::Surface * GetInput()
virtual void GenerateData() override
A version of GenerateData() specific for image processing filters.
void CastToMitkImage(const itk::SmartPointer< ItkOutputImageType > &itkimage, itk::SmartPointer< mitk::Image > &mitkoutputimage)
Cast an itk::Image (with a specific type) to an mitk::Image.
virtual void GenerateOutputInformation() override
virtual void SetInput(const mitk::Surface *surface)
void SetUseProgressBar(bool)
Set whether the mitkProgressBar should be used.
CreateDistanceImageFromSurfaceFilter()
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.