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;
}
其中的矩阵转换还是不清楚,可以下班后,拿来测试一下问题
1038

被折叠的 条评论
为什么被折叠?



