28 #include <itkCommand.h>
30 #include <itkImageSliceConstIteratorWithIndex.h>
55 m_2DInterpolationActivated = status;
62 if (m_Instance.IsNull())
72 for (
auto iter = s_InterpolatorForImage.begin(); iter != s_InterpolatorForImage.end(); ++iter)
74 if (iter->second ==
this)
76 s_InterpolatorForImage.erase(iter);
84 if (!m_BlockModified && m_Segmentation.IsNotNull() && m_2DInterpolationActivated)
86 SetSegmentationVolume(m_Segmentation);
92 m_BlockModified = block;
98 m_SegmentationCountInSlice.clear();
101 auto iter = s_InterpolatorForImage.find(segmentation);
102 if (iter != s_InterpolatorForImage.end())
104 s_InterpolatorForImage.erase(iter);
111 itkExceptionMacro(
"SegmentationInterpolationController needs a 3D-segmentation or 3D+t, not 2D.");
114 if (m_Segmentation != segmentation)
120 segmentation->AddObserver(itk::ModifiedEvent(), command);
123 m_Segmentation = segmentation;
125 m_SegmentationCountInSlice.resize(m_Segmentation->GetTimeSteps());
126 for (
unsigned int timeStep = 0; timeStep < m_Segmentation->GetTimeSteps(); ++timeStep)
128 m_SegmentationCountInSlice[timeStep].resize(3);
129 for (
unsigned int dim = 0; dim < 3; ++dim)
131 m_SegmentationCountInSlice[timeStep][dim].clear();
132 m_SegmentationCountInSlice[timeStep][dim].resize(m_Segmentation->GetDimension(dim));
133 m_SegmentationCountInSlice[timeStep][dim].assign(m_Segmentation->GetDimension(dim), 0);
137 s_InterpolatorForImage.insert(std::make_pair(m_Segmentation,
this));
141 for (
unsigned int timeStep = 0; timeStep < m_Segmentation->GetTimeSteps(); ++timeStep)
144 timeSelector->SetInput(m_Segmentation);
145 timeSelector->SetTimeNr(timeStep);
146 timeSelector->UpdateLargestPossibleRegion();
153 SetReferenceVolume(m_ReferenceImage);
160 m_ReferenceImage = referenceImage;
162 if (m_ReferenceImage.IsNull())
164 assert(m_Segmentation.IsNotNull());
167 if (m_ReferenceImage.IsNull() || m_Segmentation.IsNull() ||
168 m_ReferenceImage->GetDimension() != m_Segmentation->GetDimension() ||
169 m_ReferenceImage->GetPixelType().GetNumberOfComponents() != 1 ||
170 m_Segmentation->GetPixelType().GetNumberOfComponents() != 1)
172 MITK_WARN <<
"Segmentation image has different image characteristics than reference image." << std::endl;
173 m_ReferenceImage =
nullptr;
177 for (
unsigned int dim = 0; dim < m_Segmentation->GetDimension(); ++dim)
178 if (m_ReferenceImage->GetDimension(dim) != m_Segmentation->GetDimension(dim))
180 MITK_WARN <<
"original patient image does not match segmentation (different extent in dimension " << dim
181 <<
"), ignoring patient image" << std::endl;
182 m_ReferenceImage =
nullptr;
201 unsigned int sliceDimension,
202 unsigned int sliceIndex,
203 unsigned int timeStep)
207 if (sliceDimension > 2)
209 if (timeStep >= m_SegmentationCountInSlice.size())
211 if (sliceIndex >= m_SegmentationCountInSlice[timeStep][sliceDimension].size())
214 unsigned int dim0(0);
215 unsigned int dim1(1);
218 switch (sliceDimension)
239 unsigned char *rawSlice = (
unsigned char *)readAccess.
GetData();
244 sliceDiff, ScanChangedSlice, 2,
SetChangedSliceOptions(sliceDimension, sliceIndex, dim0, dim1, timeStep, rawSlice));
251 template <
typename DATATYPE>
255 DATATYPE *pixelData((DATATYPE *)options.
pixelData);
257 unsigned int timeStep(options.
timeStep);
262 if (sliceDimension > 2)
264 if (sliceIndex >= m_SegmentationCountInSlice[timeStep][sliceDimension].size())
267 unsigned int dim0(options.
dim0);
268 unsigned int dim1(options.
dim1);
270 int numberOfPixels(0);
272 unsigned int dim0max = m_SegmentationCountInSlice[timeStep][dim0].size();
273 unsigned int dim1max = m_SegmentationCountInSlice[timeStep][dim1].size();
277 for (
unsigned int v = 0; v < dim1max; ++v)
279 for (
unsigned int u = 0; u < dim0max; ++u)
281 DATATYPE value = *(pixelData + u + v * dim0max);
283 assert((
signed)m_SegmentationCountInSlice[timeStep][dim0][u] + (
signed)value >=
285 assert((
signed)m_SegmentationCountInSlice[timeStep][dim1][v] + (
signed)value >= 0);
287 m_SegmentationCountInSlice[timeStep][dim0][u] =
288 static_cast<unsigned int>(m_SegmentationCountInSlice[timeStep][dim0][u] + value);
289 m_SegmentationCountInSlice[timeStep][dim1][v] =
290 static_cast<unsigned int>(m_SegmentationCountInSlice[timeStep][dim1][v] + value);
291 numberOfPixels +=
static_cast<int>(value);
296 assert((
signed)m_SegmentationCountInSlice[timeStep][sliceDimension][sliceIndex] + numberOfPixels >= 0);
297 m_SegmentationCountInSlice[timeStep][sliceDimension][sliceIndex] += numberOfPixels;
304 template <
typename TPixel,
unsigned int VImageDimension>
306 unsigned int timeStep)
308 typedef itk::ImageSliceConstIteratorWithIndex<itk::Image<TPixel, VImageDimension>> IteratorType;
310 IteratorType iter(diffImage, diffImage->GetLargestPossibleRegion());
311 iter.SetFirstDirection(0);
312 iter.SetSecondDirection(1);
314 int numberOfPixels(0);
316 typename IteratorType::IndexType index;
322 while (!iter.IsAtEnd())
324 while (!iter.IsAtEndOfSlice())
326 while (!iter.IsAtEndOfLine())
328 index = iter.GetIndex();
334 TPixel value = iter.Get();
336 assert((
signed)m_SegmentationCountInSlice[timeStep][0][x] + (
signed)value >=
338 assert((
signed)m_SegmentationCountInSlice[timeStep][1][y] + (
signed)value >= 0);
340 m_SegmentationCountInSlice[timeStep][0][x] =
341 static_cast<unsigned int>(m_SegmentationCountInSlice[timeStep][0][x] + value);
342 m_SegmentationCountInSlice[timeStep][1][y] =
343 static_cast<unsigned int>(m_SegmentationCountInSlice[timeStep][1][y] + value);
345 numberOfPixels +=
static_cast<int>(value);
351 assert((
signed)m_SegmentationCountInSlice[timeStep][2][z] + numberOfPixels >= 0);
352 m_SegmentationCountInSlice[timeStep][2][z] += numberOfPixels;
359 template <
typename DATATYPE>
362 unsigned int timeStep)
366 if (timeStep >= m_SegmentationCountInSlice.size())
371 for (
unsigned int slice = 0; slice < volume->
GetDimension(2); ++slice)
373 const DATATYPE *rawVolume =
374 static_cast<const DATATYPE *
>(readAccess.GetData());
383 unsigned int timeStep(0);
385 MITK_INFO <<
"Interpolator status (timestep 0): dimensions " << m_SegmentationCountInSlice[timeStep][0].size() <<
" "
386 << m_SegmentationCountInSlice[timeStep][1].size() <<
" " << m_SegmentationCountInSlice[timeStep][2].size()
389 MITK_INFO <<
"Slice 0: " << m_SegmentationCountInSlice[timeStep][2][0] << std::endl;
392 for (
unsigned int index = 0; index < m_SegmentationCountInSlice[timeStep][0].size(); ++index)
394 if (m_SegmentationCountInSlice[timeStep][0][index] > 0)
402 for (
unsigned int index = 1; index < m_SegmentationCountInSlice[timeStep][1].size(); ++index)
404 if (m_SegmentationCountInSlice[timeStep][1][index] > 0)
409 if (m_SegmentationCountInSlice[timeStep][2].size() > index)
411 for (
unsigned int indent = 1; indent < index; ++indent)
414 if (m_SegmentationCountInSlice[timeStep][2][index] > 0)
415 MITK_INFO << m_SegmentationCountInSlice[timeStep][2][index];
424 for (
unsigned int index = m_SegmentationCountInSlice[timeStep][1].size();
425 index < m_SegmentationCountInSlice[timeStep][2].size();
428 for (
unsigned int indent = 0; indent < index; ++indent)
431 if (m_SegmentationCountInSlice[timeStep][2][index] > 0)
432 MITK_INFO << m_SegmentationCountInSlice[timeStep][2][index];
441 unsigned int sliceIndex,
443 unsigned int timeStep)
445 if (m_Segmentation.IsNull())
453 if (timeStep >= m_SegmentationCountInSlice.size())
455 if (sliceDimension > 2)
457 unsigned int upperLimit = m_SegmentationCountInSlice[timeStep][sliceDimension].size();
458 if (sliceIndex >= upperLimit - 1)
463 if (m_SegmentationCountInSlice[timeStep][sliceDimension][sliceIndex] > 0)
466 unsigned int lowerBound(0);
467 unsigned int upperBound(0);
470 for (lowerBound = sliceIndex - 1; ; --lowerBound)
472 if (m_SegmentationCountInSlice[timeStep][sliceDimension][lowerBound] > 0)
486 for (upperBound = sliceIndex + 1; upperBound < upperLimit; ++upperBound)
488 if (m_SegmentationCountInSlice[timeStep][sliceDimension][upperBound] > 0)
511 extractor->SetInput(m_Segmentation);
512 extractor->SetTimeStep(timeStep);
513 extractor->SetResliceTransformByGeometry(m_Segmentation->GetTimeGeometry()->GetGeometryForTimeStep(timeStep));
514 extractor->SetVtkOutputRequest(
false);
517 extractor->SetWorldGeometry(currentPlane);
518 extractor->Modified();
520 resultImage = extractor->GetOutput();
521 resultImage->DisconnectPipeline();
528 m_Segmentation->GetSlicedGeometry(timeStep)->WorldToIndex(origin, origin);
529 origin[sliceDimension] = lowerBound;
530 m_Segmentation->GetSlicedGeometry(timeStep)->IndexToWorld(origin, origin);
531 reslicePlane->SetOrigin(origin);
535 extractor->SetInput(m_Segmentation);
536 extractor->SetTimeStep(timeStep);
537 extractor->SetResliceTransformByGeometry(m_Segmentation->GetTimeGeometry()->GetGeometryForTimeStep(timeStep));
538 extractor->SetVtkOutputRequest(
false);
540 extractor->SetWorldGeometry(reslicePlane);
541 extractor->Modified();
543 lowerMITKSlice = extractor->GetOutput();
544 lowerMITKSlice->DisconnectPipeline();
547 m_Segmentation->GetSlicedGeometry(timeStep)->WorldToIndex(origin, origin);
548 origin[sliceDimension] = upperBound;
549 m_Segmentation->GetSlicedGeometry(timeStep)->IndexToWorld(origin, origin);
550 reslicePlane->SetOrigin(origin);
554 extractor->SetInput(m_Segmentation);
555 extractor->SetTimeStep(timeStep);
556 extractor->SetResliceTransformByGeometry(m_Segmentation->GetTimeGeometry()->GetGeometryForTimeStep(timeStep));
557 extractor->SetVtkOutputRequest(
false);
559 extractor->SetWorldGeometry(reslicePlane);
560 extractor->Modified();
562 upperMITKSlice = extractor->GetOutput();
563 upperMITKSlice->DisconnectPipeline();
565 if (lowerMITKSlice.IsNull() || upperMITKSlice.IsNull())
568 catch (
const std::exception &e)
570 MITK_ERROR <<
"Error in 2D interpolation: " << e.what();
585 return algorithm->Interpolate(lowerMITKSlice.GetPointer(),
587 upperMITKSlice.GetPointer(),
const Point3D GetOrigin() const
Get the origin, e.g. the upper-left corner of the plane.
virtual ~SegmentationInterpolationController()
itk::SmartPointer< Self > Pointer
void SetChangedSlice(const Image *sliceDiff, unsigned int sliceDimension, unsigned int sliceIndex, unsigned int timeStep)
Update after changing a single slice.
const void * GetData() const
Gives const access to the data.
Generates interpolations of 2D slices.
virtual ImageDataItemPointer GetVolumeData(int t=0, int n=0, void *data=nullptr, ImportMemoryManagementType importMemoryManagement=CopyMemory) const
void BlockModified(bool)
Block reaction to an images Modified() events.
static SegmentationInterpolationController * GetInstance()
Get existing instance or create a new one.
static InterpolatorMapType s_InterpolatorForImage
void ScanChangedVolume(const itk::Image< TPixel, VImageDimension > *, unsigned int timeStep)
Protected class of mitk::SegmentationInterpolationController. Don't use (you shouldn't be able to do ...
void SetChangedVolume(const Image *sliceDiff, unsigned int timeStep)
#define AccessFixedDimensionByItk_2(mitkImage, itkImageTypeFunction, dimension, arg1, arg2)
Image class for storing images.
void SetSegmentationVolume(const Image *segmentation)
Initialize with a whole volume.
void OnImageModified(const itk::EventObject &)
static SegmentationInterpolationController * InterpolatorForImage(const Image *)
Find interpolator for a given image.
void Activate2DInterpolation(bool)
Image::Pointer Interpolate(unsigned int sliceDimension, unsigned int sliceIndex, const mitk::PlaneGeometry *currentPlane, unsigned int timeStep)
Generates an interpolated image for the given slice.
void ScanWholeVolume(const itk::Image< DATATYPE, 3 > *, const Image *volume, unsigned int timeStep)
SegmentationInterpolationController()
std::map< const Image *, SegmentationInterpolationController * > InterpolatorMapType
#define AccessFixedDimensionByItk_1(mitkImage, itkImageTypeFunction, dimension, arg1)
void SetReferenceVolume(const Image *segmentation)
Set a reference image (original patient image) - optional.
void ScanChangedSlice(const itk::Image< DATATYPE, 2 > *, const SetChangedSliceOptions &options)
internal scan of a single slice
Describes a two-dimensional, rectangular plane.
unsigned int GetDimension() const
Get dimension of the image.
ImageReadAccessor class to get locked read access for a particular image part.
unsigned int sliceDimension
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.