use vtkPolyDataToImageStencil to colo a custom made volume voxels

Hello,
I created a lasso a 3D polydata, then I used vtkPolyDataToImageStencil to convert it to ImageStencil.
I have a custom volume and I have it’s short data, it has width,height,depth. Now I want to color the voxels in the volume that are marked by the polydata.
I check if the value of current image stencil is white, then I mark the voxel as white but it doesn’t work.
I see the result as a cube!

and that’s the result after applying lasso

FULL Pipeline:

finalPolyData->SetPoints(closedSurfacePoints.GetPointer());
finalPolyData->SetStrips(closedSurfaceStrips.GetPointer());
finalPolyData->SetPolys(closedSurfacePolys.GetPointer());
//ActorFinalPolyData->VisibilityOn();


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();


vtkNew<vtkMetaImageWriter> imageWriter;
imageWriter->SetFileName("labelImage.mhd");
imageWriter->SetInputConnection(imgstenc->GetOutputPort());
imageWriter->Write();

DVertex origin_ = mVolume->GetOrigin();
double maSpacing[3]; /// Image spacing
maSpacing[0] = mVolume->GetXSpacing();
maSpacing[1] = mVolume->GetYSpacing();
maSpacing[2] = mVolume->GetZSpacing();
auto mask = std::make_shared<DNA_Mask>(140, mVolume->GetWidth(), mVolume->GetHeight(), mVolume->GetDepth());
mask->SetSpacing(maSpacing[0], maSpacing[1], maSpacing[2]);
mask->SetOrigin(origin_);

vtkImageData* data = imgstenc->GetOutput();
int dims[3];
data->GetDimensions(dims);

//#pragma omp parallel for
short* volumeData = mVolume->GetData().get();
for (int z = 0; z < dims[2]; z++)
{
	for (int y = 0; y < dims[1]; y++)
	{
		for (int x = 0; x < dims[0]; x++)
		{
			unsigned char* pPixel = static_cast<unsigned char*>(data->GetScalarPointer(x, y, z));
			if (*pPixel == 255)
			{	
				int image_linear_index = z * dims[0] * dims[1] + y * dims[0] + x;

				volumeData[image_linear_index] = 255;
			}
		}
	}
}

@lassoan Can you help please ? I’m sorry about disturbing you.
@dgobbi

You can find the full implementation of this feature in 3D Slicer. You can freely copy any parts or the whole feature to your application. If you have difficulties with this then you might consider building your application based on 3D Slicer (you can customize every bits of the application and/or you can extend with additional features) instead of reimplementing its features. 3D Slicer is developed to be an application framework for custom medical image computing applications and it is actually a thin wrapper over VTK, ITK and Qt.

If you just want to implement “something simple” (you know exactly that you only need a few simple features and you are sure you will never need more) then I would recommend to implement it as a web application (using VTK.js, maybe using OHIF3), as users will not be willing to download and install a desktop application for doing a few simple things.

@lassoan
Thanks for your support. I actually copied the closed surface generation from Slicer. But it’s very hard to follow up what it does after that on that closed surface ? The problem is my volume has shorts of voxels, and I need to modifiy them to color them individuly. Can you help with that please ?

@lassoan I have tried 3D Slicer now, the scissor module as you suggested but it doesn’t behave as what I need. What I need is the same, a Lasso that color the voxels on the 3D Volume itself, not in 2D Slices.

After you created the segment with the Scissors tool, you can use Mask volume tool to blank out the volume inside or outside the segment.