<div dir="ltr"><div>Would it be acceptable to step out of VTK for meshing?</div><div>You could try to do something like the following:</div><div>1. Import DICOM data</div><div>2. Select region of interest</div><div>3. Export region of interest to STL</div>
<div>4. Use dedicated mesh generator like netgen</div><div>    <a href="http://sourceforge.net/apps/mediawiki/netgen-mesher/index.php?title=Main_Page">http://sourceforge.net/apps/mediawiki/netgen-mesher/index.php?title=Main_Page</a></div>
<div>    to mesh the geometry</div><div>5. Import mesh into VTK</div><div> </div><div>Export/Import can ofcourse also be replaced by</div><div>direct calls from C++ into the netgen library.</div><div>I am not sure if direct VTK support is available in</div>
<div>netgen.</div><div> </div><div> </div><div>Regards,</div><div> </div><div>Marco</div><div> </div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Wed, Nov 27, 2013 at 5:20 AM, Harold <span dir="ltr">&lt;<a href="mailto:boogiedoll@yahoo.com" target="_blank">boogiedoll@yahoo.com</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div style="font-family:HelveticaNeue,Helvetica Neue,Helvetica,Arial,Lucida Grande,sans-serif;font-size:10pt"><div>
Hi Miro,</div><div><br></div><div>Thank you for the guide. I&#39;m new to vtk so while messing around, I managed to apply the followings to a set of dicom images (in a very crude way) and save it as a .vtk file.</div><div>
1. Marching Cubes - get mesh</div><div>2. Decimation - reduce the number of triangles</div><div>3. Smoothing - smooth the mesh</div><div>4. Cropping - select the largest region using connectivity filter</div><div><br></div>
<div>I guess my next step is to find out how to do pre-processing and refining of the defected mesh, and also making statistical models (if there are enough training images...).</div><div><br></div><div>By the way, here&#39;s my crude code based on the the  MarchingCubes Example at <a href="http://www.vtk.org/Wiki/VTK/Examples/Cxx/Modelling/MarchingCubes" target="_blank">http://www.vtk.org/Wiki/VTK/Examples/Cxx/Modelling/MarchingCubes</a>&quot;. Hopefully
 it can be a small help to other novice like me out there.</div><div><br></div><div>/////////////////////////////////</div><div>int main(int argc, char *argv[])</div><div>{</div><div>  vtkSmartPointer&lt;vtkImageData&gt; volume =</div>
<div>    vtkSmartPointer&lt;vtkImageData&gt;::New();</div><div>  double isoValue;</div><div><br></div><div>  if (argc &lt; 3)   </div><div>    {</div><div><span style="white-space:pre-wrap">        </span>// Create a sphere if there&#39;s no dicom input</div>
<div>    vtkSmartPointer&lt;vtkSphereSource&gt; sphereSource = </div><div>      vtkSmartPointer&lt;vtkSphereSource&gt;::New();</div><div>    sphereSource-&gt;SetPhiResolution(20);</div><div>    sphereSource-&gt;SetThetaResolution(20);</div>
<div>    sphereSource-&gt;Update();</div><div>    </div><div>    double
 bounds[6];</div><div>    sphereSource-&gt;GetOutput()-&gt;GetBounds(bounds);</div><div>    for (unsigned int i = 0; i &lt; 6; i += 2)</div><div>      {</div><div>      double range = bounds[i+1] - bounds[i];</div><div>      bounds[i]   = bounds[i] - .1 * range;</div>
<div>      bounds[i+1] = bounds[i+1] + .1 * range;</div><div>      }</div><div>    vtkSmartPointer&lt;vtkVoxelModeller&gt; voxelModeller = </div><div>      vtkSmartPointer&lt;vtkVoxelModeller&gt;::New();</div><div>    voxelModeller-&gt;SetSampleDimensions(50,50,50);</div>
<div>    voxelModeller-&gt;SetModelBounds(bounds);</div><div>    voxelModeller-&gt;SetScalarTypeToFloat();</div><div>    voxelModeller-&gt;SetMaximumDistance(.1);</div><div>    </div><div>   
 voxelModeller-&gt;SetInputConnection(sphereSource-&gt;GetOutputPort());</div><div>    voxelModeller-&gt;Update();</div><div>    isoValue = 0.5;</div><div>    volume-&gt;DeepCopy(voxelModeller-&gt;GetOutput());</div><div>
    }</div><div>  else</div><div>    {</div><div>    // Read dicom image when dicom image folder path is specified</div><div>    vtkSmartPointer&lt;vtkDICOMImageReader&gt; reader =</div><div>      vtkSmartPointer&lt;vtkDICOMImageReader&gt;::New();</div>
<div>    reader-&gt;SetDirectoryName(argv[1]);</div><div>    reader-&gt;Update();</div><div>    volume-&gt;DeepCopy(reader-&gt;GetOutput());</div><div>    isoValue = atof(argv[2]);</div><div>    }</div><div><br></div><div>
  // Use MarchingCubes to generate iso-surface</div><div>  vtkSmartPointer&lt;vtkMarchingCubes&gt; surface
 = </div><div>    vtkSmartPointer&lt;vtkMarchingCubes&gt;::New();</div><div><br></div><div>  #if VTK_MAJOR_VERSION &lt;= 5</div><div>    surface-&gt;SetInput(volume);</div><div>  #else</div><div>    surface-&gt;SetInputData(volume);</div>
<div>  #endif</div><div>  surface-&gt;ComputeNormalsOn();</div><div>  surface-&gt;ComputeScalarsOn();</div><div>  surface-&gt;SetValue(0, isoValue);</div><div>  std::cout &lt;&lt; &quot;Marching Cube finished...&quot; &lt;&lt; std::endl;</div>
<div><br></div><div>  // Create polydata from iso-surface</div><div>  vtkSmartPointer&lt;vtkPolyData&gt; marched =</div><div>    vtkSmartPointer&lt;vtkPolyData&gt;::New();</div><div>  surface-&gt;Update();</div><div>  marched-&gt;DeepCopy(surface-&gt;GetOutput());</div>
<div>  std::cout&lt;&lt;&quot;Number of points: &quot; &lt;&lt; marched-&gt;GetNumberOfPoints() &lt;&lt;
 std::endl;</div><div>  </div><div>  // Decimation to reduce the number of triangles</div><div>  vtkSmartPointer&lt;vtkDecimatePro&gt; decimator = </div><div>    vtkDecimatePro::New();</div><div>  decimator-&gt;SetInputData(marched);</div>
<div>  decimator-&gt;SetTargetReduction(0.5);</div><div>  decimator-&gt;SetPreserveTopology(1);</div><div>  decimator-&gt;Update();</div><div>  std::cout &lt;&lt; &quot;Decimation finished....&quot; &lt;&lt; std::endl;</div>
<div><span style="white-space:pre-wrap">                </span></div><div>  // Smoothing</div><div>  vtkSmartPointer&lt;vtkSmoothPolyDataFilter&gt; smoother = vtkSmartPointer&lt;vtkSmoothPolyDataFilter&gt;::New();</div><div>  smoother-&gt;SetInputData(decimator-&gt;GetOutput());</div>
<div>  smoother-&gt;SetNumberOfIterations(5);</div><div>  smoother-&gt;SetFeatureAngle(60);</div><div> 
 smoother-&gt;SetRelaxationFactor(0.05);</div><div>  smoother-&gt;FeatureEdgeSmoothingOff();</div><div>  std::cout &lt;&lt; &quot;Smoothing mesh finished....&quot; &lt;&lt; std::endl;</div><div><br></div><div> // Select the largest region</div>
<div>  vtkSmartPointer&lt;vtkPolyDataConnectivityFilter&gt; connectivityFilter =</div><div><span style="white-space:pre-wrap">        </span>vtkSmartPointer&lt;vtkPolyDataConnectivityFilter&gt;::New();</div><div>  connectivityFilter-&gt;SetInputConnection(smoother-&gt;GetOutputPort());</div>
<div>  connectivityFilter-&gt;ScalarConnectivityOff();</div><div>  connectivityFilter-&gt;SetExtractionModeToLargestRegion();</div><div>  connectivityFilter-&gt;Update();</div><div>  </div><div> // Create final polygon mesh</div>
<div>  vtkSmartPointer&lt;vtkPolyData&gt; mesh =</div><div>    vtkSmartPointer&lt;vtkPolyData&gt;::New();</div><div> 
 mesh-&gt;ShallowCopy(connectivityFilter-&gt;GetOutput());</div><div>  std::cout&lt;&lt;&quot;Number of points in the final polygon: &quot; &lt;&lt; mesh-&gt;GetNumberOfPoints() &lt;&lt; std::endl;</div><div> </div><div>
  // Visualization</div><div>  vtkSmartPointer&lt;vtkRenderer&gt; renderer = </div><div>    vtkSmartPointer&lt;vtkRenderer&gt;::New();</div><div>  renderer-&gt;SetBackground(.1, .2, .3);</div><div><br></div><div>  vtkSmartPointer&lt;vtkRenderWindow&gt; renderWindow = </div>
<div>    vtkSmartPointer&lt;vtkRenderWindow&gt;::New();</div><div>  renderWindow-&gt;AddRenderer(renderer);</div><div>  vtkSmartPointer&lt;vtkRenderWindowInteractor&gt; interactor = </div><div>    vtkSmartPointer&lt;vtkRenderWindowInteractor&gt;::New();</div>
<div>  interactor-&gt;SetRenderWindow(renderWindow);</div><div><br></div><div>  vtkSmartPointer&lt;vtkPolyDataMapper&gt; mapper
 = </div><div>    vtkSmartPointer&lt;vtkPolyDataMapper&gt;::New();</div><div>  mapper-&gt;SetInputData(mesh);</div><div>  mapper-&gt;ScalarVisibilityOff();</div><div><br></div><div>  vtkSmartPointer&lt;vtkActor&gt; actor = </div>
<div>    vtkSmartPointer&lt;vtkActor&gt;::New();</div><div>  actor-&gt;SetMapper(mapper);</div><div><br></div><div>  renderer-&gt;AddActor(actor);</div><div><br></div><div>  renderWindow-&gt;Render();</div><div>  interactor-&gt;Start();</div>
<div><br></div><div>  // Save the mesh as a .vtk file</div><div>  vtkSmartPointer&lt;vtkPolyDataWriter&gt; writer = vtkPolyDataWriter::New();</div><div>  writer-&gt;SetFileName(&quot;mesh.vtk&quot;);</div><div>  writer-&gt;SetInputData(mesh);</div>
<div>  writer-&gt;SetFileTypeToASCII();</div><div>  writer-&gt;Write();</div><div>  </div><div>  return
 EXIT_SUCCESS;</div><div>}</div><div><br></div><div><br></div><div>Best Regards,</div><div><span></span></div><div>Harold</div><div><div class="h5"><div style="display:block"> <br> <br> <div style="font-family:HelveticaNeue,&quot;Helvetica Neue&quot;,Helvetica,Arial,&quot;Lucida Grande&quot;,sans-serif;font-size:10pt">
 <div style="font-family:HelveticaNeue,&quot;Helvetica Neue&quot;,Helvetica,Arial,&quot;Lucida Grande&quot;,sans-serif;font-size:12pt"> <div dir="ltr"> <font face="Arial"> On Wednesday, November 27, 2013 12:06 PM, Miro Drahos &lt;<a href="mailto:mdrahos@robodoc.com" target="_blank">mdrahos@robodoc.com</a>&gt; wrote:<br>
 </font> </div>  <div>This is basically a segmentation problem, which in general is a <br clear="none">difficult problem.<br clear="none">One such pipeline could be as follows:<br clear="none">1.) image preprocessing (cropping, smoothing, etc).<br clear="none">
2.) thresholding to get a filled binary mask of your object (vertebra)<br clear="none">3.) running Marching
 Cubes to get a mesh.<br clear="none"><br clear="none">This is a very crude and basic approach, but something to get you <br clear="none">started. Note that marching cubes might give you a mesh with topological <br clear="none">
defects (holes, handles), from the noise in your data.<br clear="none"><br clear="none">There are a variety of other sophisticated algorithms, e.g. using <br clear="none">statistical methods if you have some already segmented data (like <br clear="none">
creating a mean shape from the previously segmented data, and using PCA <br clear="none">to do shape analysis, or some machine learning approach).<br clear="none"><br clear="none">Another approach would be to use deformable models, i.e. define forces <br clear="none">
that would (iteratively) drive an initial mesh to fit the image. The <br clear="none">forces would be based on image intensity, gradient and/or laplacian, and <br clear="none">internal forces to keep the mesh regular
 and relatively smooth.<br clear="none"><br clear="none">There is a lot that has been done in this domain, so look at some <br clear="none">articles on segmentation.<br clear="none"><br clear="none">HTH,<br clear="none">
Miro<br clear="none"><br clear="none"><div><br clear="none">On 11/25/2013 06:20 AM, Boogiedoll wrote:<br clear="none">&gt; Hi,<br clear="none">&gt; I would like to ask the experts about common way in vtk to create a spine bone (e.g L1) mesh from a CT DICOM stack, including the pre-processing.<br clear="none">
&gt;<br clear="none">&gt; Thanks &amp; Regards,<br clear="none">&gt; Harold<br clear="none">&gt; _______________________________________________<br clear="none">&gt; Powered by <a href="http://www.kitware.com" target="_blank">www.kitware.com</a><br clear="none">
&gt;<br clear="none">&gt; Visit other Kitware open-source projects at <a href="http://www.kitware.com/opensource/opensource.html" shape="rect" target="_blank">http://www.kitware.com/opensource/opensource.html</a><br clear="none">
&gt;<br clear="none">&gt; Please keep messages on-topic and check the VTK FAQ at: <a href="http://www.vtk.org/Wiki/VTK_FAQ" shape="rect" target="_blank">http://www.vtk.org/Wiki/VTK_FAQ</a><br clear="none">&gt;<br clear="none">
&gt; Follow this link to subscribe/unsubscribe:<br clear="none">&gt; <a href="http://www.vtk.org/mailman/listinfo/vtkusers" shape="rect" target="_blank">http://www.vtk.org/mailman/listinfo/vtkusers</a><br clear="none"><br clear="none">
</div><br><br></div>  </div> </div>  </div> </div></div></div></div><br>_______________________________________________<br>
Powered by <a href="http://www.kitware.com" target="_blank">www.kitware.com</a><br>
<br>
Visit other Kitware open-source projects at <a href="http://www.kitware.com/opensource/opensource.html" target="_blank">http://www.kitware.com/opensource/opensource.html</a><br>
<br>
Please keep messages on-topic and check the VTK FAQ at: <a href="http://www.vtk.org/Wiki/VTK_FAQ" target="_blank">http://www.vtk.org/Wiki/VTK_FAQ</a><br>
<br>
Follow this link to subscribe/unsubscribe:<br>
<a href="http://www.vtk.org/mailman/listinfo/vtkusers" target="_blank">http://www.vtk.org/mailman/listinfo/vtkusers</a><br>
<br></blockquote></div><br></div>