diff --git a/Modules/Classification/CLActiveLearning/include/mitkActiveLearningSuggestRegionFilter.h b/Modules/Classification/CLActiveLearning/include/mitkActiveLearningSuggestRegionFilter.h index 00282a18be..f4319de12b 100644 --- a/Modules/Classification/CLActiveLearning/include/mitkActiveLearningSuggestRegionFilter.h +++ b/Modules/Classification/CLActiveLearning/include/mitkActiveLearningSuggestRegionFilter.h @@ -1,167 +1,167 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkActiveLearningSuggestRegionFilter_h #define mitkActiveLearningSuggestRegionFilter_h #include // ITK #include #include #include #include #include #include #include #include #include #include #include // MITK #include #include namespace mitk { /** \class ActiveLearningSuggestRegionFilter * \brief Filter that takes an image of prediction uncertainties and outputs an image (mask) containing only the most uncertain region * * This is just a composite filter using itkThresholdImageFilter and mitkSelectHighestUncertaintyRegionFilter */ template class MITKCLACTIVELEARNING_EXPORT ActiveLearningSuggestRegionFilter : public itk::ImageToImageFilter { public: typedef itk::ImageToImageFilter SuperClassName; mitkClassMacroItkParent(ActiveLearningSuggestRegionFilter, SuperClassName) itkNewMacro(Self) typedef typename InputImageType::PixelType InputImagePixelType; typedef typename OutputImageType::PixelType OutputImagePixelType; // We're not holding threshold as a member, so no set and get macro void SetThreshold(InputImagePixelType threshold) { if (m_ThresholdFilter->GetLowerThreshold() != threshold) { m_ThresholdFilter->SetLowerThreshold(threshold); this->Modified(); } } InputImagePixelType GetThreshold() const { return m_ThresholdFilter->GetLowerThreshold(); } protected: ActiveLearningSuggestRegionFilter() { m_GaussianFilter = itk::DiscreteGaussianImageFilter::New(); m_ThresholdFilter = itk::BinaryThresholdImageFilter::New(); m_CCFilter = itk::ConnectedComponentImageFilter::New(); m_ThresholdOutputFilter = itk::BinaryThresholdImageFilter::New(); m_OpeningFilter = itk::BinaryMorphologicalOpeningImageFilter::New(); m_ThresholdFilter->SetLowerThreshold(0.5); m_ThresholdFilter->SetOutsideValue(0); m_ThresholdFilter->SetInsideValue(1); m_ThresholdOutputFilter->SetOutsideValue(0); m_ThresholdOutputFilter->SetInsideValue(1); } ~ActiveLearningSuggestRegionFilter(){} virtual void GenerateData() override { // Let this filter's input be threshold filter's input auto input = InputImageType::New(); input->Graft(const_cast(this->GetInput())); m_GaussianFilter->SetInput(input); m_GaussianFilter->Modified(); m_ThresholdFilter->SetInput(m_GaussianFilter->GetOutput()); m_ThresholdFilter->Modified(); StructuringElementType structuringElement; structuringElement.SetRadius(5); structuringElement.CreateStructuringElement(); m_OpeningFilter->SetKernel(structuringElement); m_OpeningFilter->SetInput(m_ThresholdFilter->GetOutput()); - m_OPeningFilter->Modified(); + m_OpeningFilter->Modified(); // Run pipeline to get image with connected components m_CCFilter->SetInput(m_OpeningFilter->GetOutput()); m_CCFilter->Update(); // Find sum of uncertainties for all connected components int ccCount = static_cast(m_CCFilter->GetObjectCount()); std::map ccSize; for (int a=1; a<=ccCount; ++a) {ccSize[a] = 0.0;} auto inputIt = itk::ImageRegionConstIterator(input, input->GetLargestPossibleRegion()); auto outputIt = itk::ImageRegionConstIterator(m_CCFilter->GetOutput(), m_CCFilter->GetOutput()->GetLargestPossibleRegion()); while (!outputIt.IsAtEnd()) { OutputImagePixelType ccVal = outputIt.Get(); InputImagePixelType pixelVal = inputIt.Get(); if (ccVal != 0) {ccSize[ccVal] += pixelVal;} ++outputIt; ++inputIt; } // Find component with largest sum typedef typename std::map::value_type PairType; auto maxComponent = std::max_element(ccSize.begin(), ccSize.end(), [](const PairType& lhs, const PairType& rhs){return lhs.second < rhs.second;}); // Create mask m_ThresholdOutputFilter->SetLowerThreshold(maxComponent->first); m_ThresholdOutputFilter->SetUpperThreshold(maxComponent->first); m_ThresholdOutputFilter->SetInput(m_CCFilter->GetOutput()); m_ThresholdOutputFilter->GraftOutput(this->GetOutput()); m_ThresholdOutputFilter->Update(); this->GraftOutput(m_ThresholdOutputFilter->GetOutput()); } // virtual void PrintSelf(std::ostream & os, itk::Indent indent) const // { // Superclass::PrintSelf(os, indent); // m_ThresholdFilter->PrintSelf(os, indent); // m_RegionFilter->PrintSelf(os, indent); // } private: // ITK examples do this... ActiveLearningSuggestRegionFilter(const Self&); void operator=(const Self&); typename itk::DiscreteGaussianImageFilter::Pointer m_GaussianFilter; typename itk::BinaryThresholdImageFilter::Pointer m_ThresholdFilter; typename itk::ConnectedComponentImageFilter::Pointer m_CCFilter; typename itk::BinaryThresholdImageFilter::Pointer m_ThresholdOutputFilter; typedef itk::BinaryBallStructuringElement StructuringElementType; typename itk::BinaryMorphologicalOpeningImageFilter::Pointer m_OpeningFilter; }; } #endif diff --git a/Modules/Multilabel/mitkLabelSetImage.h b/Modules/Multilabel/mitkLabelSetImage.h index cce2318a4e..c007103223 100644 --- a/Modules/Multilabel/mitkLabelSetImage.h +++ b/Modules/Multilabel/mitkLabelSetImage.h @@ -1,347 +1,349 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __mitkLabelSetImage_H_ #define __mitkLabelSetImage_H_ #include #include #include namespace mitk { //##Documentation //## @brief LabelSetImage class for handling labels and layers in a segmentation session. //## //## Handles operations for adding, removing, erasing and editing labels and layers. //## @ingroup Data class MITKMULTILABEL_EXPORT LabelSetImage : public Image { public: mitkClassMacro(LabelSetImage, Image) itkNewMacro(Self) typedef mitk::Label::PixelType PixelType; /** * \brief BeforeChangeLayerEvent (e.g. used for GUI integration) * As soon as active labelset should be changed, the signal emits. * Emitted by SetActiveLayer(int layer); */ Message<> BeforeChangeLayerEvent; /** * \brief AfterchangeLayerEvent (e.g. used for GUI integration) * As soon as active labelset was changed, the signal emits. * Emitted by SetActiveLayer(int layer); */ Message<> AfterChangeLayerEvent; /** * @brief Initialize an empty mitk::LabelSetImage using the information * of an mitk::Image * @param image the image which is used for initializing the mitk::LabelSetImage */ using mitk::Image::Initialize; virtual void Initialize(const mitk::Image *image) override; /** * \brief */ void Concatenate(mitk::LabelSetImage *image); /** * \brief */ void ClearBuffer(); /** * @brief Merges the mitk::Label with a given target value with the active label * * @param pixelValue the value of the label that should be the new merged label * @param sourcePixelValue the value of the label that should be merged into the specified one * @param layer the layer in which the merge should be performed */ void MergeLabel(PixelType pixelValue, PixelType sourcePixelValue, unsigned int layer = 0); /** * @brief Merges a list of mitk::Labels with the mitk::Label that has a specific value * * @param pixelValue the value of the label that should be the new merged label * @param vectorOfSourcePixelValues the list of label values that should be merge into the specified one * @param layer the layer in which the merge should be performed */ void MergeLabels(PixelType pixelValue, std::vector& vectorOfSourcePixelValues, unsigned int layer = 0); /** * \brief */ void UpdateCenterOfMass(PixelType pixelValue, unsigned int layer = 0); /** * @brief Removes labels from the mitk::LabelSet of given layer. * Calls mitk::LabelSetImage::EraseLabels() which also removes the labels from within the image. * @param VectorOfLabelPixelValues a list of labels to be removed * @param layer the layer in which the labels should be removed */ void RemoveLabels(std::vector &VectorOfLabelPixelValues, unsigned int layer = 0); /** * @brief Erases the label with the given value in the given layer from the underlying image. * The label itself will not be erased from the respective mitk::LabelSet. In order to * remove the label itself use mitk::LabelSetImage::RemoveLabels() * @param pixelValue the label which will be remove from the image * @param layer the layer in which the label should be removed */ void EraseLabel(PixelType pixelValue, unsigned int layer = 0); /** * @brief Similar to mitk::LabelSetImage::EraseLabel() this funtion erase a list of labels from the image * @param VectorOfLabelPixelValues the list of labels that should be remove * @param layer the layer for which the labels should be removed */ void EraseLabels(std::vector &VectorOfLabelPixelValues, unsigned int layer = 0); /** * \brief Returns true if the value exists in one of the labelsets*/ bool ExistLabel(PixelType pixelValue) const; /** * @brief Checks if a label exists in a certain layer * @param pixelValue the label value * @param layer the layer in which should be searched for the label * @return true if the label exists otherwise false */ bool ExistLabel(PixelType pixelValue, unsigned int layer) const; /** * \brief Returns true if the labelset exists*/ bool ExistLabelSet(unsigned int layer) const; /** * @brief Returns the active label of a specific layer * @param layer the layer ID for which the active label should be returned * @return the active label of the specified layer */ mitk::Label *GetActiveLabel(unsigned int layer = 0); /** * @brief Returns the mitk::Label with the given pixelValue and for the given layer * @param pixelValue the pixel value of the label * @param layer the layer in which the labels should be located * @return the mitk::Label if available otherwise NULL */ mitk::Label *GetLabel(PixelType pixelValue, unsigned int layer = 0) const; /** * @brief Returns the currently active mitk::LabelSet * @return the mitk::LabelSet of the active layer or NULL if non is present */ mitk::LabelSet *GetActiveLabelSet(); /** * @brief Gets the mitk::LabelSet for the given layer * @param layer the layer for which the mitk::LabelSet should be retrieved * @return the respective mitk::LabelSet or NULL if non exists for the given layer */ mitk::LabelSet *GetLabelSet(unsigned int layer = 0); const mitk::LabelSet *GetLabelSet(unsigned int layer = 0) const; /** * @brief Gets the ID of the currently active layer * @return the ID of the active layer */ unsigned int GetActiveLayer() const; /** * @brief Get the number of all existing mitk::Labels for a given layer * @param layer the layer ID for which the active mitk::Labels should be retrieved * @return the number of all existing mitk::Labels for the given layer */ unsigned int GetNumberOfLabels(unsigned int layer = 0) const; /** * @brief Returns the number of all labels summed up across all layers * @return the overall number of labels across all layers */ unsigned int GetTotalNumberOfLabels() const; // This function will need to be ported to an external class // it requires knowledge of pixeltype and dimension and includes // too much algorithm to be sensibly part of a data class ///** // * \brief */ // void SurfaceStamp(mitk::Surface* surface, bool forceOverwrite); /** * \brief */ mitk::Image::Pointer CreateLabelMask(PixelType index); /** * @brief Initialize a new mitk::LabelSetImage by an given image. * For all distinct pixel values of the parameter image new labels will * be created. If the number of distinct pixel values exceeds mitk::Label::MAX_LABEL_VALUE * a new layer will be created * @param image the image which is used for initialization */ void InitializeByLabeledImage(mitk::Image::Pointer image); /** * \brief */ void MaskStamp(mitk::Image *mask, bool forceOverwrite); /** * \brief */ void SetActiveLayer(unsigned int layer); /** * \brief */ unsigned int GetNumberOfLayers() const; /** * @brief Adds a new layer to the LabelSetImage. The new layer will be set as the active one * @param layer a mitk::LabelSet which will be set as new layer. * @return the layer ID of the new layer */ unsigned int AddLayer(mitk::LabelSet::Pointer layer = nullptr); /** * \brief Add a layer based on a provided mitk::Image * \param layerImage is added to the vector of label images * \param lset a label set that will be added to the new layer if provided *\return the layer ID of the new layer */ unsigned int AddLayer(mitk::Image::Pointer layerImage, mitk::LabelSet::Pointer lset = nullptr); /** * \brief Add a LabelSet to an existing layer * * This will replace an existing labelSet if one exists. Throws an exceptions if you are trying * to add a labelSet to a non-existing layer. * * If there are no labelSets for layers with an id less than layerIdx default ones will be added * for them. * * \param layerIdx The index of the layer the LabelSet should be added to * \param labelSet The LabelSet that should be added */ void AddLabelSetToLayer(const unsigned int layerIdx, const mitk::LabelSet::Pointer labelSet); /** * @brief Removes the active layer and the respective mitk::LabelSet and image information. * The new active layer is the one below, if exists */ void RemoveLayer(); /** * \brief */ mitk::Image *GetLayerImage(unsigned int layer); const mitk::Image *GetLayerImage(unsigned int layer) const; void OnLabelSetModified(); /** * @brief Sets the label which is used as default exterior label when creating a new layer * @param label the label which will be used as new exterior label */ void SetExteriorLabel(mitk::Label *label); + void SetLayerImage(unsigned int layer, mitk::Image *image); + /** * @brief Gets the mitk::Label which is used as default exterior label * @return the exterior mitk::Label */ mitk::Label *GetExteriorLabel(); const mitk::Label *GetExteriorLabel() const; protected: mitkCloneMacro(Self) LabelSetImage(); LabelSetImage(const LabelSetImage &other); virtual ~LabelSetImage(); template void ChangeLayerProcessing(ImageType1 *source, ImageType2 *target); template void LayerContainerToImageProcessing(itk::Image *source, unsigned int layer); template void ImageToLayerContainerProcessing(itk::Image *source, unsigned int layer) const; template void CalculateCenterOfMassProcessing(ImageType *input, PixelType index, unsigned int layer); template void ClearBufferProcessing(ImageType *input); template void EraseLabelProcessing(ImageType *input, PixelType index, unsigned int layer); // template < typename ImageType > // void ReorderLabelProcessing( ImageType* input, int index, int layer); template void MergeLabelProcessing(ImageType *input, PixelType pixelValue, PixelType index); template void ConcatenateProcessing(ImageType *input, mitk::LabelSetImage *other); template void MaskStampProcessing(ImageType *input, mitk::Image *mask, bool forceOverwrite); template void CreateLabelMaskProcessing(ImageType *input, mitk::Image *mask, PixelType index); template void InitializeByLabeledImageProcessing(LabelSetImageType *input, ImageType *other); std::vector m_LabelSetContainer; std::vector m_LayerContainer; int m_ActiveLayer; bool m_activeLayerInvalid; mitk::Label::Pointer m_ExteriorLabel; }; /** * @brief Equal A function comparing two label set images for beeing equal in meta- and imagedata * * @ingroup MITKTestingAPI * * Following aspects are tested for equality: * - LabelSetImage members * - working image data * - layer image data * - labels in label set * * @param rightHandSide An image to be compared * @param leftHandSide An image to be compared * @param eps Tolerance for comparison. You can use mitk::eps in most cases. * @param verbose Flag indicating if the user wants detailed console output or not. * @return true, if all subsequent comparisons are true, false otherwise */ MITKMULTILABEL_EXPORT bool Equal(const mitk::LabelSetImage &leftHandSide, const mitk::LabelSetImage &rightHandSide, ScalarType eps, bool verbose); } // namespace mitk #endif // __mitkLabelSetImage_H_