[vtkusers] How to get the input to a filter as algorithm output?

Bill Lorensen bill.lorensen at gmail.com
Tue Dec 15 11:53:52 EST 2009


After seeing Berk's reply it looks as though his
vtkImageData* inputCopy = input->NewInstance();
inputCopy->ShallowCopy(input);
blend->AddInput(inputCopy);
blend->Update();
output->ShallowCopy(blend->GetOutput());

would be:

blend->AddInput(input);
blend->Update()
this->GraftOutput(blend->GetOutput());

And here is a more complex minipipeline that implements a SobelEdgeDetector:

  // Create the sobel operator
  SobelOperator<OutputPixelType, ImageDimension> opers[ImageDimension];
  ZeroFluxNeumannBoundaryCondition<TOutputImage> nbc;

  // Setup mini-pipelines along each axis.
  typename OpFilter::Pointer opFilter[ImageDimension];
  typename MultFilter::Pointer multFilter[ImageDimension];
  typename AddFilter::Pointer addFilter = AddFilter::New();
  typename SqrtFilter::Pointer sqrtFilter =  SqrtFilter::New();
  for(i=0; i < ImageDimension; ++i)
    {
    // Create the filters for this axis.
    opFilter[i] = OpFilter::New();
    multFilter[i] = MultFilter::New();

    // Set boundary condition and operator for this axis.
    opers[i].SetDirection(i);
    opers[i].CreateDirectional();
    opFilter[i]->OverrideBoundaryCondition(&nbc);
    opFilter[i]->SetOperator(opers[i]);

    // Setup the mini-pipeline for this axis.
    opFilter[i]->SetInput(this->GetInput());
    multFilter[i]->SetInput1(opFilter[i]->GetOutput());
    multFilter[i]->SetInput2(opFilter[i]->GetOutput());

    // All axes' mini-pipelines come together in addFilter.
    addFilter->SetInput(i, multFilter[i]->GetOutput());
    }

  // calculate the gradient magnitude
  sqrtFilter->SetInput(addFilter->GetOutput());

  // setup the mini-pipeline to calculate the correct regions and
  // write to the appropriate bulk data block
  sqrtFilter->GraftOutput( this->GetOutput() );

  // execute the mini-pipeline
  sqrtFilter->Update();

  // graft the mini-pipeline output back onto this filter's output.
  // this is needed to get the appropriate regions passed back.
  this->GraftOutput(sqrtFilter->GetOutput());

On Tue, Dec 15, 2009 at 11:44 AM, Bill Lorensen <bill.lorensen at gmail.com> wrote:
> ITK has mechanisms to support minipipelines and they are used
> frequently in filters. The main facility is a Graft method that each
> DataObject implements. Filters implement GraftOutput() methods that
> Graft() a data object to a filter's output. Here is the documentation
> for an image's Graft method:
>  /** Graft the data and information from one image to another. This
>   * is a convenience method to setup a second image with all the meta
>   * information of another image and use the same pixel
>   * container. Note that this method is different than just using two
>   * SmartPointers to the same image since separate DataObjects are
>   * still maintained. This method is similar to
>   * ImageSource::GraftOutput(). The implementation in ImageBase
>   * simply calls CopyInformation() and copies the region ivars.
>   * Subclasses of ImageBase are responsible for copying the pixel
>   * container. */
>
> It may be an interesting future project to see if such a mechanism can
> be added to VTK.
>
> Bill
>
>
> On Tue, Dec 15, 2009 at 9:41 AM, David Gobbi <david.gobbi at gmail.com> wrote:
>> Where to start... there are a couple important items here.
>>
>> First, there's nothing wrong with directly accessing data objects when
>> you are writing a VTK filter.  Obviously the filter must access the
>> data.  That's completely different from accessing the data objects
>> outside of the filters, and whenever I said "don't mess with the data
>> objects", I really meant "if you want to mess with the data, then
>> write a filter".
>>
>> Second item: In VTK it isn't safe to write a VTK filter that executes
>> other VTK filters inside of it.  Which is really unfortunate, because
>> it sure is a useful thing to be able to do.  But if you look through
>> all the filters in VTK (i.e. vtkAlgorithm derived objects), you will
>> not find a single one that does this.
>>
>> Each vtkAlgorithm has an executive that deals with the vtkInformation
>> and sends Requests to the vtkAlgorithm.  If, internally, you grab the
>> algorithm's input and feed it into your little "internal pipeline",
>> then that internal pipeline will propagate its own requests to the
>> input's producer.  As a result a RequestData in the main (external)
>> pipeline can cause the internal pipeline to update, which causes all
>> sorts of requests to be sent up both the internal and external
>> pipeline before the RequestData completes.  This is a violation of the
>> usual, careful way that the pipeline is supposed to step its way
>> through the various requests.  It may result in undefined behavior of
>> the pipeline.
>>
>> It would be nice if someone devised a recipe for how to safely use a
>> mini-pipeline inside a VTK filter, by using deep copies of the data
>> objects or whatnot, but so far I haven't seen one.  About the closest
>> thing that I've done is use ITK from inside a VTK filter.
>>
>>   David
>>
>>
>> On Tue, Dec 15, 2009 at 1:18 AM, Jérôme <jerome.velut at gmail.com> wrote:
>>> Hi David D.,
>>>
>>> If I understood well, you write VTK pipeline inside a VTK filter. If so, I
>>> also do that *very* often. My way avoids to get the input data, just
>>> connects the input:
>>> blend->AddInputconnection( this->GetInputConnection( ) ); // 'this' being
>>> your vtkAlgorithm-derived filter.
>>>
>>> Secondly, I read with interest the thread in which David G. taught about VTK
>>> pipelining. And I don't think he would have your head for using the
>>> old-fashioned SetInput method. It is just like... old-fashioned, but you
>>> don't "touch" at the data. It is unfair because you add some -maybe-
>>> unuseful static cast, but the integrity of the pipeline is still preserved.
>>>
>>> David G. can you confirm my feelings?
>>>
>>> Jerome
>>>
>>> 2009/12/15 David Doria <daviddoria+vtk at gmail.com>
>>>>
>>>> The first thing I typically do (and I got this by looking at existing
>>>> filters) at the beginning of a RequestData() is:
>>>>
>>>>  vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
>>>>  vtkImageData *input = vtkImageData::SafeDownCast(
>>>>      inInfo->Get(vtkDataObject::DATA_OBJECT()));
>>>>
>>>> However, now I have an actual object, so I have to do things like the
>>>> following:
>>>>
>>>>  vtkSmartPointer<vtkImageBlend> blend =
>>>> vtkSmartPointer<vtkImageBlend>::New();
>>>>  //blend->AddInputConnection(input->GetOutputPort()); //can't do this
>>>> because 'input' is not an algorithm output
>>>>  blend->AddInput(input);
>>>>
>>>> David G. would have my head for this! How should this be done instead?
>>>>
>>>> Thanks,
>>>>
>>>> David D.
>>>> _______________________________________________
>>>> Powered by www.kitware.com
>>>>
>>>> Visit other Kitware open-source projects at
>>>> http://www.kitware.com/opensource/opensource.html
>>>>
>>>> Please keep messages on-topic and check the VTK FAQ at:
>>>> http://www.vtk.org/Wiki/VTK_FAQ
>>>>
>>>> Follow this link to subscribe/unsubscribe:
>>>> http://www.vtk.org/mailman/listinfo/vtkusers
>>>
>>>
>>> _______________________________________________
>>> Powered by www.kitware.com
>>>
>>> Visit other Kitware open-source projects at
>>> http://www.kitware.com/opensource/opensource.html
>>>
>>> Please keep messages on-topic and check the VTK FAQ at:
>>> http://www.vtk.org/Wiki/VTK_FAQ
>>>
>>> Follow this link to subscribe/unsubscribe:
>>> http://www.vtk.org/mailman/listinfo/vtkusers
>>>
>>>
>> _______________________________________________
>> Powered by www.kitware.com
>>
>> Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html
>>
>> Please keep messages on-topic and check the VTK FAQ at: http://www.vtk.org/Wiki/VTK_FAQ
>>
>> Follow this link to subscribe/unsubscribe:
>> http://www.vtk.org/mailman/listinfo/vtkusers
>>
>



More information about the vtkusers mailing list