[Insight-users] RecursiveGaussianImageFilter

Silvano Agliozzo agliozzo at isiosf.isi.it
Mon, 9 Feb 2004 20:19:14 +0100 (CET)


Hi Luis and Mathieu,

I'm working with double values. The min of the 3D images is around -3000 
housfield, whereas the max varies between 500-1000.

On Mon, 9 Feb 2004, Mathieu Malaterre wrote:

> Luis Ibanez wrote:
> > 
> > Hi Silvano,
> > 
> > You are right, the results of the derivative shouldn't
> > change when you add a constant value to the input image.
> 
> Except if you are overflow. Are you working on char / unsigned char 
> image ? Then you have great chance to be overflow even if you only add a 
> small constant. BTW if you are unsigned don't add any negative value or 
> check first the scalar range (=min/max) of your image.
> 
> 
> Mathieu
> 
> 

I'm going to joint hereafter a code that generate a spherical intensity 
field with the following equation x^2 + y^2 + z^2. So the derivatives 
should be egual to :
pdx = 2*x, pdy = 2*y, pdx = 2*z, 
pdxy = pdxz = pdyz = 0,
pdxx = pdyy = pdzz = 2.

the values are almost close to the expected ones execpt for the pdxx, 
pdyy, pdzz, but with the right choice of the sigma of the different 
filters, one can obtain better results. Nevertheless if you add a constant, 
like reported in the code you'll get different results, at least this is what 
I obtained. I have to leave now, but I'm looking forward to read your 
answer tomorrow morning. Thank you,

#include <iostream>
#include <vector>

#include "itkRecursiveGaussianImageFilter.h"
#include "itkImportImageFilter.h"
#include "itkImageRegionConstIterator.h"
#include "itkImageDuplicator.h"
#include "itkImage.h"
#include <string.h>
    
struct PartialDerivative
{
    double x, y, z, xy, xz, yz, xx, yy, zz;
};
    
int main()
{   
    int i, j, k;
    unsigned short dimx = 100;
    unsigned short dimy = 100;
    unsigned short dimz = 100;
    unsigned long numberOfElements = dimx * dimy *dimz;

    int half = 49;

    double *volume = new double[numberOfElements];

    typedef double pixelType;

    typedef itk::Image<pixelType, 3> ImageType;

    typedef itk::ImageRegionConstIterator< ImageType > 
RegionConstIteratorType;

    typedef itk::ImageDuplicator< ImageType > ImageDuplicatorType;
        
    ImageType::Pointer vol = ImageType::New();

    ImageType::IndexType begin;
    
    begin[0] = 0;
    begin[1] = 0;
    begin[2] = 0;

    ImageType::SizeType size;
    
    size[0] = dimx;
    size[1] = dimy;
    size[2] = dimz;

    ImageType::RegionType region;

    region.SetIndex(begin);
    region.SetSize(size);
    double spacing[ ImageType::ImageDimension ];
    spacing[0] = 1.0; // along X direction
    spacing[1] = 1.0; // along Y direction
    spacing[2] = 1.0; // along Z direction

    double origin[ ImageType::ImageDimension ];
    origin[0] = 0.0; // X coordinate
    origin[1] = 0.0; // Y coordinate
    origin[2] = 0.0; // Z coordinate

    vol->SetRegions(region);
    vol->Allocate();
    vol->SetSpacing( spacing );
    vol->SetOrigin( origin );

    ImageType::IndexType pixelIndex;
    ImageType::PixelType value;

    std::cout<<"Getting Volume ...";

    //here you can set the value of the constant 
    //to be added to the values of the 3D image
    ImageType::PixelType constant = 0;// +/- 1000 or even much more 

    for(k = 0; k < dimz ; k++)
        for(j = 0; j < dimy; j++)
            for(i = 0; i < dimx; i++)
            {
                pixelIndex[0] = i;
                pixelIndex[1] = j;
                pixelIndex[2] = k;

                // getting a spherical intensity field
                value = (static_cast<double>(i-half)*static_cast<double>(i-half)+static_cast<double>(j-half)*static_cast<double>(j-half)+static_cast<double>(k-half)*static_cast<double>(k-half));
                value += constant;
                vol->SetPixel(pixelIndex, value);
            }

    std::cout<<"done"<<std::endl;

    std::cout<<"Getting a surface ...";

    std::vector<ImageType::IndexType> s ;

    RegionConstIteratorType volIt( vol, vol->GetRequestedRegion() );

    for(volIt.GoToBegin(); !volIt.IsAtEnd(); ++volIt)
    {
            if(volIt.Value() == 324+constant)//324 = 18^2
                s.push_back(volIt.GetIndex());
    }

    std::cout<<"done"<<std::endl;
    typedef itk::RecursiveGaussianImageFilter< ImageType, ImageType > 
FilterType;

    FilterType::Pointer filterX = FilterType::New();
    FilterType::Pointer filterY = FilterType::New();
    FilterType::Pointer filterZ = FilterType::New();

    filterX->SetNormalizeAcrossScale(false);
    filterY->SetNormalizeAcrossScale(false);
    filterZ->SetNormalizeAcrossScale(false);

    filterX->SetDirection(0);
    filterY->SetDirection(1);
    filterZ->SetDirection(2);

    filterX->SetInput(vol);
    filterY->SetInput(filterX->GetOutput());
    filterZ->SetInput(filterY->GetOutput());

    ImageDuplicatorType::Pointer duplicator = ImageDuplicatorType::New();

    duplicator->SetInputImage( filterZ->GetOutput() );

    std::cout<<"Getting pdx ...";
    filterX->SetOrder(FilterType::FirstOrder);
    filterY->SetOrder(FilterType::ZeroOrder);
    filterZ->SetOrder(FilterType::ZeroOrder);

    filterX->SetSigma(1.0);
    filterY->SetSigma(1.0);
    filterZ->SetSigma(1.0);

    std::cout<<"filter updating ...";

    filterZ->Update();

    duplicator->Update();

    std::cout<<"getting output ...";

    ImageType::Pointer pdx = duplicator->GetOutput();

    std::cout<<"done"<<std::endl;

    //pdy

    std::cout<<"Getting pdy ...";
    filterX->SetOrder(FilterType::ZeroOrder);
    filterY->SetOrder(FilterType::FirstOrder);
    filterZ->SetOrder(FilterType::ZeroOrder);
    filterX->SetSigma(1.0);
    filterY->SetSigma(1.0);
    filterZ->SetSigma(1.0);

    std::cout<<"filter updating ...";

    filterZ->Update();

    duplicator->Update();

    std::cout<<"getting output ...";

    ImageType::Pointer pdy = duplicator->GetOutput();

    std::cout<<"done"<<std::endl;

    //pdz

    std::cout<<"Getting pdz ...";

    filterX->SetOrder(FilterType::ZeroOrder);
    filterY->SetOrder(FilterType::ZeroOrder);
    filterZ->SetOrder(FilterType::FirstOrder);
    filterX->SetSigma(1.0);
    filterY->SetSigma(1.0);
    filterZ->SetSigma(1.0);

    std::cout<<"filter updating ...";

    filterZ->Update();

    duplicator->Update();

    std::cout<<"getting output ...";

    ImageType::Pointer pdz =duplicator->GetOutput();

    std::cout<<"done"<<std::endl;

    //pdxy

    std::cout<<"Getting pdxy ...";

    filterX->SetOrder(FilterType::FirstOrder);
    filterY->SetOrder(FilterType::FirstOrder);
    filterZ->SetOrder(FilterType::ZeroOrder);

    filterX->SetSigma(1.0);
    filterY->SetSigma(1.0);
    filterZ->SetSigma(1.0);

    std::cout<<"filter updating ...";

    filterZ->Update();

    duplicator->Update();

    std::cout<<"getting output ...";

    ImageType::Pointer pdxy = duplicator->GetOutput();

    std::cout<<"done"<<std::endl;

        //pdxz

    std::cout<<"Getting pdxz ...";
    filterX->SetOrder(FilterType::FirstOrder);
    filterY->SetOrder(FilterType::ZeroOrder);
    filterZ->SetOrder(FilterType::FirstOrder);

    filterX->SetSigma(1.0);
    filterY->SetSigma(1.0);
    filterZ->SetSigma(1.0);

    std::cout<<"filter updating ...";

    filterZ->Update();
    duplicator->Update();

    std::cout<<"getting output ...";

    ImageType::Pointer pdxz = duplicator->GetOutput();

    std::cout<<"done"<<std::endl;

        //pdyz

    std::cout<<"Getting pdyz ...";

    filterX->SetOrder(FilterType::ZeroOrder);
    filterY->SetOrder(FilterType::FirstOrder);
    filterZ->SetOrder(FilterType::FirstOrder);
    filterX->SetSigma(1.0);
    filterY->SetSigma(1.0);
    filterZ->SetSigma(1.0);

    std::cout<<"filter updating ...";

    filterZ->Update();

    duplicator->Update();
    std::cout<<"getting output ...";

    ImageType::Pointer pdyz = duplicator->GetOutput();

    std::cout<<"done"<<std::endl;

        //pdxx

    std::cout<<"Getting pdxx ...";

    filterX->SetOrder(FilterType::SecondOrder);
    filterY->SetOrder(FilterType::ZeroOrder);
    filterZ->SetOrder(FilterType::ZeroOrder);
    filterX->SetSigma(1.0);
    filterY->SetSigma(1.0);
    filterZ->SetSigma(1.0);

    std::cout<<"filter updating ...";

    filterZ->Update();

    duplicator->Update();

    std::cout<<"getting output ...";

    ImageType::Pointer pdxx = duplicator->GetOutput();

    std::cout<<"done"<<std::endl;

        //pdyy

    std::cout<<"Getting pdyy ...";

    filterX->SetOrder(FilterType::ZeroOrder);
    filterY->SetOrder(FilterType::SecondOrder);
    filterZ->SetOrder(FilterType::ZeroOrder);

    filterX->SetSigma(1.0);
    filterY->SetSigma(1.0);
    filterZ->SetSigma(1.0);

    std::cout<<"filter updating ...";

    filterZ->Update();

    duplicator->Update();

    std::cout<<"getting output ...";

    ImageType::Pointer pdyy = duplicator->GetOutput();
    std::cout<<"done"<<std::endl;

    //pdzz

    std::cout<<"Getting pdzz ...";

    filterX->SetOrder(FilterType::ZeroOrder);
    filterY->SetOrder(FilterType::ZeroOrder);
    filterZ->SetOrder(FilterType::SecondOrder);

    filterX->SetSigma(1.0);
    filterY->SetSigma(1.0);
    filterZ->SetSigma(1.0);

    std::cout<<"filter updating ...";

    filterZ->Update();

    duplicator->Update();

    std::cout<<"getting output ...";

    ImageType::Pointer pdzz = duplicator->GetOutput();

    std::cout<<"done"<<std::endl;

    PartialDerivative PD;

    unsigned long pos;

    for( i = 0; i < s.size(); ++i )
    {
        pixelIndex = s.at(i);

        //first order derivatives
        PD.x = pdx->GetPixel(pixelIndex);
        PD.y = pdy->GetPixel(pixelIndex);
        PD.z = pdz->GetPixel(pixelIndex);

        //second order derivatives
        PD.xy = pdxy->GetPixel(pixelIndex);
        PD.xz = pdxz->GetPixel(pixelIndex);
        PD.yz = pdyz->GetPixel(pixelIndex);

        PD.xx = pdxx->GetPixel(pixelIndex);
        PD.yy = pdyy->GetPixel(pixelIndex);
        PD.zz = pdzz->GetPixel(pixelIndex);

        std::cout<<"x "<<pixelIndex[0]<<" y "<<pixelIndex[1]<<" z 
"<<pixelIndex[2]<<std::endl;
        std::cout<<"pdx "<<PD.x<<" pdy "<<PD.y<<" pdz "<<PD.z<<std::endl;
        std::cout<<"pdxy "<<PD.xy<<" pdxz "<<PD.xz<<" pdyz 
"<<PD.yz<<std::endl;
        std::cout<<"pdxx "<<PD.xx<<" pdyy "<<PD.yy<<" pdzz 
"<<PD.zz<<std::endl;

    }

    return 0;
}