16 #include "vtkCellArray.h" 17 #include "vtkCellData.h" 18 #include "vtkDoubleArray.h" 19 #include "vtkPolyData.h" 20 #include "vtkSmartPointer.h" 22 #include "itkImageRegionIteratorWithIndex.h" 23 #include "itkNeighborhoodIterator.h" 27 void mitk::CreateDistanceImageFromSurfaceFilter::CreateEmptyDistanceImage()
30 DistanceImageType::PointType minPointInWorldCoordinates, maxPointInWorldCoordinates;
31 DistanceImageType::IndexType minPointInIndexCoordinates, maxPointInIndexCoordinates;
34 minPointInWorldCoordinates, maxPointInWorldCoordinates, minPointInIndexCoordinates, maxPointInIndexCoordinates);
41 for (
unsigned int dim = 0; dim < 3; ++dim)
43 extentMM[dim] = (std::abs(maxPointInIndexCoordinates[dim] - minPointInIndexCoordinates[dim])) *
44 m_ReferenceImage->GetSpacing()[dim];
54 double basis = (extentMM[0] * extentMM[1] * extentMM[2]) / m_DistanceImageVolume;
55 double exponent = 1.0 / 3.0;
56 m_DistanceImageSpacing = pow(basis, exponent);
59 unsigned int numberOfXPixel = extentMM[0] / m_DistanceImageSpacing;
60 unsigned int numberOfYPixel = extentMM[1] / m_DistanceImageSpacing;
61 unsigned int numberOfZPixel = extentMM[2] / m_DistanceImageSpacing;
66 DistanceImageType::SizeType sizeOfRegion;
67 sizeOfRegion[0] = numberOfXPixel + 8;
68 sizeOfRegion[1] = numberOfYPixel + 8;
69 sizeOfRegion[2] = numberOfZPixel + 8;
72 DistanceImageType::IndexType initialOriginAsIndex;
73 initialOriginAsIndex.Fill(0);
75 DistanceImageType::PointType originAsWorld = minPointInWorldCoordinates;
77 DistanceImageType::RegionType lpRegion;
78 lpRegion.SetSize(sizeOfRegion);
79 lpRegion.SetIndex(initialOriginAsIndex);
85 m_DistanceImageITK = DistanceImageType::New();
86 m_DistanceImageITK->SetOrigin(originAsWorld);
87 m_DistanceImageITK->SetDirection(m_ReferenceImage->GetDirection());
88 m_DistanceImageITK->SetRegions(lpRegion);
89 m_DistanceImageITK->SetSpacing(m_DistanceImageSpacing);
90 m_DistanceImageITK->Allocate();
93 m_DistanceImageDefaultBufferValue = 10 * m_DistanceImageSpacing;
94 m_DistanceImageITK->FillBuffer(m_DistanceImageDefaultBufferValue);
98 DistanceImageType::IndexType originAsIndex;
99 m_DistanceImageITK->TransformPhysicalPointToIndex(originAsWorld, originAsIndex);
100 originAsIndex[0] -= 2;
101 originAsIndex[1] -= 2;
102 originAsIndex[2] -= 2;
103 m_DistanceImageITK->TransformIndexToPhysicalPoint(originAsIndex, originAsWorld);
104 m_DistanceImageITK->SetOrigin(originAsWorld);
108 : m_DistanceImageSpacing(0.0), m_DistanceImageDefaultBufferValue(0.0)
110 m_DistanceImageVolume = 50000;
111 this->m_UseProgressBar =
false;
112 this->m_ProgressStepSize = 5;
115 this->SetNthOutput(0, output.GetPointer());
124 this->PreprocessContourPoints();
125 this->CreateEmptyDistanceImage();
128 this->CreateSolutionMatrixAndFunctionValues();
130 if (this->m_UseProgressBar)
133 m_Weights = m_SolutionMatrix.partialPivLu().solve(m_FunctionValues);
135 if (this->m_UseProgressBar)
139 this->FillDistanceImage();
141 if (this->m_UseProgressBar)
148 void mitk::CreateDistanceImageFromSurfaceFilter::PreprocessContourPoints()
150 unsigned int numberOfInputs = this->GetNumberOfIndexedInputs();
152 if (numberOfInputs == 0)
154 MITK_ERROR <<
"mitk::CreateDistanceImageFromSurfaceFilter: No input available. Please set an input!" << std::endl;
155 itkExceptionMacro(
"mitk::CreateDistanceImageFromSurfaceFilter: No input available. Please set an input!");
162 vtkSmartPointer<vtkPolyData> polyData;
163 vtkSmartPointer<vtkDoubleArray> currentCellNormals;
164 vtkSmartPointer<vtkCellArray> existingPolys;
165 vtkSmartPointer<vtkPoints> existingPoints;
171 for (
unsigned int i = 0; i < numberOfInputs; i++)
173 auto currentSurface = this->
GetInput(i);
174 polyData = currentSurface->GetVtkPolyData();
176 if (polyData->GetNumberOfPolys() == 0)
178 MITK_INFO <<
"mitk::CreateDistanceImageFromSurfaceFilter: No input-polygons available. Please be sure the input " 179 "surface consists of polygons!" 183 currentCellNormals = vtkDoubleArray::SafeDownCast(polyData->GetCellData()->GetNormals());
185 existingPolys = polyData->GetPolys();
187 existingPoints = polyData->GetPoints();
189 existingPolys->InitTraversal();
191 vtkIdType *cell(
nullptr);
192 vtkIdType cellSize(0);
194 for (existingPolys->InitTraversal(); existingPolys->GetNextCell(cellSize, cell);)
196 for (vtkIdType j = 0; j < cellSize; j++)
198 existingPoints->GetPoint(cell[j], p);
200 currentPoint.copy_in(p);
202 int count = std::count(m_Centers.begin(), m_Centers.end(), currentPoint);
206 double currentNormal[3];
207 currentCellNormals->GetTuple(cell[j], currentNormal);
209 normal.copy_in(currentNormal);
211 m_Normals.push_back(normal);
213 m_Centers.push_back(currentPoint);
221 void mitk::CreateDistanceImageFromSurfaceFilter::CreateSolutionMatrixAndFunctionValues()
224 unsigned int numberOfCenters = m_Centers.size();
225 m_Centers.reserve(numberOfCenters * 3);
227 m_FunctionValues.resize(numberOfCenters * 3);
229 m_FunctionValues.fill(0);
235 for (
unsigned int i = 0; i < numberOfCenters; i++)
237 currentPoint = m_Centers.at(i);
238 normal = m_Normals.at(i);
240 currentPoint[0] = currentPoint[0] - normal[0] * m_DistanceImageSpacing;
241 currentPoint[1] = currentPoint[1] - normal[1] * m_DistanceImageSpacing;
242 currentPoint[2] = currentPoint[2] - normal[2] * m_DistanceImageSpacing;
244 m_Centers.push_back(currentPoint);
246 m_FunctionValues[numberOfCenters + i] = -m_DistanceImageSpacing;
250 for (
unsigned int i = 0; i < numberOfCenters; i++)
252 currentPoint = m_Centers.at(i);
253 normal = m_Normals.at(i);
255 currentPoint[0] = currentPoint[0] + normal[0] * m_DistanceImageSpacing;
256 currentPoint[1] = currentPoint[1] + normal[1] * m_DistanceImageSpacing;
257 currentPoint[2] = currentPoint[2] + normal[2] * m_DistanceImageSpacing;
259 m_Centers.push_back(currentPoint);
261 m_FunctionValues[numberOfCenters * 2 + i] = m_DistanceImageSpacing;
265 numberOfCenters = m_Centers.size();
267 m_SolutionMatrix.resize(numberOfCenters, numberOfCenters);
269 m_Weights.resize(numberOfCenters);
275 for (
unsigned int i = 0; i < numberOfCenters; i++)
277 for (
unsigned int j = 0; j < numberOfCenters; j++)
280 p1 = m_Centers.at(i);
281 p2 = m_Centers.at(j);
283 norm = p1.two_norm();
284 m_SolutionMatrix(i, j) = norm;
289 void mitk::CreateDistanceImageFromSurfaceFilter::FillDistanceImage()
302 typedef itk::ImageRegionIteratorWithIndex<DistanceImageType> ImageIterator;
303 typedef itk::NeighborhoodIterator<DistanceImageType> NeighborhoodImageIterator;
305 std::queue<DistanceImageType::IndexType> narrowbandPoints;
306 PointType currentPoint = m_Centers.at(0);
307 double distance = this->CalculateDistanceValue(currentPoint);
310 DistanceImageType::PointType currentPointAsPoint;
311 currentPointAsPoint[0] = currentPoint[0];
312 currentPointAsPoint[1] = currentPoint[1];
313 currentPointAsPoint[2] = currentPoint[2];
316 DistanceImageType::IndexType currentIndex;
317 m_DistanceImageITK->TransformPhysicalPointToIndex(currentPointAsPoint, currentIndex);
320 m_DistanceImageITK->GetLargestPossibleRegion().IsInside(currentIndex));
322 narrowbandPoints.push(currentIndex);
323 m_DistanceImageITK->SetPixel(currentIndex, distance);
325 NeighborhoodImageIterator::RadiusType radius;
327 NeighborhoodImageIterator nIt(radius, m_DistanceImageITK, m_DistanceImageITK->GetLargestPossibleRegion());
328 unsigned int relativeNbIdx[] = {4, 10, 12, 14, 16, 22};
330 bool isInBounds =
false;
331 while (!narrowbandPoints.empty())
333 nIt.SetLocation(narrowbandPoints.front());
334 narrowbandPoints.pop();
336 unsigned int *relativeNb = &relativeNbIdx[0];
337 for (
int i = 0; i < 6; i++)
339 nIt.GetPixel(*relativeNb, isInBounds);
340 if (isInBounds && nIt.GetPixel(*relativeNb) == m_DistanceImageDefaultBufferValue)
342 currentIndex = nIt.GetIndex(*relativeNb);
346 m_DistanceImageITK->TransformIndexToPhysicalPoint(currentIndex, currentPointAsPoint);
349 currentPoint[0] = currentPointAsPoint[0];
350 currentPoint[1] = currentPointAsPoint[1];
351 currentPoint[2] = currentPointAsPoint[2];
354 distance = this->CalculateDistanceValue(currentPoint);
355 if (std::fabs(distance) <= m_DistanceImageSpacing * 2)
357 nIt.SetPixel(*relativeNb, distance);
358 narrowbandPoints.push(currentIndex);
365 ImageIterator imgRegionIterator(m_DistanceImageITK, m_DistanceImageITK->GetLargestPossibleRegion());
366 imgRegionIterator.GoToBegin();
368 double prevPixelVal = 1;
370 DistanceImageType::IndexType _size;
372 _size += m_DistanceImageITK->GetLargestPossibleRegion().GetSize();
376 while (!imgRegionIterator.IsAtEnd())
378 if (imgRegionIterator.Get() == m_DistanceImageDefaultBufferValue && prevPixelVal < 0)
380 while (imgRegionIterator.Get() == m_DistanceImageDefaultBufferValue)
382 if (imgRegionIterator.GetIndex()[0] == _size[0] || imgRegionIterator.GetIndex()[1] == _size[1] ||
383 imgRegionIterator.GetIndex()[2] == _size[2] || imgRegionIterator.GetIndex()[0] == 0U ||
384 imgRegionIterator.GetIndex()[1] == 0U || imgRegionIterator.GetIndex()[2] == 0U)
386 imgRegionIterator.Set(m_DistanceImageDefaultBufferValue);
387 prevPixelVal = m_DistanceImageDefaultBufferValue;
393 imgRegionIterator.Set((-1) * m_DistanceImageDefaultBufferValue);
395 prevPixelVal = (-1) * m_DistanceImageDefaultBufferValue;
399 else if (imgRegionIterator.GetIndex()[0] == _size[0] || imgRegionIterator.GetIndex()[1] == _size[1] ||
400 imgRegionIterator.GetIndex()[2] == _size[2] || imgRegionIterator.GetIndex()[0] == 0U ||
401 imgRegionIterator.GetIndex()[1] == 0U || imgRegionIterator.GetIndex()[2] == 0U)
404 imgRegionIterator.Set(m_DistanceImageDefaultBufferValue);
405 prevPixelVal = m_DistanceImageDefaultBufferValue;
410 prevPixelVal = imgRegionIterator.Get();
422 double mitk::CreateDistanceImageFromSurfaceFilter::CalculateDistanceValue(
PointType p)
424 double distanceValue(0);
429 CenterList::iterator centerIter;
431 unsigned int count(0);
432 for (centerIter = m_Centers.begin(); centerIter != m_Centers.end(); centerIter++)
436 norm = p2.two_norm();
437 distanceValue = distanceValue + (norm * m_Weights[count]);
440 return distanceValue;
449 std::stringstream out;
450 out <<
"Nummber of rows: " << m_SolutionMatrix.rows() <<
" ****** Number of columns: " << m_SolutionMatrix.cols()
453 for (
int i = 0; i < m_SolutionMatrix.rows(); i++)
455 for (
int j = 0; j < m_SolutionMatrix.cols(); j++)
457 out << m_SolutionMatrix(i, j) <<
" ";
463 for (
unsigned int i = 0; i < m_Centers.size(); i++)
465 out << m_Centers.at(i) <<
";" << endl;
467 std::cout <<
"Equation system: \n\n\n" << out.str();
479 this->SetNthInput(idx, const_cast<mitk::Surface *>(surface));
486 if (this->GetNumberOfIndexedInputs() < 1)
489 return static_cast<const mitk::Surface *
>(this->ProcessObject::GetInput(0));
494 if (this->GetNumberOfIndexedInputs() < 1)
497 return static_cast<const mitk::Surface *
>(this->ProcessObject::GetInput(idx));
502 DataObjectPointerArraySizeType nb = this->GetNumberOfIndexedInputs();
504 for (DataObjectPointerArraySizeType i = 0; i < nb; i++)
508 this->RemoveInput(i);
516 for (
unsigned int i = 0; i < this->GetNumberOfIndexedInputs(); i++)
518 this->PopBackInput();
520 this->SetNumberOfIndexedInputs(0);
521 this->SetNumberOfIndexedOutputs(1);
524 this->SetNthOutput(0, output.GetPointer());
529 this->m_UseProgressBar = status;
534 this->m_ProgressStepSize = stepSize;
539 m_ReferenceImage = referenceImage;
542 void mitk::CreateDistanceImageFromSurfaceFilter::DetermineBounds(
543 DistanceImageType::PointType &minPointInWorldCoordinates,
544 DistanceImageType::PointType &maxPointInWorldCoordinates,
545 DistanceImageType::IndexType &minPointInIndexCoordinates,
546 DistanceImageType::IndexType &maxPointInIndexCoordinates)
549 DistanceImageType::PointType tmpPoint;
550 tmpPoint[0] = firstCenter[0];
551 tmpPoint[1] = firstCenter[1];
552 tmpPoint[2] = firstCenter[2];
555 itk::ContinuousIndex<double, 3> tmpIndex;
556 m_ReferenceImage->TransformPhysicalPointToContinuousIndex(tmpPoint, tmpIndex);
559 DistanceImageType::IndexValueType xmin = tmpIndex[0];
560 DistanceImageType::IndexValueType ymin = tmpIndex[1];
561 DistanceImageType::IndexValueType zmin = tmpIndex[2];
562 DistanceImageType::IndexValueType xmax = tmpIndex[0];
563 DistanceImageType::IndexValueType ymax = tmpIndex[1];
564 DistanceImageType::IndexValueType zmax = tmpIndex[2];
567 auto centerIter = m_Centers.begin();
568 for (++centerIter; centerIter != m_Centers.end(); centerIter++)
570 tmpPoint[0] = (*centerIter)[0];
571 tmpPoint[1] = (*centerIter)[1];
572 tmpPoint[2] = (*centerIter)[2];
575 m_ReferenceImage->TransformPhysicalPointToContinuousIndex(tmpPoint, tmpIndex);
579 if (xmin > tmpIndex[0])
583 if (ymin > tmpIndex[1])
587 if (zmin > tmpIndex[2])
591 if (xmax < tmpIndex[0])
595 if (ymax < tmpIndex[1])
599 if (zmax < tmpIndex[2])
606 minPointInIndexCoordinates[0] = xmin;
607 minPointInIndexCoordinates[1] = ymin;
608 minPointInIndexCoordinates[2] = zmin;
610 maxPointInIndexCoordinates[0] = xmax;
611 maxPointInIndexCoordinates[1] = ymax;
612 maxPointInIndexCoordinates[2] = zmax;
615 m_ReferenceImage->TransformIndexToPhysicalPoint(minPointInIndexCoordinates, minPointInWorldCoordinates);
616 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).
~CreateDistanceImageFromSurfaceFilter() override
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()
void GenerateData() override
vnl_vector_fixed< double, 3 > PointType
void CastToMitkImage(const itk::SmartPointer< ItkOutputImageType > &itkimage, itk::SmartPointer< mitk::Image > &mitkoutputimage)
Cast an itk::Image (with a specific type) to an mitk::Image.
void GenerateOutputInformation() override
virtual void SetInput(const mitk::Surface *surface)
void SetUseProgressBar(bool)
Set whether the mitkProgressBar should be used.
OutputType * GetOutput()
Get the output data of this image source object.
CreateDistanceImageFromSurfaceFilter()