[vtkusers] trigger the execution of a vtkThreadedImageAlgorithm derived filter by calling Update()

Gomez, Alberto alberto.gomez at kcl.ac.uk
Wed Dec 16 06:34:25 EST 2015


Hi all,

I am trying to write a multithreaded filter (vtkMeanSSD), derived from 
vtkThreadedImageAlgorithm, which will calculate the mean value of the 
difference between the intensities of two images (mean SSD).

What I want to achieve is that when I call Update() on my filter, the 
calculations occur and then I can retrieve the value by calling another 
method GetValue(). This is the snippet from my main file:


vtkSmartPointer<vtkMeanSSD> myfilter = vtkSmartPointer<vtkMeanSSD>::New();
myfilter->SetInput1Data(im1);
myfilter->SetInput2Data(im2);
myfilter->Update();
double val = myfilter->GetValue(); // value is 0, which is the default 
by construction

The problem I have is that when I call myfilter->Update() the filter is 
not executed. For some reason, it does execute if I plug it to a writer, 
for example


vtkSmartPointer<vtkMeanSSD> myfilter = vtkSmartPointer<vtkMeanSSD>::New();
myfilter->SetInput1Data(im1);
myfilter->SetInput2Data(im2);

  vtkSmartPointer<vtkNIFTIImageWriter> writer 
=vtkSmartPointer<vtkNIFTIImageWriter>::New();
writer->SetFileName("image_SSD.nii");
writer->SetInputConnection(myfilter->GetOutputPort());
writer->Write(); // This triggers the execution
double val = myfilter->GetValue(); // good value

Any advice how I can trigger the ThreadedRequestData method by calling 
update? Is there any other better way to achieve the functionality I want?

Thanks for your help. The full filter code is below.

Alberto




=======================================  vtkMeanSSD.h 
=======================================


// .NAME vtkMeanSSD - Simple SSD image-image filter.
// .SECTION Description
// This calculates the mean sum of squared differences
// 1/N*sum (a -b)^2


#ifndef vtkMeanSSD_h
#define vtkMeanSSD_h

#include "vtkImagingGeneralModule.h" // For export macro
#include "vtkThreadedImageAlgorithm.h"

class VTKIMAGINGGENERAL_EXPORT vtkMeanSSD : public vtkThreadedImageAlgorithm
{
public:


     static vtkMeanSSD *New();
     vtkTypeMacro(vtkMeanSSD,vtkThreadedImageAlgorithm);


     // Description:
     // Set the two inputs to this filter
     virtual void SetInput1Data(vtkDataObject *in) { 
this->SetInputData(0,in); }
     virtual void SetInput2Data(vtkDataObject *in) { 
this->SetInputData(1,in); }

     // Description:
     // Get the metric value from the images.  This is
     // computed when Update() is called.
     double GetValue() {return this->m_value;}


protected:

     vtkMeanSSD();
     ~vtkMeanSSD() {}

     virtual void ThreadedRequestData(vtkInformation *request,
                                      vtkInformationVector **inputVector,
                                      vtkInformationVector *outputVector,
                                      vtkImageData ***inData,
                                      vtkImageData **outData,
                                      int extent[6], int threadId);

     double m_value;

private:

     vtkMeanSSD(const vtkMeanSSD&);  // Not implemented.
     void operator=(const vtkMeanSSD&);  // Not implemented.


};

#endif







// VTK-HeaderTest-Exclude: vtkMeanSSD.h


=======================================  vtkMeanSSD.cxx 
=======================================


#include "vtkMeanSSD.h"

#include "vtkImageData.h"
#include "vtkImageProgressIterator.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkStreamingDemandDrivenPipeline.h"

vtkStandardNewMacro(vtkMeanSSD);

//----------------------------------------------------------------------------
vtkMeanSSD::vtkMeanSSD()
{
     this->SetNumberOfInputPorts(2);
     this->m_value = 0;
}


//----------------------------------------------------------------------------
// This templated function executes the filter for any type of data.
// Handles the two input operations
template <class T>
void vtkMeanSSDExecute(vtkMeanSSD *self,
                             vtkImageData *in1Data,
                             vtkImageData *in2Data,
                             double *value,
                             int outExt[6], int id, T *)
{
     vtkImageIterator<T> inIt1(in1Data, outExt);
     vtkImageIterator<T> inIt2(in2Data, outExt);

     // find the region to loop over
     int N = in1Data->GetNumberOfPoints();
     float val = 0;

     // sum (a -b)*(a-b)
     /// Calculate the average of each image

     while (!inIt1.IsAtEnd())
     {
         T* inSI1 = inIt1.BeginSpan();
         T* inSI2 = inIt2.BeginSpan();
         T* inSI1End = inIt1.EndSpan();

         while (inSI1 != inSI1End){

             T v1 = static_cast<float>(*inSI1);
             T v2 = static_cast<float>(*inSI2);
             val += (v1-v2)*(v1-v2);
             ++inSI1;
             ++inSI2;
         }
         inIt1.NextSpan();
         inIt2.NextSpan();
     }
     val/=N;

     *value  = val;

}



//----------------------------------------------------------------------------
// This method is passed a input and output regions, and executes the filter
// algorithm to fill the output from the inputs.
// It just executes a switch statement to call the correct function for
// the regions data types.
void vtkMeanSSD::ThreadedRequestData(
         vtkInformation * vtkNotUsed( request ),
         vtkInformationVector ** vtkNotUsed( inputVector ),
         vtkInformationVector * vtkNotUsed( outputVector ),
         vtkImageData ***inData,
         vtkImageData **outData,
         int outExt[6], int id)
{
     // this filter expects that input is the same type as output.
     if (inData[0][0]->GetScalarType() != outData[0]->GetScalarType())
     {
         vtkErrorMacro(<< "Execute: input1 ScalarType, "
                       <<  inData[0][0]->GetScalarType()
                 << ", must match output ScalarType "
                 << outData[0]->GetScalarType());
         return;
     }

     if (inData[1][0]->GetScalarType() != outData[0]->GetScalarType())
     {
         vtkErrorMacro(<< "Execute: input2 ScalarType, "
                       << inData[1][0]->GetScalarType()
                 << ", must match output ScalarType "
                 << outData[0]->GetScalarType());
         return;
     }

     // this filter expects that inputs that have the same number of 
components
     if (inData[0][0]->GetNumberOfScalarComponents() !=
             inData[1][0]->GetNumberOfScalarComponents())
     {
         vtkErrorMacro(<< "Execute: input1 NumberOfScalarComponents, "
                       << inData[0][0]->GetNumberOfScalarComponents()
                 << ", must match out input2 NumberOfScalarComponents "
                 << inData[1][0]->GetNumberOfScalarComponents());
         return;
     }

     switch (inData[0][0]->GetScalarType())
     {
     double d;
     vtkTemplateMacro(
                 vtkMeanSSDExecute(this, inData[0][0],
             inData[1][0], &this->m_value, outExt, id,
             static_cast<VTK_TT *>(0)));
     default:
         vtkErrorMacro(<< "Execute: Unknown ScalarType");
         return;
     }
}

-- 
Dr Alberto Gomez
Research Associate
Department of Biomedical Engineering
King's College London

020 7188 7188 ext 50871
4th North Wing
St Thomas' Hospital
SE1 7EH London, UK



More information about the vtkusers mailing list