I try it. And the generated Volumes are almost the same comparing only set isovalue to 1000 and set isovalue twice with 1000 and 2000.<br><div><br></div>
 <span>
 </span>
<br>      在2016-03-18,"David Gobbi" <david.gobbi@gmail.com> 写道:
        <blockquote id="isReplyContent" style="padding-left:1ex; margin: 0px 0px 0px 0.8ex; BORDER-LEFT: #ccc 1px solid">
        -----原始邮件-----<br>
        <b>发件人:</b>"David Gobbi" <david.gobbi@gmail.com> <br>
        <b>发送时间:</b>2016年03月18日 星期五<br>
        <b>收件人:</b>"Liu_tj" <tjlp@netease.com><br>
        <b>抄送:</b>"vtkusers" <vtkusers@vtk.org><br>
        <b>主题:</b>Re: Re: Re: Re: Re: Re: [vtkusers] High memory cost of vtkDecimatePro for 3D model generation from DICOM series<br>
<br><div dir="ltr">You can segment an image with just one threshold (i.e. just the lower threshold).  It is not necessary to set a range.<div><br></div><div>But, regardless, vtkMarchingCubes is designed to take a greyscale image as input, not a binary image.</div><div><br></div><div> - David</div><div><br><div><br></div><div><div><div><div class="gmail_extra"><div class="gmail_quote">On Thu, Mar 17, 2016 at 8:09 PM, Liu_tj <span dir="ltr"><<a href="mailto:tjlp@netease.com" target="_blank">tjlp@netease.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi, David,<br><br>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.<br><br>Thanks<span class=""><br><div><br></div>
 <span>
 </span>
<br>      在2016-03-18,"David Gobbi" <<a href="mailto:david.gobbi@gmail.com" target="_blank">david.gobbi@gmail.com</a>> 写道:
        </span><blockquote style="padding-left:1ex;margin:0px 0px 0px 0.8ex;BORDER-LEFT:#ccc 1px solid"><span class="">
        -----原始邮件-----<br>
        <b>发件人:</b>"David Gobbi" <<a href="mailto:david.gobbi@gmail.com" target="_blank">david.gobbi@gmail.com</a>> <br>
        <b>发送时间:</b>2016年03月18日 星期五<br>
        <b>收件人:</b>"Liu_tj" <<a href="mailto:tjlp@netease.com" target="_blank">tjlp@netease.com</a>><br>
        <b>抄送:</b>"vtkusers" <<a href="mailto:vtkusers@vtk.org" target="_blank">vtkusers@vtk.org</a>><br>
        </span><b>主题:</b>Re: Re: Re: Re: Re: [vtkusers] High memory cost of vtkDecimatePro for 3D model generation from DICOM series<div><div class="h5"><br>
<br><div dir="ltr"><div>You only need one threshold to create a model from an image.</div><div>Why do you let the user set two thresholds?</div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Mar 17, 2016 at 7:54 PM, Liu_tj <span dir="ltr"><<a href="mailto:tjlp@netease.com" target="_blank">tjlp@netease.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi, David,<br><br>If the user sets a upper value, what should we do?<br><br>Thanks<br>Liu Peng<span><br><div><br><br></div>
 <span>
 </span>
<br>      在2016-03-18,"David Gobbi" <<a href="mailto:david.gobbi@gmail.com" target="_blank">david.gobbi@gmail.com</a>> 写道:
        </span><blockquote style="padding-left:1ex;margin:0px 0px 0px 0.8ex;BORDER-LEFT:#ccc 1px solid"><span>
        -----原始邮件-----<br>
        <b>发件人:</b>"David Gobbi" <<a href="mailto:david.gobbi@gmail.com" target="_blank">david.gobbi@gmail.com</a>> <br>
        </span><b>发送时间:</b>2016年03月18日 星期五<span><br>
        <b>收件人:</b>"Liu_tj" <<a href="mailto:tjlp@netease.com" target="_blank">tjlp@netease.com</a>><br>
        <b>抄送:</b>"vtkusers" <<a href="mailto:vtkusers@vtk.org" target="_blank">vtkusers@vtk.org</a>><br>
        </span><b>主题:</b>Re: Re: Re: Re: [vtkusers] High memory cost of vtkDecimatePro for 3D model generation from DICOM series<div><div><br>
<br><div dir="ltr">Hi Liu Peng,<div><br></div><div>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.</div><div><br></div><div>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.</div><div><br></div><div>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.</div><div><br></div><div> - David</div><div><br></div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Mar 17, 2016 at 7:07 PM, Liu_tj <span dir="ltr"><<a href="mailto:tjlp@netease.com" target="_blank">tjlp@netease.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi, David,<br><br>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?<br><br>      private void Display(vtkRenderWindow aRenderWindow, vtkImageData aData)<br>        {<br>            vtkImageData volume = vtkImageData.New();<br>            double isoValue = 1;<br>            volume.DeepCopy(aData);<br>            vtkImageThreshold image_threshold = vtkImageThreshold.New();<br>            image_threshold.SetInputData(volume);<br>            image_threshold.ThresholdBetween(1000,20000);<br>            image_threshold.ReplaceInOn();<br>            image_threshold.SetInValue(1);<br>            image_threshold.ReplaceOutOn();<br>            image_threshold.SetOutValue(0);<br>            image_threshold.Update();<br><br>            vtkMarchingCubes surface = vtkMarchingCubes.New();<br>            surface.SetInputData(image_threshold.GetOutput());<br>            surface.ComputeNormalsOn();<br>            surface.ComputeScalarsOn();<br>            surface.SetValue(0, isoValue);<br>            surface.Update();<br><br>            vtkPolyData marched = vtkPolyData.New();<br>            marched.DeepCopy(surface.GetOutput());<br><br>            long pointcnt = marched.GetNumberOfPoints();<span><br><br>            // Decimation to reduce the number of triangles<br></span>            vtkDecimatePro decimator = vtkDecimatePro.New();<br>            decimator.SetInputData(marched);<br>            decimator.SetTargetReduction(0.5);<br>            decimator.SetPreserveTopology(1);<br>            decimator.Update();<br>            //Smoothing<br>           vtkSmoothPolyDataFilter smoother = vtkSmoothPolyDataFilter.New();<br>            smoother.SetInputData(decimator.GetOutput());<br>            smoother.SetNumberOfIterations(5);<br>            smoother.SetFeatureAngle(60);<br>            smoother.SetRelaxationFactor(0.05);<br>            smoother.FeatureEdgeSmoothingOff();<br><br>            //Select the largest region<br>            vtkPolyDataConnectivityFilter connectivityFilter = vtkPolyDataConnectivityFilter.New();<br>            connectivityFilter.SetInputConnection(decimator.GetOutputPort());<br>            connectivityFilter.ScalarConnectivityOff();<br>            connectivityFilter.SetExtractionModeToLargestRegion();<br>            connectivityFilter.Update();<br><br>            // Create final polygon mesh<br>            vtkPolyData mesh = vtkPolyData.New();<br>            mesh.ShallowCopy(connectivityFilter.GetOutput());<br><br>            // Visualization<br>            vtkRenderer renderer = aRenderWindow.GetRenderers().GetFirstRenderer();<br>            renderer.SetBackground(0.0, 0.0, 0.0);<br><br>            vtkPolyDataMapper mapper = vtkPolyDataMapper.New();<br>            mapper.SetInputData(mesh);<br>            mapper.ScalarVisibilityOff();<br><br>            vtkActor actor = vtkActor.New();<br>            actor.SetMapper(mapper);<br>            renderer.AddActor(actor);<br><br>            vtkCamera camera = renderer.MakeCamera();<br>            camera.SetPosition(-500.0, 245.5, 122.0);<br>            camera.SetFocalPoint(301.0, 245.5, 122.0);<br>            camera.SetViewAngle(30.0);<br>            camera.SetRoll(-90.0);<br>            renderer.SetActiveCamera(camera);<br><br>            aRenderWindow.Render();<br><br>            vtkRenderWindowInteractor interactor  = aRenderWindow.GetInteractor();<br>            interactor.Start();<span><br>        }<br><div><br><br></div>
 <span>
 </span>
<br>      在2016-03-17,"David Gobbi" <<a href="mailto:david.gobbi@gmail.com" target="_blank">david.gobbi@gmail.com</a>> 写道:
        </span><blockquote style="padding-left:1ex;margin:0px 0px 0px 0.8ex;BORDER-LEFT:#ccc 1px solid"><span>
        -----原始邮件-----<br>
        <b>发件人:</b>"David Gobbi" <<a href="mailto:david.gobbi@gmail.com" target="_blank">david.gobbi@gmail.com</a>> <br>
        <b>发送时间:</b>2016年03月17日 星期四<br>
        <b>收件人:</b>"Liu_tj" <<a href="mailto:tjlp@netease.com" target="_blank">tjlp@netease.com</a>><br>
        <b>抄送:</b>"vtkusers" <<a href="mailto:vtkusers@vtk.org" target="_blank">vtkusers@vtk.org</a>><br>
        </span><b>主题:</b>Re: Re: Re: [vtkusers] High memory cost of vtkDecimatePro for 3D model generation from DICOM series<div><div><br>
<br><div dir="ltr">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:<div><br></div><div>vtkSmartPointer<vtkMarchingCubes> cubes1 = vtkSmartPointer<vtkMarchingCubes>::New();<br></div><div>cubes1->SetInputData(imagedata);</div><div>cubes1->SetValue(0, lowerThreshold);</div><div><br></div><div>vtkSmartPointer<vtkMarchingCubes> cubes2 = vtkSmartPointer<vtkMarchingCubes>::New();<br></div><div>cubes2->SetInputData(imagedata);</div><div>cubes2->SetValue(0, upperThreshold);</div><div><br></div><div>vtkSmartPointer<vtkReverseSense> reverse = vtkSmartPointer<vtkReverseSense>::New();<br></div><div>reverse->SetInputConnection(cubes2->GetOutputPort());</div><div><br></div><div>vtkSmartPointer<vtkAppendPolyData> surface = vtkSmartPointer<vtkAppendPolyData>::New();<br></div><div>surface->SetInputConnection(cubes1->GetOutputPort());</div><div>surface->AddInputConnection(cubes2->GetOutputPort());<br></div><div>surface->Update();</div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Mar 17, 2016 at 6:06 AM, David Gobbi <span dir="ltr"><<a href="mailto:david.gobbi@gmail.com" target="_blank">david.gobbi@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Hi Liu Peng,<div><br></div><div>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.</div><span><font color="#888888"><div><br></div><div> - David</div></font></span></div><div><div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Mar 16, 2016 at 11:27 PM, Liu_tj <span dir="ltr"><<a href="mailto:tjlp@netease.com" target="_blank">tjlp@netease.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi, David,<br><br>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. <div><br>Thanks<br>Liu Peng<br></div><span>
 <span>
 </span>
<br>      在2016-03-17,"David Gobbi" <<a href="mailto:david.gobbi@gmail.com" target="_blank">david.gobbi@gmail.com</a>> 写道:
        </span><blockquote style="padding-left:1ex;margin:0px 0px 0px 0.8ex;BORDER-LEFT:#ccc 1px solid"><span>
        -----原始邮件-----<br>
        <b>发件人:</b>"David Gobbi" <<a href="mailto:david.gobbi@gmail.com" target="_blank">david.gobbi@gmail.com</a>> <br>
        <b>发送时间:</b>2016年03月17日 星期四<br>
        <b>收件人:</b>"Liu_tj" <<a href="mailto:tjlp@netease.com" target="_blank">tjlp@netease.com</a>><br>
        <b>抄送:</b>"vtkusers" <<a href="mailto:vtkusers@vtk.org" target="_blank">vtkusers@vtk.org</a>><br>
        </span><b>主题:</b>Re: Re: [vtkusers] High memory cost of vtkDecimatePro for 3D model generation from DICOM series<div><div><br>
<br><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Wed, Mar 16, 2016 at 10:35 PM, Liu_tj <span dir="ltr"><<a href="mailto:tjlp@netease.com" target="_blank">tjlp@netease.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi,David,<br><br>If using vtkImageThreshold before vtkMarchingCubes is not a good option, what other better way do you have?<br></blockquote><div><br></div><div>The output of the reader should go directly into vtkMarchingCubes.</div><div>   </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">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.<br></blockquote><div><br></div><div>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.  </div><div><br></div><div>Also, after vtkMarchingCubes, you can use vtkConnectivityFilter to clean up the polydata before you decimate it.</div><div><br></div><div> - David</div></div></div></div>
</div></div></blockquote><br><br><span title="neteasefooter"><p> </p></span></blockquote></div><br></div>
</div></div></blockquote></div><br></div>
</div></div></blockquote></blockquote></div><br></div>
</div></div></blockquote></blockquote></div><br></div>
</div></div></blockquote></blockquote></div><br></div></div></div></div></div></div>
</blockquote>