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

David Gobbi david.gobbi at gmail.com
Thu Mar 17 22:19:11 EDT 2016


You can segment an image with just one threshold (i.e. just the lower
threshold).  It is not necessary to set a range.

But, regardless, vtkMarchingCubes is designed to take a greyscale image as
input, not a binary image.

 - David


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

> Hi, David,
>
> The user scenario is that we allow the user to set segment threshold which
> is a grayscale range. So at the 2D DICOM view, the pixels which fall in
> this range will be shown by special color (I implement it with
> vtkLookupTableand vtkImageMapToColors); then the user can preview the 3D
> model generated by the points in this grayscale range.
>
> Thanks
>
>
> 在2016-03-18,"David Gobbi" <david.gobbi at gmail.com> 写道:
>
> -----原始邮件-----
> *发件人:*"David Gobbi" <david.gobbi at gmail.com>
> *发送时间:*2016年03月18日 星期五
> *收件人:*"Liu_tj" <tjlp at netease.com>
> *抄送:*"vtkusers" <vtkusers at vtk.org>
> *主题:*Re: Re: Re: Re: Re: [vtkusers] High memory cost of vtkDecimatePro
> for 3D model generation from DICOM series
>
>
> You only need one threshold to create a model from an image.
> Why do you let the user set two thresholds?
>
>
> On Thu, Mar 17, 2016 at 7:54 PM, Liu_tj <tjlp at netease.com> wrote:
>
>> Hi, David,
>>
>> If the user sets a upper value, what should we do?
>>
>> Thanks
>> Liu Peng
>>
>>
>>
>> 在2016-03-18,"David Gobbi" <david.gobbi at gmail.com> 写道:
>>
>> -----原始邮件-----
>> *发件人:*"David Gobbi" <david.gobbi at gmail.com>
>> *发送时间:*2016年03月18日 星期五
>> *收件人:*"Liu_tj" <tjlp at netease.com>
>> *抄送:*"vtkusers" <vtkusers at vtk.org>
>> *主题:*Re: Re: Re: Re: [vtkusers] High memory cost of vtkDecimatePro for
>> 3D model generation from DICOM series
>>
>>
>> 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/02726fb6/attachment.html>


More information about the vtkusers mailing list