AndreAhmed
(andreahmed)
February 23, 2023, 10:41pm
1
hello,
I’m following the post here How to delete/hide specific points from vtkvolume?
I use the converted closed surface and that’s the result as polydata
Now I want to color the voxels under the lasso to a specific color
I’m using the exact code in github for just constructing the lasso and 3D closed surface. But don’t know how to convert the closed surface into binary image ? but If I managed to convert that, how do I color specific voxels that are under the Lasso (Selected by it )
AndreAhmed
(andreahmed)
February 24, 2023, 4:49am
2
Here is the pipeline:
// Construct polydata
vtkNew<vtkPolyData> closedSurfacePolyData;
closedSurfacePolyData->SetPoints(closedSurfacePoints.GetPointer());
closedSurfacePolyData->SetStrips(closedSurfaceStrips.GetPointer());
closedSurfacePolyData->SetPolys(closedSurfacePolys.GetPointer());
this->BrushPolyDataNormals = vtkSmartPointer<vtkPolyDataNormals>::New();
this->BrushPolyDataNormals->AutoOrientNormalsOn();
this->BrushPolyDataNormals->SetInputData(closedSurfacePolyData.GetPointer());
this->BrushPolyDataNormals->Update();
finalPolyData->SetPoints(closedSurfacePoints.GetPointer());
finalPolyData->SetStrips(closedSurfaceStrips.GetPointer());
finalPolyData->SetPolys(closedSurfacePolys.GetPointer());
ActorFinalPolyData->VisibilityOn();
this->WorldToModifierLabelmapIjkTransformer = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
this->WorldToModifierLabelmapIjkTransform = vtkSmartPointer<vtkTransform>::New();
this->WorldToModifierLabelmapIjkTransformer->SetTransform(this->WorldToModifierLabelmapIjkTransform);
this->WorldToModifierLabelmapIjkTransformer->SetInputConnection(this->BrushPolyDataNormals->GetOutputPort());
this->BrushPolyDataToStencil = vtkSmartPointer<vtkPolyDataToImageStencil>::New();
this->BrushPolyDataToStencil->SetOutputSpacing(mVolume->GetXSpacing(), mVolume->GetYSpacing(), mVolume->GetZSpacing());
this->BrushPolyDataToStencil->SetOutputOrigin(mVolume->GetOrigin().x(), mVolume->GetOrigin().y(), mVolume->GetOrigin().z());
this->BrushPolyDataToStencil->SetOutputWholeExtent(0, mVolume->GetWidth(), 0, mVolume->GetHeight(), 0, mVolume->GetDepth());
this->BrushPolyDataToStencil->SetInputConnection(this->WorldToModifierLabelmapIjkTransformer->GetOutputPort());
this->BrushPolyDataToStencil->Update();
vtkImageStencilData* stencilData = this->BrushPolyDataToStencil->GetOutput();
int stencilExtent[6] = { 0, -1, 0, -1, 0, -1 };
stencilData->GetExtent(stencilExtent);
vtkNew<vtkImageStencilToImage> stencilToImage;
stencilToImage->SetInputConnection(this->BrushPolyDataToStencil->GetOutputPort());
stencilToImage->SetInsideValue(1);
stencilToImage->SetOutsideValue(0);
stencilToImage->Update();
vtkNew<vtkPNGWriter> writer;
writer->SetFileName("selection.png");
writer->SetInputConnection(stencilToImage->GetOutputPort());
writer->Write();
AndreAhmed
(andreahmed)
February 24, 2023, 12:02pm
3
@lassoan
Hello I hope you are doing fine. Can you help me with that issue please ?
AndreAhmed
(andreahmed)
February 24, 2023, 12:12pm
4
I also noticed something weird, when I constructed the closed_surface polydata, it’s drawen as 3D Lasso, but when I change the zooming of camera, or rotate the scene, the closed surface gets distored, and gets disappearing out of the scene
lassoan
(Andras Lasso)
February 24, 2023, 12:18pm
5
AndreAhmed
(andreahmed)
February 24, 2023, 12:19pm
6
@lassoan
Thanks for your quick reply. But can you give me an intrepretation to the above problem of the distorion and disappearing?
2. How the mask under the lasso should be created ?
Sorry about disturbing you
AndreAhmed
(andreahmed)
February 24, 2023, 12:55pm
7
@lassoan Hello Hope you’re doing fine.
This is the current pipeline, but all I get is black image that is written to disc. Still I have problem of distortionn and disappearing of 3D Lasso while moving the camera.
vtkNew<vtkPolyData> closedSurfacePolyData;
closedSurfacePolyData->SetPoints(closedSurfacePoints.GetPointer());
closedSurfacePolyData->SetStrips(closedSurfaceStrips.GetPointer());
closedSurfacePolyData->SetPolys(closedSurfacePolys.GetPointer());
this->BrushPolyDataNormals = vtkSmartPointer<vtkPolyDataNormals>::New();
this->BrushPolyDataNormals->AutoOrientNormalsOn();
this->BrushPolyDataNormals->SetInputData(closedSurfacePolyData.GetPointer());
this->BrushPolyDataNormals->Update();
this->WorldToModifierLabelmapIjkTransformer = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
this->WorldToModifierLabelmapIjkTransform = vtkSmartPointer<vtkTransform>::New();
this->WorldToModifierLabelmapIjkTransformer->SetTransform(this->WorldToModifierLabelmapIjkTransform);
this->WorldToModifierLabelmapIjkTransformer->SetInputConnection(this->BrushPolyDataNormals->GetOutputPort());
this->BrushPolyDataToStencil = vtkSmartPointer<vtkPolyDataToImageStencil>::New();
this->BrushPolyDataToStencil->SetOutputSpacing(mVolume->GetXSpacing(), mVolume->GetYSpacing(), mVolume->GetZSpacing());
this->BrushPolyDataToStencil->SetOutputOrigin(mVolume->GetOrigin().x(), mVolume->GetOrigin().y(), mVolume->GetOrigin().z());
this->BrushPolyDataToStencil->SetOutputWholeExtent(0, mVolume->GetWidth(), 0, mVolume->GetHeight(), 0, mVolume->GetDepth());
this->BrushPolyDataToStencil->SetInputConnection(this->WorldToModifierLabelmapIjkTransformer->GetOutputPort());
this->BrushPolyDataToStencil->Update();
vtkNew<vtkImageStencilToImage> stencilToImage;
stencilToImage->SetInputConnection(this->BrushPolyDataToStencil->GetOutputPort());
stencilToImage->SetInsideValue(0);
stencilToImage->SetOutsideValue(1);
stencilToImage->Update();
vtkNew<vtkImageImport> imageImport;
imageImport->SetOutput(stencilToImage->GetOutput());
unsigned int xSize = mVolume->GetXSize();
unsigned int ySize = mVolume->GetYSize();
unsigned int zSize = mVolume->GetZSize();
auto origin = mVolume->GetOrigin();
double spacing[3]{
mVolume->GetXSpacing() * 10.0,
mVolume->GetYSpacing() * 10.0,
mVolume->GetZSpacing() * 10.0
};
imageImport->SetDataSpacing(spacing);
imageImport->SetDataOrigin(
origin.x() * 10.0,
origin.y() * 10.0,
origin.z() * 10.0
);
imageImport->SetDataExtent(
0, xSize - 1,
0, ySize - 1,
0, zSize - 1);
imageImport->SetWholeExtent(
0, xSize - 1,
0, ySize - 1,
0, zSize - 1);
short* data = mVolume->GetData().get();
imageImport->SetDataScalarTypeToUnsignedShort() ;
imageImport->SetImportVoidPointer(data);
imageImport->Update();
AndreAhmed
(andreahmed)
February 24, 2023, 1:29pm
8
@lassoan
Here is an image of what I mean, if you notice, the RED cone is the lasso. After I rotate the camera it appears like that, and it seems its not projected on the volume itself.
AndreAhmed
(andreahmed)
February 24, 2023, 6:08pm
9
@lassoan I hope you can help me
AndreAhmed
(andreahmed)
February 24, 2023, 6:29pm
10
This is the current pipeline, getting volume data, and overwrite it. closedSurface, is lasso3D from the code in slicer.Slicer/qSlicerSegmentEditorScissorsEffect.cxx at 83a84a0f72baa0fcd1bb3653cedae7b02ca3bd1b · Slicer/Slicer · GitHub
finalPolyData->SetPoints(closedSurfacePoints.GetPointer());
finalPolyData->SetStrips(closedSurfaceStrips.GetPointer());
finalPolyData->SetPolys(closedSurfacePolys.GetPointer());
vtkNew<vtkImageData> whiteImage;
double bounds[6];
finalPolyData->GetBounds(bounds);
double spacing[3]; // desired volume spacing
spacing[0] = 0.5;
spacing[1] = 0.5;
spacing[2] = 0.5;
whiteImage->SetSpacing(spacing);
// compute dimensions
int dim[3];
for (int i = 0; i < 3; i++)
{
dim[i] = static_cast<int>(
ceil((bounds[i * 2 + 1] - bounds[i * 2]) / spacing[i]));
}
whiteImage->SetDimensions(dim);
whiteImage->SetExtent(0, dim[0] - 1, 0, dim[1] - 1, 0, dim[2] - 1);
double origin[3];
origin[0] = bounds[0] + spacing[0] / 2;
origin[1] = bounds[2] + spacing[1] / 2;
origin[2] = bounds[4] + spacing[2] / 2;
whiteImage->SetOrigin(origin);
whiteImage->AllocateScalars(VTK_UNSIGNED_CHAR, 1);
// fill the image with foreground voxels:
unsigned char inval = 255;
unsigned char outval = 0;
vtkIdType count = whiteImage->GetNumberOfPoints();
for (vtkIdType i = 0; i < count; ++i)
{
whiteImage->GetPointData()->GetScalars()->SetTuple1(i, inval);
}
// polygonal data --> image stencil:
vtkNew<vtkPolyDataToImageStencil> pol2stenc;
pol2stenc->SetInputData(finalPolyData);
pol2stenc->SetOutputOrigin(origin);
pol2stenc->SetOutputSpacing(spacing);
pol2stenc->SetOutputWholeExtent(whiteImage->GetExtent());
pol2stenc->Update();
// cut the corresponding white image and set the background:
imgstenc->SetInputData(whiteImage);
imgstenc->SetStencilConnection(pol2stenc->GetOutputPort());
imgstenc->ReverseStencilOff();
imgstenc->SetBackgroundValue(outval);
imgstenc->Update();
//imageMapper->SetInputConnection(imgstenc->GetOutputPort());
vtkImageData* image = vtkImageData::New();
//GetStencilDataAsImageData(imgstenc->GetStencil(), image);
short* labelData = mVolume->GetData().get();
//#pragma omp parallel for
for (int z = 0; z < mVolume->GetDepth(); z++)
{
for (int y = 0; y < mVolume->GetHeight(); y++)
{
for (int x = 0; x < mVolume->GetWidth(); x++)
{
if (imgstenc->GetStencil()->IsInside(x, y, z))
{
int image_linear_index = z * mVolume->GetWidth() * mVolume->GetHeight() + y * mVolume->GetWidth() + x;
labelData[image_linear_index] = 0;
}
}
}
}