Slicer学习笔记(六十一)slicer下segmentation segment合并

slicer下segmentation segment合并


slicer合并segment volume
参考python源代码

 def onApply(self):
    # Make sure the user wants to do the operation, even if the segment is not visible
    if not self.scriptedEffect.confirmCurrentSegmentVisible():
      return

    import vtkSegmentationCorePython as vtkSegmentationCore

    self.scriptedEffect.saveStateForUndo()

    import vtkSegmentationCorePython as vtkSegmentationCore

    # Get modifier labelmap and parameters

    operation = self.scriptedEffect.parameter("Operation")
    bypassMasking =  (self.scriptedEffect.integerParameter("BypassMasking") != 0)

    selectedSegmentID = self.scriptedEffect.parameterSetNode().GetSelectedSegmentID()

    segmentationNode = self.scriptedEffect.parameterSetNode().GetSegmentationNode()
    segmentation = segmentationNode.GetSegmentation()

    if operation in self.operationsRequireModifierSegment:

      # Get modifier segment
      modifierSegmentID = self.modifierSegmentID()
      if not modifierSegmentID:
        logging.error("Operation {0} requires a selected modifier segment".format(operation))
        return
      modifierSegment = segmentation.GetSegment(modifierSegmentID)
      modifierSegmentLabelmap = slicer.vtkOrientedImageData()
      segmentationNode.GetBinaryLabelmapRepresentation(modifierSegmentID, modifierSegmentLabelmap)

      # Get common geometry
      commonGeometryString = segmentationNode.GetSegmentation().DetermineCommonLabelmapGeometry(
        vtkSegmentationCore.vtkSegmentation.EXTENT_UNION_OF_SEGMENTS, None)
      if not commonGeometryString:
        logging.info("Logical operation skipped: all segments are empty")
        return
      commonGeometryImage = slicer.vtkOrientedImageData()
      vtkSegmentationCore.vtkSegmentationConverter.DeserializeImageGeometry(commonGeometryString, commonGeometryImage, False)

      # Make sure modifier segment has correct geometry
      # (if modifier segment has been just copied over from another segment then its geometry may be different)
      if not vtkSegmentationCore.vtkOrientedImageDataResample.DoGeometriesMatch(commonGeometryImage, modifierSegmentLabelmap):
        modifierSegmentLabelmap_CommonGeometry = slicer.vtkOrientedImageData()
        vtkSegmentationCore.vtkOrientedImageDataResample.ResampleOrientedImageToReferenceOrientedImage(
          modifierSegmentLabelmap, commonGeometryImage, modifierSegmentLabelmap_CommonGeometry,
          False, # nearest neighbor interpolation,
          True # make sure resampled modifier segment is not cropped
          )
        modifierSegmentLabelmap = modifierSegmentLabelmap_CommonGeometry

      if operation == LOGICAL_COPY:
          self.scriptedEffect.modifySelectedSegmentByLabelmap(
            modifierSegmentLabelmap, slicer.qSlicerSegmentEditorAbstractEffect.ModificationModeSet, bypassMasking)
      elif operation == LOGICAL_UNION:
          self.scriptedEffect.modifySelectedSegmentByLabelmap(
            modifierSegmentLabelmap, slicer.qSlicerSegmentEditorAbstractEffect.ModificationModeAdd, bypassMasking)
      elif operation == LOGICAL_SUBTRACT:
          self.scriptedEffect.modifySelectedSegmentByLabelmap(
            modifierSegmentLabelmap, slicer.qSlicerSegmentEditorAbstractEffect.ModificationModeRemove, bypassMasking)
      elif operation == LOGICAL_INTERSECT:
        selectedSegmentLabelmap = self.scriptedEffect.selectedSegmentLabelmap()
        intersectionLabelmap = slicer.vtkOrientedImageData()
        vtkSegmentationCore.vtkOrientedImageDataResample.MergeImage(
          selectedSegmentLabelmap, modifierSegmentLabelmap, intersectionLabelmap,
          vtkSegmentationCore.vtkOrientedImageDataResample.OPERATION_MINIMUM, selectedSegmentLabelmap.GetExtent())
        selectedSegmentLabelmapExtent = selectedSegmentLabelmap.GetExtent()
        modifierSegmentLabelmapExtent = modifierSegmentLabelmap.GetExtent()
        commonExtent = [max(selectedSegmentLabelmapExtent[0], modifierSegmentLabelmapExtent[0]),
          min(selectedSegmentLabelmapExtent[1], modifierSegmentLabelmapExtent[1]),
          max(selectedSegmentLabelmapExtent[2], modifierSegmentLabelmapExtent[2]),
          min(selectedSegmentLabelmapExtent[3], modifierSegmentLabelmapExtent[3]),
          max(selectedSegmentLabelmapExtent[4], modifierSegmentLabelmapExtent[4]),
          min(selectedSegmentLabelmapExtent[5], modifierSegmentLabelmapExtent[5])]
        self.scriptedEffect.modifySelectedSegmentByLabelmap(
          intersectionLabelmap, slicer.qSlicerSegmentEditorAbstractEffect.ModificationModeSet, commonExtent, bypassMasking)

    elif operation == LOGICAL_INVERT:
      selectedSegmentLabelmap = self.scriptedEffect.selectedSegmentLabelmap()
      invertedSelectedSegmentLabelmap = self.getInvertedBinaryLabelmap(selectedSegmentLabelmap)
      self.scriptedEffect.modifySelectedSegmentByLabelmap(
        invertedSelectedSegmentLabelmap, slicer.qSlicerSegmentEditorAbstractEffect.ModificationModeSet, bypassMasking)

    elif operation == LOGICAL_CLEAR or operation == LOGICAL_FILL:
      selectedSegmentLabelmap = self.scriptedEffect.selectedSegmentLabelmap()
      vtkSegmentationCore.vtkOrientedImageDataResample.FillImage(selectedSegmentLabelmap, 1 if operation == LOGICAL_FILL else 0, selectedSegmentLabelmap.GetExtent())
      self.scriptedEffect.modifySelectedSegmentByLabelmap(
        selectedSegmentLabelmap, slicer.qSlicerSegmentEditorAbstractEffect.ModificationModeSet, bypassMasking)

    else:
      logging.error("Unknown operation: {0}".format(operation))

LOGICAL_COPY = 'COPY'
LOGICAL_UNION = 'UNION'
LOGICAL_INTERSECT = 'INTERSECT'
LOGICAL_SUBTRACT = 'SUBTRACT'
LOGICAL_INVERT = 'INVERT'
LOGICAL_CLEAR = 'CLEAR'
LOGICAL_FILL = 'FILL'

参考c++源代码

void qSlicerSegmentEditorAbstractEffect::modifySegmentByLabelmap(vtkMRMLSegmentationNode* segmentationNode, const char* segmentID,
  vtkOrientedImageData* modifierLabelmapInput, ModificationMode modificationMode, const int modificationExtent[6], bool bypassMasking/*=false*/)
{
    
    
  Q_D(qSlicerSegmentEditorAbstractEffect);

  vtkMRMLSegmentEditorNode* parameterSetNode = this->parameterSetNode();
  if (!parameterSetNode)
    {
    
    
    qCritical() << Q_FUNC_INFO << ": Invalid segment editor parameter set node";
    this->defaultModifierLabelmap();
    return;
    }

  if (!segmentationNode)
    {
    
    
    qCritical() << Q_FUNC_INFO << ": Invalid segmentation";
    this->defaultModifierLabelmap();
    return;
    }

  vtkSegment* segment = nullptr;
  if (segmentID)
    {
    
    
    segment = segmentationNode->GetSegmentation()->GetSegment(segmentID);
    }
  if (!segment)
    {
    
    
    qCritical() << Q_FUNC_INFO << ": Invalid segment";
    this->defaultModifierLabelmap();
    return;
    }

  if (!modifierLabelmapInput)
    {
    
    
    // If per-segment flag is off, then it is not an error (the effect itself has written it back to segmentation)
    if (this->perSegment())
      {
    
    
      qCritical() << Q_FUNC_INFO << ": Cannot apply edit operation because modifier labelmap cannot be accessed";
      }
    this->defaultModifierLabelmap();
    return;
    }

  vtkSmartPointer<vtkOrientedImageData> modifierLabelmap = modifierLabelmapInput;
  if ((!bypassMasking && parameterSetNode->GetMaskMode() != vtkMRMLSegmentEditorNode::PaintAllowedEverywhere) ||
    parameterSetNode->GetMasterVolumeIntensityMask())
    {
    
    
    vtkNew<vtkOrientedImageData> maskImage;
    maskImage->SetExtent(modifierLabelmap->GetExtent());
    maskImage->SetSpacing(modifierLabelmap->GetSpacing());
    maskImage->SetOrigin(modifierLabelmap->GetOrigin());
    maskImage->CopyDirections(modifierLabelmap);
    maskImage->AllocateScalars(VTK_UNSIGNED_CHAR, 1);
    vtkOrientedImageDataResample::FillImage(maskImage, m_EraseValue);

    // Apply mask to modifier labelmap if masking is enabled
    if (!bypassMasking && parameterSetNode->GetMaskMode() != vtkMRMLSegmentEditorNode::PaintAllowedEverywhere)
      {
    
    
      vtkOrientedImageDataResample::ModifyImage(maskImage, this->maskLabelmap(), vtkOrientedImageDataResample::OPERATION_MAXIMUM);
      }

    // Apply threshold mask if paint threshold is turned on
    if (parameterSetNode->GetMasterVolumeIntensityMask())
      {
    
    
      vtkOrientedImageData* masterVolumeOrientedImageData = this->masterVolumeImageData();
      if (!masterVolumeOrientedImageData)
        {
    
    
        qCritical() << Q_FUNC_INFO << ": Unable to get master volume image";
        this->defaultModifierLabelmap();
        return;
        }
      // Make sure the modifier labelmap has the same geometry as the master volume
      if (!vtkOrientedImageDataResample::DoGeometriesMatch(modifierLabelmap, masterVolumeOrientedImageData))
        {
    
    
        qCritical() << Q_FUNC_INFO << ": Modifier labelmap should have the same geometry as the master volume";
        this->defaultModifierLabelmap();
        return;
        }

      // Create threshold image
      vtkSmartPointer<vtkImageThreshold> threshold = vtkSmartPointer<vtkImageThreshold>::New();
      threshold->SetInputData(masterVolumeOrientedImageData);
      threshold->ThresholdBetween(parameterSetNode->GetMasterVolumeIntensityMaskRange()[0], parameterSetNode->GetMasterVolumeIntensityMaskRange()[1]);
      threshold->SetInValue(m_EraseValue);
      threshold->SetOutValue(m_FillValue);
      threshold->SetOutputScalarTypeToUnsignedChar();
      threshold->Update();

      vtkSmartPointer<vtkOrientedImageData> thresholdMask = vtkSmartPointer<vtkOrientedImageData>::New();
      thresholdMask->ShallowCopy(threshold->GetOutput());
      vtkSmartPointer<vtkMatrix4x4> modifierLabelmapToWorldMatrix = vtkSmartPointer<vtkMatrix4x4>::New();
      modifierLabelmap->GetImageToWorldMatrix(modifierLabelmapToWorldMatrix);
      thresholdMask->SetGeometryFromImageToWorldMatrix(modifierLabelmapToWorldMatrix);
      vtkOrientedImageDataResample::ModifyImage(maskImage, thresholdMask, vtkOrientedImageDataResample::OPERATION_MAXIMUM);
      }

    vtkNew<vtkOrientedImageData> maskWithCurrentSegment;
    maskWithCurrentSegment->DeepCopy(maskImage);

    bool paintInsideSegments = this->parameterSetNode()->GetMaskMode() == vtkMRMLSegmentationNode::EditAllowedInsideAllSegments ||
      this->parameterSetNode()->GetMaskMode() == vtkMRMLSegmentationNode::EditAllowedInsideVisibleSegments ||
      this->parameterSetNode()->GetMaskMode() == vtkMRMLSegmentationNode::EditAllowedInsideSingleSegment;
    vtkSmartPointer<vtkOrientedImageData> segmentLayerLabelmap =
      vtkOrientedImageData::SafeDownCast(segment->GetRepresentation(segmentationNode->GetSegmentation()->GetMasterRepresentationName()));
    if (segmentLayerLabelmap && paintInsideSegments)
      {
    
    
      // If we are painting inside a segment, some effects can modify the current segment outside the masking region (ex. erase effect can add-back regions)
      // Add the current segment to the editable area
      vtkNew<vtkImageThreshold> segmentInverter;
      segmentInverter->SetInputData(segmentLayerLabelmap);
      segmentInverter->SetInValue(m_EraseValue);
      segmentInverter->SetOutValue(m_FillValue);
      segmentInverter->ReplaceInOn();
      segmentInverter->ThresholdBetween(segment->GetLabelValue(), segment->GetLabelValue());
      segmentInverter->SetOutputScalarTypeToUnsignedChar();
      segmentInverter->Update();

      vtkNew<vtkOrientedImageData> invertedSegment;
      invertedSegment->ShallowCopy(segmentInverter->GetOutput());
      invertedSegment->CopyDirections(segmentLayerLabelmap);
      vtkOrientedImageDataResample::ModifyImage(maskWithCurrentSegment, invertedSegment, vtkOrientedImageDataResample::OPERATION_MINIMUM);
      }

    // If we need to the modifier labelmap, make a copy to not modify the input
    vtkOrientedImageDataResample::ApplyImageMask(modifierLabelmap, maskWithCurrentSegment, m_EraseValue, true);

    if (segmentLayerLabelmap && modificationMode == qSlicerSegmentEditorAbstractEffect::ModificationModeSet)
      {
    
    
      // If modification mode is "set", we don't want to erase the existing labelmap outside of the mask region,
      // so we need to add it to the modifier labelmap
      vtkNew<vtkImageThreshold> segmentThreshold;
      segmentThreshold->SetInputData(segmentLayerLabelmap);
      segmentThreshold->SetInValue(m_FillValue);
      segmentThreshold->SetOutValue(m_EraseValue);
      segmentThreshold->ReplaceInOn();
      segmentThreshold->ThresholdBetween(segment->GetLabelValue(), segment->GetLabelValue());
      segmentThreshold->SetOutputScalarTypeToUnsignedChar();
      segmentThreshold->Update();

      int segmentThresholdExtent[6] = {
    
     0, -1, 0, -1, 0, -1 };
      segmentThreshold->GetOutput()->GetExtent(segmentThresholdExtent);
      if (segmentThresholdExtent[0] <= segmentThresholdExtent[1]
        && segmentThresholdExtent[2] <= segmentThresholdExtent[3]
        && segmentThresholdExtent[4] <= segmentThresholdExtent[5])
        {
    
    
        vtkNew<vtkOrientedImageData> segmentOutsideMask;
        segmentOutsideMask->ShallowCopy(segmentThreshold->GetOutput());
        segmentOutsideMask->CopyDirections(segmentLayerLabelmap);
        vtkOrientedImageDataResample::ModifyImage(segmentOutsideMask, maskImage, vtkOrientedImageDataResample::OPERATION_MINIMUM);
        vtkOrientedImageDataResample::ModifyImage(modifierLabelmap, segmentOutsideMask, vtkOrientedImageDataResample::OPERATION_MAXIMUM);
        }
      }
    }

  // Copy the temporary padded modifier labelmap to the segment.
  // Mask and threshold was already applied on modifier labelmap at this point if requested.
  const int* extent = modificationExtent;
  if (extent[0]>extent[1] || extent[2]>extent[3] || extent[4]>extent[5])
    {
    
    
    // invalid extent, it means we have to work with the entire modifier labelmap
    extent = nullptr;
    }

  std::vector<std::string> allSegmentIDs;
  segmentationNode->GetSegmentation()->GetSegmentIDs(allSegmentIDs);
  // remove selected segment, that is already handled
  allSegmentIDs.erase(std::remove(allSegmentIDs.begin(), allSegmentIDs.end(), segmentID), allSegmentIDs.end());

  std::vector<std::string> visibleSegmentIDs;
  vtkMRMLSegmentationDisplayNode* displayNode = vtkMRMLSegmentationDisplayNode::SafeDownCast(segmentationNode->GetDisplayNode());
  if (displayNode)
    {
    
    
    for (std::vector<std::string>::iterator segmentIDIt = allSegmentIDs.begin(); segmentIDIt != allSegmentIDs.end(); ++segmentIDIt)
      {
    
    
      if (displayNode->GetSegmentVisibility(*segmentIDIt))
        {
    
    
        visibleSegmentIDs.push_back(*segmentIDIt);
        }
      }
    }

  std::vector<std::string> segmentIDsToOverwrite;
  switch (this->parameterSetNode()->GetOverwriteMode())
    {
    
    
    case vtkMRMLSegmentEditorNode::OverwriteNone:
      // nothing to overwrite
      break;
    case vtkMRMLSegmentEditorNode::OverwriteVisibleSegments:
      segmentIDsToOverwrite = visibleSegmentIDs;
      break;
    case vtkMRMLSegmentEditorNode::OverwriteAllSegments:
      segmentIDsToOverwrite = allSegmentIDs;
      break;
    }

  if (bypassMasking)
    {
    
    
    segmentIDsToOverwrite.clear();
    }

  std::vector<std::string> sharedSegmentIDs;
  segmentationNode->GetSegmentation()->GetSegmentIDsSharingBinaryLabelmapRepresentation(segmentID, sharedSegmentIDs, false);

  std::vector<std::string> segmentsToErase;
  for (std::string segmentIDToOverwrite : segmentIDsToOverwrite)
    {
    
    
    std::vector<std::string>::iterator foundSegmentIDIt = std::find(sharedSegmentIDs.begin(), sharedSegmentIDs.end(), segmentIDToOverwrite);
    if (foundSegmentIDIt == sharedSegmentIDs.end())
      {
    
    
      segmentsToErase.push_back(segmentIDToOverwrite);
      }
    }

  // Create inverted binary labelmap
  vtkSmartPointer<vtkImageThreshold> inverter = vtkSmartPointer<vtkImageThreshold>::New();
  inverter->SetInputData(modifierLabelmap);
  inverter->SetInValue(VTK_UNSIGNED_CHAR_MAX);
  inverter->SetOutValue(m_EraseValue);
  inverter->ThresholdByLower(0);
  inverter->SetOutputScalarTypeToUnsignedChar();

  if (modificationMode == qSlicerSegmentEditorAbstractEffect::ModificationModeSet)
    {
    
    
    vtkSmartPointer<vtkImageThreshold> segmentInverter = vtkSmartPointer<vtkImageThreshold>::New();
    segmentInverter->SetInputData(segment->GetRepresentation(segmentationNode->GetSegmentation()->GetMasterRepresentationName()));
    segmentInverter->SetInValue(m_EraseValue);
    segmentInverter->SetOutValue(VTK_UNSIGNED_CHAR_MAX);
    segmentInverter->ReplaceInOn();
    segmentInverter->ThresholdBetween(segment->GetLabelValue(), segment->GetLabelValue());
    segmentInverter->SetOutputScalarTypeToUnsignedChar();
    segmentInverter->Update();
    vtkNew<vtkOrientedImageData> invertedModifierLabelmap;
    invertedModifierLabelmap->ShallowCopy(segmentInverter->GetOutput());
    vtkNew<vtkMatrix4x4> imageToWorldMatrix;
    modifierLabelmap->GetImageToWorldMatrix(imageToWorldMatrix.GetPointer());
    invertedModifierLabelmap->SetGeometryFromImageToWorldMatrix(imageToWorldMatrix.GetPointer());
    if (!vtkSlicerSegmentationsModuleLogic::SetBinaryLabelmapToSegment(
      invertedModifierLabelmap.GetPointer(), segmentationNode, segmentID, vtkSlicerSegmentationsModuleLogic::MODE_MERGE_MIN,
      nullptr, false, segmentIDsToOverwrite))
      {
    
    
      qCritical() << Q_FUNC_INFO << ": Failed to remove modifier labelmap from selected segment";
      }
    if (!vtkSlicerSegmentationsModuleLogic::SetBinaryLabelmapToSegment(
      modifierLabelmap, segmentationNode, segmentID, vtkSlicerSegmentationsModuleLogic::MODE_MERGE_MASK, extent, false, segmentIDsToOverwrite))
      {
    
    
      qCritical() << Q_FUNC_INFO << ": Failed to add modifier labelmap to selected segment";
      }
    }
  else if (modificationMode == qSlicerSegmentEditorAbstractEffect::ModificationModeAdd)
    {
    
    
    if (!vtkSlicerSegmentationsModuleLogic::SetBinaryLabelmapToSegment(
      modifierLabelmap, segmentationNode, segmentID, vtkSlicerSegmentationsModuleLogic::MODE_MERGE_MASK, extent, false, segmentIDsToOverwrite))
      {
    
    
      qCritical() << Q_FUNC_INFO << ": Failed to add modifier labelmap to selected segment";
      }
    }
  else if (modificationMode == qSlicerSegmentEditorAbstractEffect::ModificationModeRemove
    || modificationMode == qSlicerSegmentEditorAbstractEffect::ModificationModeRemoveAll)
    {
    
    
    inverter->Update();
    vtkNew<vtkOrientedImageData> invertedModifierLabelmap;
    invertedModifierLabelmap->ShallowCopy(inverter->GetOutput());
    vtkNew<vtkMatrix4x4> imageToWorldMatrix;
    modifierLabelmap->GetImageToWorldMatrix(imageToWorldMatrix.GetPointer());
    invertedModifierLabelmap->SetGeometryFromImageToWorldMatrix(imageToWorldMatrix.GetPointer());
    if (!vtkSlicerSegmentationsModuleLogic::SetBinaryLabelmapToSegment(
      invertedModifierLabelmap.GetPointer(), segmentationNode, segmentID, vtkSlicerSegmentationsModuleLogic::MODE_MERGE_MIN,
      extent, false, segmentIDsToOverwrite))
      {
    
    
      qCritical() << Q_FUNC_INFO << ": Failed to remove modifier labelmap from selected segment";
      }
    }

  if (segment)
    {
    
    
    if (vtkSlicerSegmentationsModuleLogic::GetSegmentStatus(segment) == vtkSlicerSegmentationsModuleLogic::NotStarted)
      {
    
    
      vtkSlicerSegmentationsModuleLogic::SetSegmentStatus(segment, vtkSlicerSegmentationsModuleLogic::InProgress);
      }
    }

  if (!segmentsToErase.empty() &&
     ( modificationMode == qSlicerSegmentEditorAbstractEffect::ModificationModeSet
    || modificationMode == qSlicerSegmentEditorAbstractEffect::ModificationModeAdd
    || modificationMode == qSlicerSegmentEditorAbstractEffect::ModificationModeRemoveAll))
    {
    
    
    inverter->Update();
    vtkNew<vtkOrientedImageData> invertedModifierLabelmap;
    invertedModifierLabelmap->ShallowCopy(inverter->GetOutput());
    vtkNew<vtkMatrix4x4> imageToWorldMatrix;
    modifierLabelmap->GetImageToWorldMatrix(imageToWorldMatrix.GetPointer());
    invertedModifierLabelmap->SetGeometryFromImageToWorldMatrix(imageToWorldMatrix.GetPointer());

    std::map<vtkDataObject*, bool> erased;
    for (std::string eraseSegmentID : segmentsToErase)
      {
    
    
      vtkSegment* currentSegment = segmentationNode->GetSegmentation()->GetSegment(eraseSegmentID);
      vtkDataObject* dataObject = currentSegment->GetRepresentation(vtkSegmentationConverter::GetBinaryLabelmapRepresentationName());
      if (erased[dataObject])
        {
    
    
        continue;
        }
      erased[dataObject] = true;

      vtkOrientedImageData* currentLabelmap = vtkOrientedImageData::SafeDownCast(dataObject);

      std::vector<std::string> dontOverwriteIDs;
      std::vector<std::string> currentSharedIDs;
      segmentationNode->GetSegmentation()->GetSegmentIDsSharingBinaryLabelmapRepresentation(eraseSegmentID, currentSharedIDs, true);
      for (std::string sharedSegmentID : currentSharedIDs)
        {
    
    
        if (std::find(segmentsToErase.begin(), segmentsToErase.end(), sharedSegmentID) == segmentsToErase.end())
          {
    
    
          dontOverwriteIDs.push_back(sharedSegmentID);
          }
        }

      vtkSmartPointer<vtkOrientedImageData> invertedModifierLabelmap2 = invertedModifierLabelmap;
      if (dontOverwriteIDs.size() > 0)
        {
    
    
        invertedModifierLabelmap2 = vtkSmartPointer<vtkOrientedImageData>::New();
        invertedModifierLabelmap2->DeepCopy(invertedModifierLabelmap);

        vtkNew<vtkOrientedImageData> maskImage;
        maskImage->CopyDirections(currentLabelmap);
        for (std::string dontOverwriteID : dontOverwriteIDs)
          {
    
    
          vtkSegment* dontOverwriteSegment = segmentationNode->GetSegmentation()->GetSegment(dontOverwriteID);
          vtkNew<vtkImageThreshold> threshold;
          threshold->SetInputData(currentLabelmap);
          threshold->ThresholdBetween(dontOverwriteSegment->GetLabelValue(), dontOverwriteSegment->GetLabelValue());
          threshold->SetInValue(1);
          threshold->SetOutValue(0);
          threshold->SetOutputScalarTypeToUnsignedChar();
          threshold->Update();
          maskImage->ShallowCopy(threshold->GetOutput());
          vtkOrientedImageDataResample::ApplyImageMask(invertedModifierLabelmap2, maskImage, VTK_UNSIGNED_CHAR_MAX, true);
          }
        }

      if (!vtkSlicerSegmentationsModuleLogic::SetBinaryLabelmapToSegment(
        invertedModifierLabelmap2, segmentationNode, eraseSegmentID, vtkSlicerSegmentationsModuleLogic::MODE_MERGE_MIN, extent, true, segmentIDsToOverwrite))
        {
    
    
        qCritical() << Q_FUNC_INFO << ": Failed to set modifier labelmap to segment " << (eraseSegmentID.c_str());
        }
      }
    }
  else if (modificationMode == qSlicerSegmentEditorAbstractEffect::ModificationModeRemove)
    {
    
    
    // In general, we don't try to "add back" areas to other segments when an area is removed from the selected segment.
    // The only exception is when we draw inside one specific segment. In that case erasing adds to the mask segment. It is useful
    // for splitting a segment into two by painting.
    if (this->parameterSetNode()->GetMaskMode() == vtkMRMLSegmentEditorNode::PaintAllowedInsideSingleSegment
      && this->parameterSetNode()->GetMaskSegmentID())
      {
    
    
      if (!vtkSlicerSegmentationsModuleLogic::SetBinaryLabelmapToSegment(
        modifierLabelmap, segmentationNode, this->parameterSetNode()->GetMaskSegmentID(), vtkSlicerSegmentationsModuleLogic::MODE_MERGE_MASK,
        extent, false, segmentIDsToOverwrite))
        {
    
    
        qCritical() << Q_FUNC_INFO << ": Failed to remove modifier labelmap from segment " << this->parameterSetNode()->GetMaskSegmentID();
        }
      }
    }

  // Make sure the segmentation node is under the same parent as the master volume
  vtkMRMLScalarVolumeNode* masterVolumeNode = d->ParameterSetNode->GetMasterVolumeNode();
  if (masterVolumeNode)
    {
    
    
    vtkMRMLSubjectHierarchyNode* shNode = vtkMRMLSubjectHierarchyNode::GetSubjectHierarchyNode(d->ParameterSetNode->GetScene());
    if (shNode)
      {
    
    
      vtkIdType segmentationId = shNode->GetItemByDataNode(segmentationNode);
      vtkIdType masterVolumeShId = shNode->GetItemByDataNode(masterVolumeNode);
      if (segmentationId && masterVolumeShId)
        {
    
    
        shNode->SetItemParent(segmentationId, shNode->GetItemParent(masterVolumeShId));
        }
      else
        {
    
    
        qCritical() << Q_FUNC_INFO << ": Subject hierarchy items not found for segmentation or master volume";
        }
      }
    }
}

猜你喜欢

转载自blog.csdn.net/juluwangriyue/article/details/125293738