Hi Dan,<br>Your code looks great.<br>I have been trying hard to make it work but it <br>has not got to the finish line yet.<br><br>I am carving out small 3D regions for the speed <br>function (on the range of 30x40x30 pixels).<br>
<br>I map the speed pixels to a float range [0.0 - 1.0];<br>and can verify that the start and end points (1 end point for now)<br>are where they should be in the small image.<br><br>Then I pass this to the filter. I added a function to your code<br>
to read the arrival function at the end :<br>after calling pathFilter-&gt;Update()<br>I do (InputImagePointer GetArrivalFunc(){return m_CurrentArrivalFunction;}; )<br>in itkSpeedFunctionToPathFilter.h<br><br>This reveals the following statistics for Arrival:<br>
min=0; max=1.70141e+38, mean=4.26e+36 ...<br>I also read the arrival time at the endpoint: 1431.25<br>(reasonable, right?)<br><br>(Even when I use a fake end point that is very close<br>to the start point, the arrival value is 315.8...)<br>
<br>yet, the path is always empty!<br><br>I tried all 3 suggested optimizers, but the result is the same.<br><br>Can you suggest anything?<br>I am attaching my calling method in case you see anything obvious.<br><br>Thanks for your help.<br>
<br><br>#if defined(_MSC_VER)<br>//Warning about: identifier was truncated to &#39;255&#39; characters in the debug information (MVC6.0 Debug)<br>#pragma warning( disable : 4786 )<br>#endif<br><br>// General includes<br>#include &lt;string&gt;<br>
#include &lt;iostream&gt;<br><br>// ITK includes<br>#include &quot;itkNumericTraits.h&quot;<br>#include &quot;itkImage.h&quot;<br>#include &quot;itkImageFileReader.h&quot;<br>#include &quot;itkImageFileWriter.h&quot;<br>#include &quot;itkPolyLineParametricPath.h&quot;<br>
#include &quot;itkNearestNeighborInterpolateImageFunction.h&quot;<br>#include &quot;itkLinearInterpolateImageFunction.h&quot;<br>#include &quot;itkArrivalFunctionToPathFilter.h&quot;<br>#include &quot;itkSpeedFunctionToPathFilter.h&quot;<br>
#include &quot;itkPathIterator.h&quot;<br>#include &quot;itkGradientDescentOptimizer.h&quot;<br>#include &quot;itkRegularStepGradientDescentOptimizer.h&quot;<br>#include &quot;itkIterateNeighborhoodOptimizer.h&quot;<br>#include &quot;itkStatisticsImageFilter.h&quot;<br>
<br>#include &quot;SpineRing.h&quot;<br><br>PathType::Pointer SpCandidate::FMPath(SpeedImageType::Pointer speed, PointType start, PointSetContainerType::Pointer endptscont)<br>{<br>    //typedef float    PixelType;//speed<br>
    typedef    unsigned char OutputPixelType;<br>    //typedef itk::Image&lt; PixelType, spr_SPIMGDIMENSION    &gt; ImageType;//speed<br>    typedef    itk::Image&lt;    OutputPixelType, spr_SPIMGDIMENSION    &gt; OutputImageType;<br>
    //typedef itk::ImageFileReader&lt;    ImageType &gt;    ReaderType;<br>    typedef    itk::ImageFileWriter&lt; OutputImageType &gt;    WriterType;<br>    //typedef    itk::SpeedFunctionToPathFilter&lt;    SpineImageType,    PathType &gt; PathFilterType;<br>
    typedef    itk::SpeedFunctionToPathFilter&lt;    SpeedImageType,    PathType &gt; PathFilterType;<br>    typedef    PathFilterType::CostFunctionType::CoordRepType    CoordRepType;<br>    typedef    itk::PathIterator&lt; OutputImageType,    PathType &gt; PathIteratorType;<br>
<br>    char* OutputFilename = &quot;TestPath.tif&quot;;<br><br>    speed-&gt;DisconnectPipeline();<br><br>    // Create interpolator<br>    typedef    itk::LinearInterpolateImageFunction&lt;SpeedImageType, CoordRepType&gt;<br>
        InterpolatorType;<br>    InterpolatorType::Pointer interp =    InterpolatorType::New();<br><br>    // Create cost function<br>    PathFilterType::CostFunctionType::Pointer cost    =<br>        PathFilterType::CostFunctionType::New();<br>
    cost-&gt;SetInterpolator( interp );<br><br>    // Create optimizer<br>    ///////////////////////////////////////////////////////////////<br>    //typedef    itk::GradientDescentOptimizer OptimizerType;<br>    //OptimizerType::Pointer    optimizer =    OptimizerType::New();<br>
    //optimizer-&gt;SetNumberOfIterations( 1000 );<br>    //////////////////////////////////////////////////////////////<br><br>    ///////////////////////////////////////////////////////////////////<br>    //typedef itk::RegularStepGradientDescentOptimizer OptimizerType;<br>
    //OptimizerType::Pointer optimizer    = OptimizerType::New();<br>    //optimizer-&gt;SetNumberOfIterations(    1000 );<br>    //optimizer-&gt;SetMaximumStepLength( 0.5 );<br>    //optimizer-&gt;SetMinimumStepLength( 0.1 );<br>
    //optimizer-&gt;SetRelaxationFactor( 0.5 );<br>    ///////////////////////////////////////////////////////////////////<br><br>    ///////////////////////////////////////////////////////////////////<br>    // Create IterateNeighborhoodOptimizer<br>
     typedef itk::IterateNeighborhoodOptimizer OptimizerType;<br>     OptimizerType::Pointer optimizer = OptimizerType::New();<br>     optimizer-&gt;MinimizeOn( );<br>     optimizer-&gt;FullyConnectedOn( );<br>     OptimizerType::NeighborhoodSizeType nbrsize( 3 );<br>
     //float StepLengthFactor = .2;<br>     for (unsigned int i=0; i&lt;3; i++)<br>          nbrsize[i] = speed-&gt;GetSpacing()[i]; //* StepLengthFactor;<br>     optimizer-&gt;SetNeighborhoodSize( nbrsize );<br><br>    // Create path filter<br>
    PathFilterType::Pointer pathFilter    = PathFilterType::New();<br>    pathFilter-&gt;SetInput( speed    );<br>    pathFilter-&gt;SetCostFunction( cost );<br>    pathFilter-&gt;SetOptimizer( optimizer    );<br>    pathFilter-&gt;SetTerminationValue( 2.0 );<br>
<br>    // Setup path points<br>    PathFilterType::PointType pstart, pend; <br>    pstart = start;<br><br>    // Add path    information<br>    PathFilterType::PathInfo info;<br>    info.SetStartPoint(    pstart );<br>    <br>
    pathFilter-&gt;AddPathInfo( info );<br>    <br><br>    PointSetType::PointsContainerIterator    pciter = endptscont-&gt;Begin();<br>    PointType                                pt;<br>    while (pciter != endptscont-&gt;End()) <br>
    {<br>        pt = pciter-&gt;Value();<br>        //for    (int j=0; j&lt;spr_SPIMGDIMENSION;    j++) <br>        //{<br>    //    pend = pt;<br>        //}<br>        // just to test a very close end point!<br>        for (int ii=0; ii&lt;3; ii++)<br>
            pend[ii]=pstart[ii]-5;<br><br>        info.SetEndPoint( pend );<br>        //////////////////////////////////<br>        // Hussein  FIXME<br>        // for now<br>        break;<br>        // need to  examine endpt arrivals.. for all endpts. Choose best.<br>
        /////////////////////////////////<br>        pciter++;<br>    }<br><br><br>    // Compute the path<br>    pathFilter-&gt;Update(    );<br>    //////////////////////////////////////////////////////////<br>    /////////////// DEBUG STUFF<br>
    SpeedImageType::Pointer Arrival = pathFilter-&gt;GetArrivalFunc();<br>    typedef    itk::ImageFileWriter&lt; SpeedImageType &gt;    WriterType2;<br>    WriterType2::Pointer writer2    = WriterType2::New();<br>    writer2-&gt;SetFileName( &quot;Arrival.vtk&quot;    );<br>
    writer2-&gt;SetInput( Arrival );<br>    writer2-&gt;Update();<br>    typedef itk::StatisticsImageFilter&lt;SpeedImageType&gt;  StatisticsType;<br>    StatisticsType::Pointer statistics = StatisticsType::New();<br>    statistics-&gt;SetInput(Arrival );<br>
    statistics-&gt;Update();<br>    float imin = statistics-&gt;GetMinimum();<br>    float imax = statistics-&gt;GetMaximum();<br>    float imean = statistics-&gt;GetMean();<br>    float istd = statistics-&gt;GetSigma();<br>
<br>    std::cout &lt;&lt; &quot;Input Image Statistics: min:&quot;&lt;&lt; imin &lt;&lt; &quot; max:&quot; &lt;&lt; imax &lt;&lt; &quot; mean:&quot;&lt;&lt; imean &lt;&lt; &quot; std:&quot; &lt;&lt; istd &lt;&lt; std::endl;<br>
    SpeedImageType::IndexType arrIndex;<br>    for (int ii=0; ii&lt;3; ii++)<br>        arrIndex[ii] = pend[ii];<br>    std::cout &lt;&lt; &quot;End Arrival Val=&quot; &lt;&lt; Arrival-&gt;GetPixel(arrIndex) &lt;&lt; std::endl;<br>
    //itk::ImageRegionIterator&lt;SpeedImageType&gt; arrit(Arrival, Arrival-&gt;GetRequestedRegion());<br>    //SpeedPixelType spdpxl;<br>    //for ( arrit.GoToBegin(); !arrit.IsAtEnd(); ++arrit)<br>    //{<br>    //    std::cout &lt;&lt; arrit.Get(); //spregion = (spregion-m)/(M-m);  %0 to 1<br>
    //}<br>    /////////// END DEBUG STUFF<br>    //////////////////////////////////////////////////////////////<br>        ///////////////<br>    // Allocate    output image<br>    OutputImageType::Pointer output = OutputImageType::New();<br>
    output-&gt;SetRegions(    speed-&gt;GetLargestPossibleRegion() );<br>    output-&gt;SetSpacing(    speed-&gt;GetSpacing()    );<br>    output-&gt;SetOrigin( speed-&gt;GetOrigin() );<br>    output-&gt;Allocate( );<br>    output-&gt;FillBuffer(    itk::NumericTraits&lt;OutputPixelType&gt;::Zero );<br>
<br>    PathType::Pointer path;<br>    // Rasterize path<br>    for    (unsigned int i=0; i&lt;pathFilter-&gt;GetNumberOfOutputs(); i++)<br>    {<br>        // Get the path<br>        path    = pathFilter-&gt;GetOutput( i );<br>
<br>        // Check path is valid<br>        if ( path-&gt;GetVertexList()-&gt;Size() == 0    )<br>        {<br>            std::cout &lt;&lt; &quot;WARNING: Path    &quot; &lt;&lt; (i+1) &lt;&lt; &quot;    contains no    points!&quot; &lt;&lt;    std::endl;<br>
            continue;<br>        }<br><br>        // Iterate path    and    convert    to image<br>        PathIteratorType it( output, path );<br>        for    (it.GoToBegin(); !it.IsAtEnd();    ++it)<br>        {<br>            it.Set(    itk::NumericTraits&lt;OutputPixelType&gt;::max() );<br>
        }<br>    }<br><br>    // Write output<br>    WriterType::Pointer writer    = WriterType::New();<br>    writer-&gt;SetFileName( OutputFilename    );<br>    writer-&gt;SetInput( output );<br>    writer-&gt;Update();<br>
<br>    return path;<br>}<br><br><br><div class="gmail_quote">On Fri, Jul 17, 2009 at 3:57 AM, Dan Mueller <span dir="ltr">&lt;<a href="mailto:dan.muel@gmail.com">dan.muel@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Hi Hussein,<br>
<div class="im"><br>
&gt; In the ArrivalFunctionToPathFilter  superclass, you had AddEndPoint,<br>
&gt; but in SpeedFunctionToPathFilter, it is invalidated with a warning!<br>
&gt; Why is that?<br>
</div><div class="im">&gt; In the current implementation, I would have to rerun the wave as many<br>
&gt; times as there are endpoints and choose the one with least geodesic<br>
&gt; distance.<br>
&gt; Or alternatively, set all those end points as way points and compare their<br>
&gt; geodesics, pick the least, and use it for the path.<br>
<br>
</div>Indeed, SpeedFunctionToPathFilter allows only a single end point. This<br>
is because the filter performs the path extraction in sections (eg.<br>
start point to way point 1, way point 1 to way point 2, way point 2 to<br>
end point). I guess it could be extended in the manner you describe,<br>
but to date has not been. Feel free to make this extension and submit<br>
it to the Insight Journal!<br>
<br>
If your path consists of multiple start points and multiple end points<br>
(ie. no way/intermediate points but multiple candidate start points),<br>
then you should instead use the ArrivalFunctionToPathFilter. This<br>
filter expects as input an arrival function, which you can compute<br>
yourself using FastMarchingImageFilter with all of the start points as<br>
trial points. Then simply add the end points via AddPathEndPoint(..)<br>
and the extracted path will select the closest start point.<br>
<br>
HTH<br>
<br>
Cheers, Dan<br>
<br>
2009/7/16 asamwm &lt;<a href="mailto:asamwm@gmail.com">asamwm@gmail.com</a>&gt;:<br>
<div><div></div><div class="h5">&gt; Hi Dan,<br>
&gt; I am towards the end of connecting things together however, it looks like<br>
&gt; you only allow one end point at a time to be set for the path.<br>
&gt; Please correct me if I am wrong, I am assuming the wave starts at<br>
&gt; startpoint (0 geodesic distance) and ends at endpoint.<br>
&gt;<br>
&gt; In the ArrivalFunctionToPathFilter  superclass, you had AddEndPoint,<br>
&gt; but in SpeedFunctionToPathFilter, it is invalidated with a warning!<br>
&gt; Why is that?<br>
&gt; The reason I think it is needed is when you have multiple end<br>
&gt; point candidates and you want the wave to stop propagation when it reaches<br>
&gt; the first endpoint (that would be the fastest / closest geodesic pt.).<br>
&gt;<br>
&gt; In the current implementation, I would have to rerun the wave as many<br>
&gt; times as there are endpoints and choose the one with least geodesic<br>
&gt; distance.<br>
&gt; Or alternatively, set all those end points as way points and compare their<br>
&gt; geodesics, pick the least, and use it for the path.<br>
&gt;<br>
&gt; What do you think?<br>
&gt;<br>
&gt; Thanks.<br>
&gt; Hussein<br>
&gt;<br>
&gt;<br>
&gt; On Fri, Jul 10, 2009 at 12:58 AM, asamwm &lt;<a href="mailto:asamwm@gmail.com">asamwm@gmail.com</a>&gt; wrote:<br>
&gt;&gt;<br>
&gt;&gt; Thanks Dan.<br>
&gt;&gt; I&#39;ll let you know when I get it in place.<br>
&gt;&gt;<br>
&gt;&gt; Regards.<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt; On Fri, Jul 10, 2009 at 12:42 AM, Dan Mueller &lt;<a href="mailto:dan.muel@gmail.com">dan.muel@gmail.com</a>&gt; wrote:<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Hi,<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; The filter is not yet available in the main ITK code archive. You must<br>
&gt;&gt;&gt; download the article and code from here:<br>
&gt;&gt;&gt;    <a href="http://www.insight-journal.org/browse/publication/213" target="_blank">http://www.insight-journal.org/browse/publication/213</a><br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Click on the full download &quot;.zip&quot; link and extract the files somewhere<br>
&gt;&gt;&gt; on your hard drive. As explained in the article (section 2.1, page 3)<br>
&gt;&gt;&gt; the main filter you will want to use is<br>
&gt;&gt;&gt; itk::SpeedFunctionToPathFilter, which is located under the &quot;Source&quot;<br>
&gt;&gt;&gt; folder. To use this filter within your own project, you will need to<br>
&gt;&gt;&gt; copy all of the files under the &quot;Source&quot; folder to your own source<br>
&gt;&gt;&gt; code directory.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Make sure you leave a review at the journal!  ;P<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Hope this helps.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Cheers, Dan<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; 2009/7/9 asamwm &lt;<a href="mailto:asamwm@gmail.com">asamwm@gmail.com</a>&gt;:<br>
&gt;&gt;&gt; &gt; Hi all,<br>
&gt;&gt;&gt; &gt; I spent a lot of time searching for this but could not find it.<br>
&gt;&gt;&gt; &gt; There is this insight-journal publication:<br>
&gt;&gt;&gt; &gt; <a href="http://www.insight-journal.org/browse/publication/213" target="_blank">http://www.insight-journal.org/browse/publication/213</a><br>
&gt;&gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt; but where is that filter? I searched under the itk code tree for<br>
&gt;&gt;&gt; &gt; the keywords, speed function, minimal path,  .. no success<br>
&gt;&gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt; Any successful examples? any alternatives?<br>
&gt;&gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt; Thanks<br>
&gt;&gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt; _____________________________________<br>
&gt;&gt;&gt; &gt; Powered by <a href="http://www.kitware.com" target="_blank">www.kitware.com</a><br>
&gt;&gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt; Visit other Kitware open-source projects at<br>
&gt;&gt;&gt; &gt; <a href="http://www.kitware.com/opensource/opensource.html" target="_blank">http://www.kitware.com/opensource/opensource.html</a><br>
&gt;&gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt; Please keep messages on-topic and check the ITK FAQ at:<br>
&gt;&gt;&gt; &gt; <a href="http://www.itk.org/Wiki/ITK_FAQ" target="_blank">http://www.itk.org/Wiki/ITK_FAQ</a><br>
&gt;&gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt; Follow this link to subscribe/unsubscribe:<br>
&gt;&gt;&gt; &gt; <a href="http://www.itk.org/mailman/listinfo/insight-users" target="_blank">http://www.itk.org/mailman/listinfo/insight-users</a><br>
&gt;&gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt;<br>
&gt;&gt;<br>
&gt;<br>
&gt;<br>
</div></div></blockquote></div><br>