<html>
<head>
<style>
.hmmessage P
{
margin:0px;
padding:0px
}
body.hmmessage
{
font-size: 10pt;
font-family:Verdana
}
</style>
</head>
<body class='hmmessage'>
Hi everyone,<br><br>I have spent days trying to resolve this problem and hope someone out there has dealt with this before. I want to rigidly register an image (moving component) to a mesh (fixed component). The image in question is a vertebra I segmented using ITK-SNAP and and exported as MHD file (so 3d image). The mesh is VTK Polydata mesh exported from ITK-SNAP from another segmented vertebra.<br><br>Before registration I decimate the mesh (vtkDecimatePro), write it back to file and read it as an ITK Mesh. I take that mesh an set all PointData to zero. I do this so I can register a signed danielsson distance map to the mesh. The purpose of registering a distance map to a zeroed mesh is to reduce computational overhead. However, when I get the transformation it appears that it's not using the distance map/zeroed mesh properly. I should be seeing a translation of (10,45,35) but instead get a translation that approaches 0. The same goes for rotation and scaling, the "better" the optimizer settings are, the worse the transformation is (eg extreme shrinking, rotation that results in perpendicular alignment). It always goes till the max iteration setting. I verified all this using Paraview and even hard coding the correct translation (the correct rotation/scaling already near identity) it screws things up.<br><br>I have looked at the ICP examples and the PointSettoImage test examples and obviously none of them deal with this problem. The closest thing I found was in ICP example 3, where distance map is used for the fixed pointset (EuclideanMetric-&gt;SetDistanceMap). The problem is, my overall project depends on having different vertebre images registering to the same fixed mesh.<br><br>Any help would be GREATLY appreciated, I've exhausted all other resources.<br><br>PS cleaned up relevant source code included below<br><br>//-----------------------------------------------------------<br>// setPointsToZero: reset ITK Mesh PointData to zero<br>//-----------------------------------------------------------<br>void setPointsToZero (MeshType::Pointer &amp;templateMesh){<br><br>&nbsp;&nbsp;&nbsp; PixelTypeDouble zero = (0.0,0.0,0.0);<br><br>&nbsp;&nbsp;&nbsp; // Get the number of points in the mesh<br>&nbsp;&nbsp; int numPoints = templateMesh-&gt;GetNumberOfPoints();<br>&nbsp;&nbsp; if(numPoints == 0)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; templateMesh-&gt;Print(std::cerr &lt;&lt; "Mesh has no points." &lt;&lt; std::endl);<br>&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; // Iterate over all the points in the itk mesh seting values to 0&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; MeshType::PointsContainer::Pointer points = templateMesh-&gt;GetPoints();<br>&nbsp;&nbsp;&nbsp; for(MeshType::PointsContainer::Iterator i = points-&gt;Begin(); i != points-&gt;End(); i++){<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // Get the point index from the point container iterator<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; templateMesh-&gt;SetPointData(i-&gt;Index(), zero);<br><br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; <br>}<br><br>//--------------------------------------------------------------<br>// registerMeshToImg: 3d rigid register distance map to ITK Mesh<br>//--------------------------------------------------------------<br>void registerMeshToImg(MeshType::Pointer &amp;meshTemplate, ImageTypeDouble::Pointer &amp;imgDistanceMap)<br>{<br><br>&nbsp; //-----------------------------------------------------------<br>&nbsp; // Set up&nbsp; the Metric<br>&nbsp; //-----------------------------------------------------------<br>&nbsp; typedef itk::MeanSquaresPointSetToImageMetric&lt;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MeshType, <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ImageTypeDouble &gt;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MetricType;<br><br>&nbsp; typedef MetricType::TransformType&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TransformBaseType;<br>&nbsp; typedef TransformBaseType::ParametersType&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ParametersType;<br>&nbsp; typedef TransformBaseType::JacobianType&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; JacobianType;<br><br>&nbsp; MetricType::Pointer&nbsp; metric = MetricType::New();<br><br>&nbsp; //-----------------------------------------------------------<br>&nbsp; // Set up a Transform<br>&nbsp; //-----------------------------------------------------------<br>&nbsp; typedef itk::Similarity3DTransform&lt; PixelTypeDouble &gt; TransformType;<br><br>&nbsp; TransformType::Pointer transform = TransformType::New();<br><br>&nbsp; //------------------------------------------------------------<br>&nbsp; // Set up an Interpolator<br>&nbsp; //------------------------------------------------------------<br>&nbsp; typedef itk::LinearInterpolateImageFunction&lt; <br>&nbsp;&nbsp;&nbsp; ImageTypeDouble,<br>&nbsp;&nbsp;&nbsp; PixelTypeDouble &gt; InterpolatorType;<br><br>&nbsp; InterpolatorType::Pointer interpolator = InterpolatorType::New();<br><br>&nbsp; // Optimizer Type<br>&nbsp; typedef itk::RegularStepGradientDescentOptimizer&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OptimizerType;<br><br>&nbsp; OptimizerType::Pointer&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; optimizer&nbsp;&nbsp;&nbsp;&nbsp; = OptimizerType::New();<br><br>&nbsp; // Registration Method<br>&nbsp; typedef itk::PointSetToImageRegistrationMethod&lt; <br>&nbsp;&nbsp;&nbsp; MeshType, <br>&nbsp;&nbsp;&nbsp; ImageTypeDouble &gt;&nbsp;&nbsp;&nbsp; RegistrationType;<br><br><br>&nbsp; RegistrationType::Pointer&nbsp;&nbsp; registration&nbsp; = RegistrationType::New();<br><br>&nbsp; // Scale the components of the Transform in the Optimizer<br>&nbsp; OptimizerType::ScalesType scales( transform-&gt;GetNumberOfParameters() );<br>&nbsp; scales.Fill( 1.0 );<br><br>&nbsp; unsigned long&nbsp;&nbsp; numberOfIterations =&nbsp;&nbsp; 500;<br>&nbsp; double&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maximumStepLenght&nbsp; =&nbsp; 0.001;&nbsp; // no step will be larger than this<br>&nbsp; double&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; minimumStepLenght&nbsp; =&nbsp; 0.0001; // convergence criterion<br>&nbsp; double&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gradientTolerance&nbsp; =&nbsp; 1e-6; // convergence criterion<br>&nbsp; <br>&nbsp; optimizer-&gt;SetScales( scales );<br>&nbsp; optimizer-&gt;SetNumberOfIterations( numberOfIterations );<br>&nbsp; optimizer-&gt;SetMinimumStepLength( minimumStepLenght );<br>&nbsp; optimizer-&gt;SetMaximumStepLength( maximumStepLenght );<br>&nbsp; optimizer-&gt;SetGradientMagnitudeTolerance( gradientTolerance );<br>&nbsp; optimizer-&gt;MinimizeOn();<br>&nbsp; <br>&nbsp; // Start from an Identity transform<br>&nbsp; transform-&gt;SetIdentity();<br>&nbsp; transform-&gt;SetCenter( /* Center of Gravity of Mesh */ );<br>&nbsp; <br>&nbsp; registration-&gt;SetInitialTransformParameters( transform-&gt;GetParameters() );<br>&nbsp; <br>&nbsp; //------------------------------------------------------<br>&nbsp; // Connect all the components required for Registration<br>&nbsp; //------------------------------------------------------<br>&nbsp; registration-&gt;SetMetric(&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; metric&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; );<br>&nbsp; registration-&gt;SetOptimizer(&nbsp;&nbsp;&nbsp;&nbsp; optimizer&nbsp;&nbsp;&nbsp;&nbsp; );<br>&nbsp; registration-&gt;SetTransform(&nbsp;&nbsp;&nbsp;&nbsp; transform&nbsp;&nbsp;&nbsp;&nbsp; );<br>&nbsp; registration-&gt;SetFixedPointSet( meshTemplate );<br>&nbsp; registration-&gt;SetMovingImage(&nbsp;&nbsp; imgDistanceMap&nbsp;&nbsp; );<br>&nbsp; registration-&gt;SetInterpolator(&nbsp; interpolator&nbsp; );<br>&nbsp; <br>&nbsp; //------------------------------------------------------------<br>&nbsp; // Set up transform parameters<br>&nbsp; //------------------------------------------------------------<br>&nbsp; ParametersType parameters( transform-&gt;GetNumberOfParameters() );<br><br>&nbsp; try <br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; registration-&gt;StartRegistration();<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp; catch( itk::ExceptionObject &amp; e )<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; e &lt;&lt; std::endl;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; <br>}<br><br><br /><hr />Windows Live™ Hotmail®:…more than just e-mail. <a href='http://windowslive.com/online/hotmail?ocid=TXT_TAGLM_WL_HM_more_042009' target='_new'>Check it out.</a></body>
</html>