[vtkusers] High memory cost of vtkDecimatePro for 3D model generation from DICOM series

David Gobbi david.gobbi at gmail.com
Thu Mar 17 21:38:00 EDT 2016


Hi Liu Peng,

Now that I have seen your code, you should definitely remove
vtkImageThreshold and set the vtkMarchingCubes isovalue to around 1000.
I'm certain that vtkImageThreshold does nothing useful in this pipeline.

For vtkReverseSense, see the documentation page for the class for an
explanation of what it does.  I wrote that example code because I thought
you might need an upper and a lower threshold, but now that I have seen
your code, I think you only need one threshold (just the lower threshold).
So you can ignore the code that I sent.

As for the camera, it is usually a good idea to point it at the center of
the volume.  I do not always like VTK's default camera position, so I when
I write VTK code, I almost always set the camera position myself.

 - David



On Thu, Mar 17, 2016 at 7:07 PM, Liu_tj <tjlp at netease.com> wrote:

> Hi, David,
>
> Below is my present C# code.You can see that I reset the camera position,
> otherwise after rendering, the 3D model is not at the window center, I have
> to pan it, any recommendation for the position issue also?
>
>       private void Display(vtkRenderWindow aRenderWindow, vtkImageData
> aData)
>         {
>             vtkImageData volume = vtkImageData.New();
>             double isoValue = 1;
>             volume.DeepCopy(aData);
>             vtkImageThreshold image_threshold = vtkImageThreshold.New();
>             image_threshold.SetInputData(volume);
>             image_threshold.ThresholdBetween(1000,20000);
>             image_threshold.ReplaceInOn();
>             image_threshold.SetInValue(1);
>             image_threshold.ReplaceOutOn();
>             image_threshold.SetOutValue(0);
>             image_threshold.Update();
>
>             vtkMarchingCubes surface = vtkMarchingCubes.New();
>             surface.SetInputData(image_threshold.GetOutput());
>             surface.ComputeNormalsOn();
>             surface.ComputeScalarsOn();
>             surface.SetValue(0, isoValue);
>             surface.Update();
>
>             vtkPolyData marched = vtkPolyData.New();
>             marched.DeepCopy(surface.GetOutput());
>
>             long pointcnt = marched.GetNumberOfPoints();
>
>             // Decimation to reduce the number of triangles
>             vtkDecimatePro decimator = vtkDecimatePro.New();
>             decimator.SetInputData(marched);
>             decimator.SetTargetReduction(0.5);
>             decimator.SetPreserveTopology(1);
>             decimator.Update();
>             //Smoothing
>            vtkSmoothPolyDataFilter smoother =
> vtkSmoothPolyDataFilter.New();
>             smoother.SetInputData(decimator.GetOutput());
>             smoother.SetNumberOfIterations(5);
>             smoother.SetFeatureAngle(60);
>             smoother.SetRelaxationFactor(0.05);
>             smoother.FeatureEdgeSmoothingOff();
>
>             //Select the largest region
>             vtkPolyDataConnectivityFilter connectivityFilter =
> vtkPolyDataConnectivityFilter.New();
>
> connectivityFilter.SetInputConnection(decimator.GetOutputPort());
>             connectivityFilter.ScalarConnectivityOff();
>             connectivityFilter.SetExtractionModeToLargestRegion();
>             connectivityFilter.Update();
>
>             // Create final polygon mesh
>             vtkPolyData mesh = vtkPolyData.New();
>             mesh.ShallowCopy(connectivityFilter.GetOutput());
>
>             // Visualization
>             vtkRenderer renderer =
> aRenderWindow.GetRenderers().GetFirstRenderer();
>             renderer.SetBackground(0.0, 0.0, 0.0);
>
>             vtkPolyDataMapper mapper = vtkPolyDataMapper.New();
>             mapper.SetInputData(mesh);
>             mapper.ScalarVisibilityOff();
>
>             vtkActor actor = vtkActor.New();
>             actor.SetMapper(mapper);
>             renderer.AddActor(actor);
>
>             vtkCamera camera = renderer.MakeCamera();
>             camera.SetPosition(-500.0, 245.5, 122.0);
>             camera.SetFocalPoint(301.0, 245.5, 122.0);
>             camera.SetViewAngle(30.0);
>             camera.SetRoll(-90.0);
>             renderer.SetActiveCamera(camera);
>
>             aRenderWindow.Render();
>
>             vtkRenderWindowInteractor interactor  =
> aRenderWindow.GetInteractor();
>             interactor.Start();
>         }
>
>
>
> 在2016-03-17,"David Gobbi" <david.gobbi at gmail.com> 写道:
>
> -----原始邮件-----
> *发件人:*"David Gobbi" <david.gobbi at gmail.com>
> *发送时间:*2016年03月17日 星期四
> *收件人:*"Liu_tj" <tjlp at netease.com>
> *抄送:*"vtkusers" <vtkusers at vtk.org>
> *主题:*Re: Re: Re: [vtkusers] High memory cost of vtkDecimatePro for 3D
> model generation from DICOM series
>
>
> And I should add: if it is necessary to use a range (instead of just a
> lower threshold), then the pipeline can use vtkMarchingCubes twice:
>
> vtkSmartPointer<vtkMarchingCubes> cubes1 =
> vtkSmartPointer<vtkMarchingCubes>::New();
> cubes1->SetInputData(imagedata);
> cubes1->SetValue(0, lowerThreshold);
>
> vtkSmartPointer<vtkMarchingCubes> cubes2 =
> vtkSmartPointer<vtkMarchingCubes>::New();
> cubes2->SetInputData(imagedata);
> cubes2->SetValue(0, upperThreshold);
>
> vtkSmartPointer<vtkReverseSense> reverse =
> vtkSmartPointer<vtkReverseSense>::New();
> reverse->SetInputConnection(cubes2->GetOutputPort());
>
> vtkSmartPointer<vtkAppendPolyData> surface =
> vtkSmartPointer<vtkAppendPolyData>::New();
> surface->SetInputConnection(cubes1->GetOutputPort());
> surface->AddInputConnection(cubes2->GetOutputPort());
> surface->Update();
>
>
> On Thu, Mar 17, 2016 at 6:06 AM, David Gobbi <david.gobbi at gmail.com>
> wrote:
>
>> Hi Liu Peng,
>>
>> For creating a model, it is common to allow the user to set just a lower
>> threshold (rather than a range), and to use the lower threshold as the
>> isovalue.  If you send the code for the whole pipeline, that might help.
>>
>>  - David
>>
>> On Wed, Mar 16, 2016 at 11:27 PM, Liu_tj <tjlp at netease.com> wrote:
>>
>>> Hi, David,
>>>
>>> If I don't use vtkImageThreshol, how to generate 3D model from the
>>> points whose grayscale is in some specific range? This range can be changed
>>> by the user.
>>>
>>> Thanks
>>> Liu Peng
>>>
>>> 在2016-03-17,"David Gobbi" <david.gobbi at gmail.com> 写道:
>>>
>>> -----原始邮件-----
>>> *发件人:*"David Gobbi" <david.gobbi at gmail.com>
>>> *发送时间:*2016年03月17日 星期四
>>> *收件人:*"Liu_tj" <tjlp at netease.com>
>>> *抄送:*"vtkusers" <vtkusers at vtk.org>
>>> *主题:*Re: Re: [vtkusers] High memory cost of vtkDecimatePro for 3D model
>>> generation from DICOM series
>>>
>>>
>>> On Wed, Mar 16, 2016 at 10:35 PM, Liu_tj <tjlp at netease.com> wrote:
>>>
>>>> Hi,David,
>>>>
>>>> If using vtkImageThreshold before vtkMarchingCubes is not a good
>>>> option, what other better way do you have?
>>>>
>>>
>>> The output of the reader should go directly into vtkMarchingCubes.
>>>
>>>
>>>> Beside, for the isovalue, I try 2,3,4 and marched->GetNumberOfPoints()
>>>> return 0, only isovalue is 1 and marched->GetNumberOfPoints() return a
>>>> number greater than 0. I have no idea this is relating to the DICOM series
>>>> or other problem.
>>>>
>>>
>>> If you remove vtkImageThreshold, and put the output of the reader
>>> directly into vtkMarchingCubes, then you should be able to use an isovalue
>>> somewhere between 100 and 2000 and get a good result.
>>>
>>> Also, after vtkMarchingCubes, you can use vtkConnectivityFilter to clean
>>> up the polydata before you decimate it.
>>>
>>>  - David
>>>
>>>
>>>
>>>
>>>
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://public.kitware.com/pipermail/vtkusers/attachments/20160317/805af56c/attachment.html>


More information about the vtkusers mailing list