closedSurfaceTovtkimagedata

slicer3D :segment 文件夹中的vtkClosedSurfaceToBinaryLabelmapConversionRule

bool vtkClosedSurfaceToBinaryLabelmapConversionRule::Convert(vtkSegment* segment)
{
  vtkSmartPointer<vtkOrientedImageData> outputGeometryLabelmap = vtkOrientedImageData::SafeDownCast(
    segment->GetRepresentation(this->GetTargetRepresentationName()));
  this->CreateTargetRepresentation(segment);

  // Check validity of source and target representation objects
  vtkPolyData* closedSurfacePolyData = vtkPolyData::SafeDownCast(segment->GetRepresentation(this->GetSourceRepresentationName()));
  if (!closedSurfacePolyData)
    {
    vtkErrorMacro("Convert: Source representation is not a poly data!");
    return false;
    }

  if (closedSurfacePolyData->GetNumberOfPoints() < 2 || closedSurfacePolyData->GetNumberOfCells() < 2)
    {
    vtkDebugMacro("Convert: Cannot create binary labelmap from surface with number of points: "
      << closedSurfacePolyData->GetNumberOfPoints() << " and number of cells: " << closedSurfacePolyData->GetNumberOfCells());
    return false;
    }

  vtkOrientedImageData* binaryLabelmap = vtkOrientedImageData::SafeDownCast(segment->GetRepresentation(this->GetTargetRepresentationName()));
  if (!binaryLabelmap)
    {
    vtkErrorMacro("Convert: Target representation is not an oriented image data!");
    return false;
    }

  // Setup output labelmap

  // Compute output labelmap geometry based on poly data, an reference image
  // geometry, and store the calculated geometry in output labelmap image data
  if (!this->UseOutputImageDataGeometry)
    {
    if (!this->CalculateOutputGeometry(closedSurfacePolyData, binaryLabelmap))
      {
      vtkErrorMacro("Convert: Failed to calculate output image geometry!");
      return false;
      }
    }
  else if (outputGeometryLabelmap)
    {
    std::string geometryString = vtkSegmentationConverter::SerializeImageGeometry(outputGeometryLabelmap);
    vtkSegmentationConverter::DeserializeImageGeometry(geometryString, binaryLabelmap, false);
    }

  // Allocate output image data
  binaryLabelmap->AllocateScalars(VTK_UNSIGNED_CHAR, 1);

  void* binaryLabelmapVoxelsPointer = binaryLabelmap->GetScalarPointerForExtent(binaryLabelmap->GetExtent());
  if (!binaryLabelmapVoxelsPointer)
    {
    vtkErrorMacro("Convert: Failed to allocate memory for output labelmap image!");
    return false;
    }
  else
    {
    // Set voxel values to 0
    int extent[6] = {0,-1,0,-1,0,-1};
    binaryLabelmap->GetExtent(extent);
    memset(binaryLabelmapVoxelsPointer, 0, ((extent[1]-extent[0]+1)*(extent[3]-extent[2]+1)*(extent[5]-extent[4]+1) *
      binaryLabelmap->GetScalarSize() * binaryLabelmap->GetNumberOfScalarComponents()));
    }

  // Perform conversion

  // Now the output labelmap image data contains the right geometry.
  // We need to apply inverse of geometry matrix to the input poly data so that we can perform
  // the conversion in IJK space, because the filters do not support oriented image data.
  vtkSmartPointer<vtkMatrix4x4> outputLabelmapImageToWorldMatrix = vtkSmartPointer<vtkMatrix4x4>::New();
  binaryLabelmap->GetImageToWorldMatrix(outputLabelmapImageToWorldMatrix);
  vtkSmartPointer<vtkTransform> inverseOutputLabelmapGeometryTransform = vtkSmartPointer<vtkTransform>::New();
  inverseOutputLabelmapGeometryTransform->SetMatrix(outputLabelmapImageToWorldMatrix);
  inverseOutputLabelmapGeometryTransform->Inverse();

  // Set geometry to identity for the volume so that we can perform the stencil operation in IJK space
  vtkSmartPointer<vtkMatrix4x4> identityMatrix = vtkSmartPointer<vtkMatrix4x4>::New();
  identityMatrix->Identity();
  binaryLabelmap->SetGeometryFromImageToWorldMatrix(identityMatrix);

  vtkSmartPointer<vtkTransformPolyDataFilter> transformPolyDataFilter =
    vtkSmartPointer<vtkTransformPolyDataFilter>::New();
  transformPolyDataFilter->SetInputData(closedSurfacePolyData);
  transformPolyDataFilter->SetTransform(inverseOutputLabelmapGeometryTransform);

  // Compute polydata normals
  vtkNew<vtkPolyDataNormals> normalFilter;
  normalFilter->SetInputConnection(transformPolyDataFilter->GetOutputPort());
  normalFilter->ConsistencyOn();

  // Make sure that we have a clean triangle polydata
  vtkNew<vtkTriangleFilter> triangle;
  triangle->SetInputConnection(normalFilter->GetOutputPort());

  // Convert to triangle strip
  vtkSmartPointer<vtkStripper> stripper=vtkSmartPointer<vtkStripper>::New();
  stripper->SetInputConnection(triangle->GetOutputPort());

  // Convert polydata to stencil
  vtkNew<vtkPolyDataToImageStencil> polyDataToImageStencil;
  polyDataToImageStencil->SetInputConnection(stripper->GetOutputPort());
  polyDataToImageStencil->SetOutputSpacing(binaryLabelmap->GetSpacing());
  polyDataToImageStencil->SetOutputOrigin(binaryLabelmap->GetOrigin());
  polyDataToImageStencil->SetOutputWholeExtent(binaryLabelmap->GetExtent());

  // Convert stencil to image
  vtkNew<vtkImageStencil> stencil;
  stencil->SetInputData(binaryLabelmap);
  stencil->SetStencilConnection(polyDataToImageStencil->GetOutputPort());
  stencil->ReverseStencilOn();
  // If the output labelmap was to required to be unsigned char, we could use the segment label value.
  // To ensure that the label value is < 255, we set it to 1. Collapsing the labelmaps during post-conversion may assign new a value regardless.
  stencil->SetBackgroundValue(DEFAULT_LABEL_VALUE); // General foreground value is 1 (background value because of reverse stencil)

  // Save result to output
  vtkNew<vtkImageCast> imageCast;
  imageCast->SetInputConnection(stencil->GetOutputPort());
  imageCast->SetOutputScalarTypeToUnsignedChar();
  imageCast->Update();
  binaryLabelmap->ShallowCopy(imageCast->GetOutput());

  // Restore geometry of the labelmap that we set to identity before conversion
  // (so that we can perform the stencil operations in IJK space)
  binaryLabelmap->SetGeometryFromImageToWorldMatrix(outputLabelmapImageToWorldMatrix);

  // Set segment value to 1
  segment->SetLabelValue(DEFAULT_LABEL_VALUE);

  return true;
}

其中的矩阵转换还是不清楚,可以下班后,拿来测试一下问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值