diff --git a/Plugins/org.mitk.gui.qt.application/src/QmitkDataNodeReinitAction.cpp b/Plugins/org.mitk.gui.qt.application/src/QmitkDataNodeReinitAction.cpp index 4cc09949e7..1a62a732dc 100644 --- a/Plugins/org.mitk.gui.qt.application/src/QmitkDataNodeReinitAction.cpp +++ b/Plugins/org.mitk.gui.qt.application/src/QmitkDataNodeReinitAction.cpp @@ -1,133 +1,133 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include // mitk core #include #include #include #include #include // mitk gui common plugin #include // namespace that contains the concrete action namespace ReinitAction { void Run(berry::IWorkbenchPartSite::Pointer workbenchPartSite, mitk::DataStorage::Pointer dataStorage, const QList& selectedNodes /*= QList()*/, mitk::BaseRenderer* baseRenderer /*= nullptr*/) { if (selectedNodes.empty()) { return; } if (workbenchPartSite.IsNotNull()) { auto renderWindow = mitk::WorkbenchUtil::GetRenderWindowPart(workbenchPartSite->GetPage(), mitk::WorkbenchUtil::NONE); if (nullptr == renderWindow) { renderWindow = mitk::WorkbenchUtil::OpenRenderWindowPart(workbenchPartSite->GetPage(), false); if (nullptr == renderWindow) { // no render window available return; } } } auto boundingBoxPredicate = mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("includeInBoundingBox", mitk::BoolProperty::New(false), baseRenderer)); mitk::DataStorage::SetOfObjects::Pointer nodes = mitk::DataStorage::SetOfObjects::New(); for (const auto& dataNode : selectedNodes) { if (boundingBoxPredicate->CheckNode(dataNode)) { nodes->InsertElement(nodes->Size(), dataNode); } } if (nodes->empty()) { return; } if (1 == nodes->Size()) // Special case: If exactly one ... { auto image = dynamic_cast(nodes->ElementAt(0)->GetData()); if (nullptr != image) // ... image is selected, reinit is expected to rectify askew images. { if (nullptr == baseRenderer) { - mitk::RenderingManager::GetInstance()->InitializeViews(image->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL); + mitk::RenderingManager::GetInstance()->InitializeViews(image->GetTimeGeometry()); } else { - mitk::RenderingManager::GetInstance()->InitializeView(baseRenderer->GetRenderWindow(), image->GetTimeGeometry(), true); + mitk::RenderingManager::GetInstance()->InitializeView(baseRenderer->GetRenderWindow(), image->GetTimeGeometry()); } return; } } auto boundingGeometry = dataStorage->ComputeBoundingGeometry3D(nodes, "visible", baseRenderer); if (nullptr == baseRenderer) { mitk::RenderingManager::GetInstance()->InitializeViews(boundingGeometry); } else { mitk::RenderingManager::GetInstance()->InitializeView(baseRenderer->GetRenderWindow(), boundingGeometry); } } } QmitkDataNodeReinitAction::QmitkDataNodeReinitAction(QWidget* parent, berry::IWorkbenchPartSite::Pointer workbenchpartSite) : QAction(parent) , QmitkAbstractDataNodeAction(workbenchpartSite) { setText(tr("Reinit")); InitializeAction(); } QmitkDataNodeReinitAction::QmitkDataNodeReinitAction(QWidget* parent, berry::IWorkbenchPartSite* workbenchpartSite) : QAction(parent) , QmitkAbstractDataNodeAction(berry::IWorkbenchPartSite::Pointer(workbenchpartSite)) { setText(tr("Reinit")); InitializeAction(); } void QmitkDataNodeReinitAction::InitializeAction() { connect(this, &QmitkDataNodeReinitAction::triggered, this, &QmitkDataNodeReinitAction::OnActionTriggered); } void QmitkDataNodeReinitAction::OnActionTriggered(bool /*checked*/) { if (m_WorkbenchPartSite.Expired()) { return; } if (m_DataStorage.IsExpired()) { return; } mitk::BaseRenderer::Pointer baseRenderer = GetBaseRenderer(); auto selectedNodes = GetSelectedNodes(); ReinitAction::Run(m_WorkbenchPartSite.Lock(), m_DataStorage.Lock(), selectedNodes, baseRenderer); } diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkAutocropAction.cpp b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkAutocropAction.cpp index 5cf185edc8..0e2b55a2c0 100644 --- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkAutocropAction.cpp +++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkAutocropAction.cpp @@ -1,192 +1,191 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "QmitkAutocropAction.h" #include "mitkAutoCropImageFilter.h" #include "mitkImageCast.h" #include "mitkImageWriteAccessor.h" #include "mitkRenderingManager.h" #include "mitkProgressBar.h" #include //needed for qApp #include QmitkAutocropAction::QmitkAutocropAction() { } QmitkAutocropAction::~QmitkAutocropAction() { } void QmitkAutocropAction::Run( const QList &selectedNodes ) { foreach ( mitk::DataNode::Pointer node, selectedNodes ) { if (node) { mitk::Image::Pointer image = dynamic_cast( node->GetData() ); if (image.IsNull()) return; mitk::ProgressBar::GetInstance()->AddStepsToDo(10); mitk::ProgressBar::GetInstance()->Progress(2); qApp->processEvents(); mitk::AutoCropImageFilter::Pointer cropFilter = mitk::AutoCropImageFilter::New(); cropFilter->SetInput( image ); cropFilter->SetBackgroundValue( 0 ); try { cropFilter->Update(); image = cropFilter->GetOutput(); if (image.IsNotNull()) { if (image->GetDimension() == 4) { MITK_INFO << "4D AUTOCROP DOES NOT WORK AT THE MOMENT"; throw "4D AUTOCROP DOES NOT WORK AT THE MOMENT"; unsigned int timesteps = image->GetDimension(3); for (unsigned int i = 0; i < timesteps; i++) { mitk::ImageTimeSelector::Pointer imageTimeSelector = mitk::ImageTimeSelector::New(); imageTimeSelector->SetInput(image); imageTimeSelector->SetTimeNr(i); imageTimeSelector->UpdateLargestPossibleRegion(); // We split a long nested code line into separate calls for debugging: mitk::ImageSource::OutputImageType *_3dSlice = imageTimeSelector->GetOutput(); mitk::Image::Pointer _cropped3dSlice = this->IncreaseCroppedImageSize(_3dSlice); // +++ BUG +++ BUG +++ BUG +++ BUG +++ BUG +++ BUG +++ BUG +++ mitk::ImageWriteAccessor imAccess(_cropped3dSlice); void *_data = imAccess.GetData(); // // We write some stripes into the image if ((i & 1) == 0) { int depth = _cropped3dSlice->GetDimension(2); int height = _cropped3dSlice->GetDimension(1); int width = _cropped3dSlice->GetDimension(0); for (int z = 0; z < depth; ++z) for (int y = 0; y < height; ++y) for (int x = 0; x < width; ++x) reinterpret_cast(_data)[(width * height * z) + (width * y) + x] = x & 1; // } image->SetVolume(_data, i); } node->SetData( image ); // bug fix 3145 } else { node->SetData( this->IncreaseCroppedImageSize(image) ); // bug fix 3145 } // Reinit node - mitk::RenderingManager::GetInstance()->InitializeViews( - node->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true); + mitk::RenderingManager::GetInstance()->InitializeViews(node->GetData()->GetTimeGeometry()); } } catch(...) { MITK_ERROR << "Cropping image failed..."; } mitk::ProgressBar::GetInstance()->Progress(8); } else { MITK_INFO << " a nullptr node selected"; } } } mitk::Image::Pointer QmitkAutocropAction::IncreaseCroppedImageSize( mitk::Image::Pointer image ) { typedef itk::Image< short, 3 > ImageType; typedef itk::Image< unsigned char, 3 > PADOutputImageType; ImageType::Pointer itkTransformImage = ImageType::New(); mitk::CastToItkImage( image, itkTransformImage ); typedef itk::ConstantPadImageFilter< ImageType, PADOutputImageType > PadFilterType; PadFilterType::Pointer padFilter = PadFilterType::New(); itk::SizeValueType upperPad[3]; itk::SizeValueType lowerPad[3]; int borderLiner = 3; mitk::Point3D mitkOriginPoint; double origin[3]; origin[0]=0; origin[1]=0; origin[2]=0; itkTransformImage->SetOrigin(origin); lowerPad[0]=borderLiner; lowerPad[1]=borderLiner; lowerPad[2]=borderLiner; upperPad[0]=borderLiner; upperPad[1]=borderLiner; upperPad[2]=borderLiner; padFilter->SetInput(itkTransformImage); padFilter->SetConstant(0); padFilter->SetPadUpperBound(upperPad); padFilter->SetPadLowerBound(lowerPad); padFilter->UpdateLargestPossibleRegion(); mitk::Image::Pointer paddedImage = mitk::Image::New(); paddedImage->InitializeByItk(padFilter->GetOutput()); mitk::CastToMitkImage(padFilter->GetOutput(), paddedImage); //calculate translation according to padding to get the new origin mitk::Point3D paddedOrigin = image->GetGeometry()->GetOrigin(); mitk::Vector3D spacing = image->GetGeometry()->GetSpacing(); paddedOrigin[0] -= (borderLiner)*spacing[0]; paddedOrigin[1] -= (borderLiner)*spacing[1]; paddedOrigin[2] -= (borderLiner)*spacing[2]; paddedImage->GetGeometry()->SetOrigin( paddedOrigin ); return paddedImage; } void QmitkAutocropAction::SetSmoothed(bool /*smoothed*/) { //not needed } void QmitkAutocropAction::SetDecimated(bool /*decimated*/) { //not needed } void QmitkAutocropAction::SetDataStorage(mitk::DataStorage* /*dataStorage*/) { //not needed } void QmitkAutocropAction::SetFunctionality(berry::QtViewPart* /*view*/) { //not needed } diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkAutocropLabelSetImageAction.cpp b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkAutocropLabelSetImageAction.cpp index 5d4494547c..f7f5f77362 100644 --- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkAutocropLabelSetImageAction.cpp +++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkAutocropLabelSetImageAction.cpp @@ -1,300 +1,300 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "QmitkAutocropLabelSetImageAction.h" #include #include #include #include namespace { // Iterate over all layers, time steps, and dimensions of a LabelSetImage to // determine the overall minimum and maximum indices of labeled pixels. // // Returns false if the input image is empty, minIndex and maxIndex contain // valid indices otherwise. // // Throws an mitk::Exception if read access was denied. // bool DetermineMinimumAndMaximumIndicesOfNonBackgroundPixels(mitk::LabelSetImage::Pointer labelSetImage, itk::Index<3>& minIndex, itk::Index<3>& maxIndex) { // We need a time selector to handle 3d+t images. It is not used for 3d images, though. auto timeSelector = mitk::ImageTimeSelector::New(); timeSelector->SetInput(labelSetImage); const auto background = labelSetImage->GetExteriorLabel()->GetValue(); const auto numLayers = labelSetImage->GetNumberOfLayers(); const auto numTimeSteps = labelSetImage->GetTimeSteps(); const itk::Index<3> dim = { labelSetImage->GetDimension(0), labelSetImage->GetDimension(1), labelSetImage->GetDimension(2) }; maxIndex = { 0, 0, 0 }; minIndex = dim; itk::Index<3> index; bool labelSetImageIsEmpty = true; for (std::remove_const_t layer = 0; layer < numLayers; ++layer) { labelSetImage->SetActiveLayer(layer); for (std::remove_const_t timeStep = 0; timeStep < numTimeSteps; ++timeStep) { const mitk::Image* image = nullptr; if (numTimeSteps > 1) { timeSelector->SetTimeNr(timeStep); timeSelector->Update(); image = timeSelector->GetOutput(); } else { image = labelSetImage; } mitk::ImagePixelReadAccessor pixelReader(image); bool imageIsEmpty = true; for (index[2] = 0; index[2] < dim[2]; ++index[2]) { for (index[1] = 0; index[1] < dim[1]; ++index[1]) { for (index[0] = 0; index[0] < dim[0]; ++index[0]) { if (background != pixelReader.GetPixelByIndex(index)) { imageIsEmpty = false; minIndex = { std::min(minIndex[0], index[0]), std::min(minIndex[1], index[1]), std::min(minIndex[2], index[2]) }; break; } } } } if (imageIsEmpty) continue; maxIndex = { std::max(maxIndex[0], minIndex[0]), std::max(maxIndex[1], minIndex[1]), std::max(maxIndex[2], minIndex[2]) }; for (index[2] = dim[2] - 1; index[2] >= 0; --index[2]) { for (index[1] = dim[1] - 1; index[1] >= 0; --index[1]) { for (index[0] = dim[0] - 1; index[0] >= 0; --index[0]) { if (background != pixelReader.GetPixelByIndex(index)) { maxIndex = { std::max(maxIndex[0], index[0]), std::max(maxIndex[1], index[1]), std::max(maxIndex[2], index[2]) }; break; } } } } if (!imageIsEmpty) labelSetImageIsEmpty = false; } } return !labelSetImageIsEmpty; } // Crop a LabelSetImage. Labels in the cropped LabelSetImage will still have // their original properties like names and colors. // // Returns a cropped LabelSetImage. // // Throws an mitk::Exception if read access was denied. // mitk::LabelSetImage::Pointer Crop(mitk::LabelSetImage::Pointer labelSetImage, const itk::Index<3>& minIndex, const itk::Index<3>& maxIndex) { // We need a time selector to handle 3d+t images. It is not used for 3d images, though. auto timeSelector = mitk::ImageTimeSelector::New(); timeSelector->SetInput(labelSetImage); const auto numLayers = labelSetImage->GetNumberOfLayers(); const auto numTimeSteps = labelSetImage->GetTimeSteps(); const itk::Index<3> croppedDim = { 1 + maxIndex[0] - minIndex[0], 1 + maxIndex[1] - minIndex[1], 1 + maxIndex[2] - minIndex[2] }; const auto numPixels = croppedDim[0] * croppedDim[1] * croppedDim[2]; mitk::BaseGeometry::BoundsArrayType croppedBounds; croppedBounds[0] = 0; croppedBounds[1] = croppedDim[0]; croppedBounds[2] = 0; croppedBounds[3] = croppedDim[1]; croppedBounds[4] = 0; croppedBounds[5] = croppedDim[2]; // Clone and adapt the original TimeGeometry to the cropped region auto croppedTimeGeometry = labelSetImage->GetTimeGeometry()->Clone(); for (std::remove_const_t timeStep = 0; timeStep < numTimeSteps; ++timeStep) { auto geometry = croppedTimeGeometry->GetGeometryForTimeStep(timeStep); mitk::Point3D croppedOrigin; geometry->IndexToWorld(minIndex, croppedOrigin); geometry->SetOrigin(croppedOrigin); geometry->SetBounds(croppedBounds); } auto croppedLabelSetImage = mitk::LabelSetImage::New(); croppedLabelSetImage->Initialize(mitk::MakeScalarPixelType(), *croppedTimeGeometry); // Create cropped image volumes for all time steps in all layers for (std::remove_const_t layer = 0; layer < numLayers; ++layer) { labelSetImage->SetActiveLayer(layer); croppedLabelSetImage->AddLayer(); for (std::remove_const_t timeStep = 0; timeStep < numTimeSteps; ++timeStep) { const mitk::Image* image = nullptr; if (numTimeSteps > 1) { timeSelector->SetTimeNr(timeStep); timeSelector->Update(); image = timeSelector->GetOutput(); } else { image = labelSetImage; } mitk::ImagePixelReadAccessor pixelReader(image); auto* croppedVolume = new mitk::LabelSetImage::PixelType[numPixels]; itk::Index<3> croppedIndex; itk::Index<3> index; for (croppedIndex[2] = 0; croppedIndex[2] < croppedDim[2]; ++croppedIndex[2]) { for (croppedIndex[1] = 0; croppedIndex[1] < croppedDim[1]; ++croppedIndex[1]) { for (croppedIndex[0] = 0; croppedIndex[0] < croppedDim[0]; ++croppedIndex[0]) { index[0] = croppedIndex[0] + minIndex[0]; index[1] = croppedIndex[1] + minIndex[1]; index[2] = croppedIndex[2] + minIndex[2]; const auto& pixel = pixelReader.GetPixelByIndex(index); croppedVolume[croppedIndex[2] * croppedDim[1] * croppedDim[0] + croppedIndex[1] * croppedDim[0] + croppedIndex[0]] = pixel; } } } croppedLabelSetImage->SetImportVolume(croppedVolume, timeStep, 0, mitk::Image::ReferenceMemory); croppedLabelSetImage->AddLabelSetToLayer(layer, labelSetImage->GetLabelSet(layer)); } } return croppedLabelSetImage; } } QmitkAutocropLabelSetImageAction::QmitkAutocropLabelSetImageAction() { } QmitkAutocropLabelSetImageAction::~QmitkAutocropLabelSetImageAction() { } void QmitkAutocropLabelSetImageAction::Run(const QList& selectedNodes) { for (const auto& dataNode : selectedNodes) { mitk::LabelSetImage::Pointer labelSetImage = dynamic_cast(dataNode->GetData()); if (labelSetImage.IsNull()) continue; // Backup currently active layer as we need to restore it later auto activeLayer = labelSetImage->GetActiveLayer(); mitk::LabelSetImage::Pointer croppedLabelSetImage; itk::Index<3> minIndex; itk::Index<3> maxIndex; try { if (!DetermineMinimumAndMaximumIndicesOfNonBackgroundPixels(labelSetImage, minIndex, maxIndex)) { MITK_WARN << "Autocrop was skipped: Image \"" << dataNode->GetName() << "\" is empty."; labelSetImage->SetActiveLayer(activeLayer); // Restore the originally active layer return; } croppedLabelSetImage = Crop(labelSetImage, minIndex, maxIndex); } catch (const mitk::Exception&) { MITK_ERROR << "Autocrop was aborted: Image read access to \"" << dataNode->GetName() << "\" was denied."; labelSetImage->SetActiveLayer(activeLayer); // Restore the originally active layer return; } // Restore the originally active layer in the cropped LabelSetImage croppedLabelSetImage->SetActiveLayer(activeLayer); // Override the original LabelSetImage with the cropped LabelSetImage dataNode->SetData(croppedLabelSetImage); // If we cropped a single LabelSetImage, reinit the views to give a visible feedback to the user if (1 == selectedNodes.size()) - mitk::RenderingManager::GetInstance()->InitializeViews(croppedLabelSetImage->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true); + mitk::RenderingManager::GetInstance()->InitializeViews(croppedLabelSetImage->GetTimeGeometry()); } } void QmitkAutocropLabelSetImageAction::SetSmoothed(bool) { } void QmitkAutocropLabelSetImageAction::SetDecimated(bool) { } void QmitkAutocropLabelSetImageAction::SetDataStorage(mitk::DataStorage*) { } void QmitkAutocropLabelSetImageAction::SetFunctionality(berry::QtViewPart*) { }