17 #include <itkGradientMagnitudeImageFilter.h>
33 #include "mitkLiveWireTool2D.xpm"
40 class RemoveFromDataStorage
45 void operator()(
const std::pair<mitk::DataNode::Pointer, mitk::PlaneGeometry::Pointer> &dataNode)
60 this->ClearSegmentation();
63 void mitk::LiveWireTool2D::RemoveHelperObjects()
65 DataStorage *dataStorage = m_ToolManager->GetDataStorage();
67 if (!m_EditingContours.empty())
68 std::for_each(m_EditingContours.begin(), m_EditingContours.end(), RemoveFromDataStorage(dataStorage));
70 if (!m_WorkingContours.empty())
71 std::for_each(m_WorkingContours.begin(), m_WorkingContours.end(), RemoveFromDataStorage(dataStorage));
73 if (m_EditingContourNode.IsNotNull())
74 dataStorage->
Remove(m_EditingContourNode);
76 if (m_LiveWireContourNode.IsNotNull())
77 dataStorage->
Remove(m_LiveWireContourNode);
79 if (m_ContourModelNode.IsNotNull())
80 dataStorage->
Remove(m_ContourModelNode);
85 void mitk::LiveWireTool2D::ReleaseHelperObjects()
87 this->RemoveHelperObjects();
89 if (!m_EditingContours.empty())
90 m_EditingContours.clear();
92 if (!m_WorkingContours.empty())
93 m_WorkingContours.clear();
95 m_EditingContourNode = NULL;
96 m_EditingContour = NULL;
98 m_LiveWireContourNode = NULL;
99 m_LiveWireContour = NULL;
101 m_ContourModelNode = NULL;
105 void mitk::LiveWireTool2D::ReleaseInteractors()
107 this->EnableContourLiveWireInteraction(
false);
108 m_LiveWireNodes.clear();
126 return mitkLiveWireTool2D_xpm;
146 Superclass::Activated();
147 this->ResetToStartState();
148 this->EnableContourLiveWireInteraction(
true);
153 this->ConfirmSegmentation();
154 Superclass::Deactivated();
159 for (
auto interactor : m_LiveWireNodes)
162 interactor->EnableInteraction(
true);
164 interactor->EnableInteraction(
false);
170 DataNode *workingNode(m_ToolManager->GetWorkingData(0));
175 Image *workingImage =
dynamic_cast<Image *
>(workingNode->GetData());
181 std::vector<std::pair<mitk::DataNode::Pointer, mitk::PlaneGeometry::Pointer>>::iterator itWorkingContours =
182 this->m_WorkingContours.begin();
183 std::vector<SliceInformation> sliceList;
184 sliceList.reserve(m_WorkingContours.size());
185 while (itWorkingContours != this->m_WorkingContours.end())
188 if (itWorkingContours->first->GetData())
200 this->GetAffectedImageSliceAs2DImage(itWorkingContours->second, workingImage, currentTimestep);
207 SliceInformation sliceInfo(workingSlice, itWorkingContours->second, currentTimestep);
208 sliceList.push_back(sliceInfo);
209 this->WriteSliceToVolume(sliceInfo);
216 this->WriteBackSegmentationResult(sliceList,
false);
217 this->ClearSegmentation();
222 this->ReleaseHelperObjects();
223 this->ReleaseInteractors();
224 this->ResetToStartState();
230 bool IsPositionEventInsideImageRegion =
232 if (!IsPositionEventInsideImageRegion)
234 MITK_WARN(
"LiveWireTool2D") <<
"PositionEvent is outside ImageRegion!";
247 mitk::DataNode *workingDataNode = m_ToolManager->GetWorkingData(0);
248 if (!IsPositionEventInsideImageRegion(positionEvent, workingDataNode->
GetData()))
250 this->ResetToStartState();
254 m_LastEventSender = positionEvent->
GetSender();
255 m_LastEventSlice = m_LastEventSender->
GetSlice();
260 m_Contour->Expand(timestep + 1);
262 m_ContourModelNode->SetData(m_Contour);
263 m_ContourModelNode->SetName(
"working contour node");
267 m_ContourModelNode->AddProperty(
"contour.color",
ColorProperty::New(1, 1, 0), NULL,
true);
268 m_ContourModelNode->AddProperty(
"contour.points.color",
ColorProperty::New(1.0, 0.0, 0.1), NULL,
true);
269 m_ContourModelNode->AddProperty(
"contour.controlpoints.show",
BoolProperty::New(
true), NULL,
true);
272 m_LiveWireContour->Expand(timestep + 1);
274 m_LiveWireContourNode->SetData(m_LiveWireContour);
275 m_LiveWireContourNode->SetName(
"active livewire node");
279 m_LiveWireContourNode->AddProperty(
"contour.color",
ColorProperty::New(0.1, 1.0, 0.1), NULL,
true);
283 m_EditingContour->Expand(timestep + 1);
285 m_EditingContourNode->SetData(m_EditingContour);
286 m_EditingContourNode->SetName(
"editing node");
290 m_EditingContourNode->AddProperty(
"contour.color",
ColorProperty::New(0.1, 1.0, 0.1), NULL,
true);
291 m_EditingContourNode->AddProperty(
"contour.points.color",
ColorProperty::New(0.0, 0.0, 1.0), NULL,
true);
294 m_ToolManager->GetDataStorage()->Add(m_ContourModelNode, workingDataNode);
295 m_ToolManager->GetDataStorage()->Add(m_LiveWireContourNode, workingDataNode);
296 m_ToolManager->GetDataStorage()->Add(m_EditingContourNode, workingDataNode);
299 m_WorkingSlice = this->GetAffectedReferenceSlice(positionEvent);
301 mitk::Point3D newOrigin = m_WorkingSlice->GetSlicedGeometry()->GetOrigin();
302 m_WorkingSlice->GetSlicedGeometry()->WorldToIndex(newOrigin, newOrigin);
303 m_WorkingSlice->GetSlicedGeometry()->IndexToWorld(newOrigin, newOrigin);
304 m_WorkingSlice->GetSlicedGeometry()->SetOrigin(newOrigin);
307 m_LiveWireFilter->SetInput(m_WorkingSlice);
312 m_WorkingSlice->GetGeometry()->WorldToIndex(click, idx);
319 click[0] = indexWithHighestGradient[0];
320 click[1] = indexWithHighestGradient[1];
321 click[2] = indexWithHighestGradient[2];
322 m_WorkingSlice->GetGeometry()->IndexToWorld(click, click);
325 m_Contour->AddVertex(click,
true, timestep);
326 m_LiveWireFilter->SetStartPoint(click);
330 m_CreateAndUseDynamicCosts =
true;
347 if (m_PlaneGeometry != NULL)
359 typedef mitk::ImageLiveWireContourModelFilter::InternalImageType::IndexType IndexType;
361 for (; iter != m_LiveWireContour->IteratorEnd(timestep); iter++)
364 this->m_WorkingSlice->GetGeometry()->WorldToIndex((*iter)->Coordinates, idx);
366 this->m_LiveWireFilter->AddRepulsivePoint(idx);
370 m_LiveWireContour->RemoveVertexAt(0, timestep);
373 m_LiveWireContour->SetControlVertexAt(m_LiveWireContour->GetNumberOfVertices(timestep) - 1, timestep);
376 m_Contour->Concatenate(m_LiveWireContour, timestep);
379 m_LiveWireContour->Clear(timestep);
384 if (m_CreateAndUseDynamicCosts)
387 m_LiveWireFilter->CreateDynamicCostMap(m_Contour);
388 m_LiveWireFilter->SetUseDynamicCostMap(
true);
408 m_LiveWireFilter->SetTimeStep(timestep);
409 m_LiveWireFilter->Update();
411 m_LiveWireContour = this->m_LiveWireFilter->GetOutput();
412 m_LiveWireContourNode->SetData(this->m_LiveWireContour);
422 m_LiveWireFilter->SetUseDynamicCostMap(
false);
423 OnMouseMoved(NULL, interactionEvent);
424 m_LiveWireFilter->SetUseDynamicCostMap(
true);
442 mitk::Point3D first = this->m_Contour->GetVertexAt(0, timestep)->Coordinates;
444 if (first.EuclideanDistanceTo(click) < 4.5)
473 m_Contour->RemoveVertexAt(m_Contour->GetNumberOfVertices(timestep) - 1, timestep);
476 std::pair<mitk::DataNode::Pointer, mitk::PlaneGeometry::Pointer> cp(
478 this->m_WorkingContours.push_back(cp);
480 std::pair<mitk::DataNode::Pointer, mitk::PlaneGeometry::Pointer> ecp(
482 this->m_EditingContours.push_back(ecp);
484 m_LiveWireFilter->SetUseDynamicCostMap(
false);
491 int numberOfTimesteps =
static_cast<int>(m_Contour->GetTimeGeometry()->CountTimeSteps());
494 for (
unsigned int i = 0; i <= numberOfTimesteps; i++)
499 m_ToolManager->GetDataStorage()->Remove(m_LiveWireContourNode);
502 m_LiveWireContourNode = NULL;
503 m_LiveWireContour = NULL;
508 m_ContourInteractor->SetDataNode(m_ContourModelNode);
510 m_ContourInteractor->LoadStateMachine(
"ContourModelModificationInteractor.xml",
us::GetModuleContext()->GetModule());
512 m_ContourInteractor->SetEventConfig(
"ContourModelModificationConfig.xml",
us::GetModuleContext()->GetModule());
514 m_ContourInteractor->SetWorkingImage(this->m_WorkingSlice);
515 m_ContourInteractor->SetEditingContourModelNode(this->m_EditingContourNode);
516 m_ContourModelNode->SetDataInteractor(m_ContourInteractor.GetPointer());
518 this->m_LiveWireNodes.push_back(m_ContourInteractor);
526 if (m_Contour->GetNumberOfVertices(timestep) <= 1)
528 m_ToolManager->GetDataStorage()->Remove(m_LiveWireContourNode);
529 m_ToolManager->GetDataStorage()->Remove(m_ContourModelNode);
530 m_ToolManager->GetDataStorage()->Remove(m_EditingContourNode);
533 m_ContourModelNode->SetData(m_Contour);
534 m_LiveWireContourNode->SetData(m_LiveWireContour);
535 this->ResetToStartState();
541 m_LiveWireContourNode->SetData(m_LiveWireContour);
544 newContour->Expand(m_Contour->GetTimeSteps());
552 if (newLast != begin)
558 while (newLast != begin && !((*newLast)->IsControlPoint))
564 m_LiveWireFilter->SetStartPoint((*newLast)->Coordinates);
569 while (it <= newLast)
571 newContour->AddVertex((*it)->Coordinates, (*it)->IsControlPoint, timestep);
575 newContour->SetClosed(m_Contour->IsClosed());
578 m_ContourModelNode->SetData(newContour);
580 m_Contour = newContour;
587 template <
typename TPixel,
unsigned int VImageDimension>
593 typedef typename InputImageType::IndexType IndexType;
595 unsigned long xMAX = inputImage->GetLargestPossibleRegion().GetSize()[0];
596 unsigned long yMAX = inputImage->GetLargestPossibleRegion().GetSize()[1];
598 returnIndex[0] = index[0];
599 returnIndex[1] = index[1];
600 returnIndex[2] = 0.0;
602 double gradientMagnitude = 0.0;
603 double maxGradientMagnitude = 0.0;
611 typename InputImageType::SizeType size;
616 IndexType startRegion;
617 startRegion[0] = index[0] - 3;
618 startRegion[1] = index[1] - 3;
619 if (startRegion[0] < 0)
621 if (startRegion[1] < 0)
623 if (xMAX - index[0] < 7)
624 startRegion[0] = xMAX - 7;
625 if (yMAX - index[1] < 7)
626 startRegion[1] = yMAX - 7;
628 index[0] = startRegion[0] + 3;
629 index[1] = startRegion[1] + 3;
631 typename InputImageType::RegionType region;
632 region.SetSize(size);
633 region.SetIndex(startRegion);
635 typedef typename itk::GradientMagnitudeImageFilter<InputImageType, InputImageType> GradientMagnitudeFilterType;
637 gradientFilter->SetInput(inputImage);
638 gradientFilter->GetOutput()->SetRequestedRegion(region);
640 gradientFilter->Update();
642 gradientMagnImage = gradientFilter->GetOutput();
644 IndexType currentIndex;
649 for (
int x = -1; x <= 1; ++x)
651 currentIndex[0] = index[0] + x;
653 for (
int y = -1; y <= 1; ++y)
655 currentIndex[1] = index[1] + y;
657 gradientMagnitude = gradientMagnImage->GetPixel(currentIndex);
660 if (maxGradientMagnitude < gradientMagnitude)
662 maxGradientMagnitude = gradientMagnitude;
663 returnIndex[0] = currentIndex[0];
664 returnIndex[1] = currentIndex[1];
665 returnIndex[2] = 0.0;
669 currentIndex[1] = index[1];
ContourModel is a structure of linked vertices defining a contour in 3D space. The vertices are store...
Super class for all position events.
Data management class that handles 'was created by' relations.
itk::SmartPointer< Self > Pointer
virtual unsigned int GetSlice() const
BaseRenderer * GetSender() const
Base of all data objects.
static void FillContourInSlice(ContourModel *projectedContour, Image *sliceImage, mitk::Image::Pointer workingImage, int paintingPixelValue=1)
Fill a contour in a 2D slice with a specified pixel value at time step 0.
Point3D GetPositionInWorld() const
mitk::ContourElement::VertexIterator VertexIterator
#define MITKSEGMENTATION_EXPORT
DataCollection - Class to facilitate loading/accessing structured data.
virtual const PlaneGeometry * GetCurrentWorldPlaneGeometry()
Get the current 2D-worldgeometry (m_CurrentWorldPlaneGeometry) used for 2D-rendering.
const mitk::TimeGeometry * GetTimeGeometry() const
Return the TimeGeometry of the data as const pointer.
BaseData * GetData() const
Get the data object (instance of BaseData, e.g., an Image) managed by this DataNode.
Constants for most interaction classes, due to the generic StateMachines.
mitk::DataStorage::Pointer m_DataStorage
virtual mitk::RenderingManager * GetRenderingManager() const
Setter for the RenderingManager that handles this instance of BaseRenderer.
itk::Image< double, 3 > InputImageType
#define AccessFixedDimensionByItk_2(mitkImage, itkImageTypeFunction, dimension, arg1, arg2)
static RenderingManager * GetInstance()
Represents an action, that is executed after a certain event (in statemachine-mechanism) TODO: implem...
Module * GetModule() const
Image class for storing images.
static ContourModel::Pointer ProjectContourTo2DSlice(Image *slice, ContourModel *contourIn3D, bool correctionForIpSegmentation, bool constrainToInside)
Projects a contour onto an image point by point. Converts from world to index coordinates.
mitk::ContourElement::ConstVertexIterator ConstVertexIterator
std::vcl_size_t TimeStepType
virtual unsigned int GetTimeStep() const
void RequestUpdate(vtkRenderWindow *renderWindow)
MITKCORE_EXPORT const ScalarType sqrteps
#define CONNECT_CONDITION(a, f)
#define CONNECT_FUNCTION(a, f)
bool IsInside(const mitk::Point3D &p) const
Test whether the point p (world coordinates in mm) is inside the bounding box.
virtual void Remove(const mitk::DataNode *node)=0
Removes node from the DataStorage.
mitk::BaseGeometry * GetGeometry(int t=0) const
Return the geometry, which is a TimeGeometry, of the data as non-const pointer.
itk::SmartPointer< Self > Pointer
static ModuleContext * GetModuleContext()
Returns the module context of the calling module.
vtkRenderWindow * GetRenderWindow() const
Access the RenderWindow into which this renderer renders.
void RequestUpdateAll(RequestType type=REQUEST_UPDATE_ALL)
Class for nodes of the DataTree.
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.