Skip to content

RL: Perform voxel-by-voxel division #82

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ endif()

SET(VERSION_MAJOR 1)
SET(VERSION_MINOR 2)
SET(VERSION_PATCH 9)
SET(VERSION_PATCH 10)

MAKE_DIRECTORY(${PROJECT_BINARY_DIR}/config)

Expand Down
5 changes: 4 additions & 1 deletion lib/petpvcRLPVCImageFilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <itkExtractImageFilter.h>
#include <itkMultiplyImageFilter.h>
#include <itkDivideImageFilter.h>
#include <itkCastImageFilter.h>
#include <itkAddImageFilter.h>
#include <itkSubtractImageFilter.h>
#include <itkDiscreteGaussianImageFilter.h>
Expand Down Expand Up @@ -89,7 +90,6 @@ class RichardsonLucyPVCImageFilter:public ImageToImageFilter< TInputImage, TInpu
this->m_vecVariance = vec;
}


ITKVectorType GetPSF() {
return this->m_vecVariance;
}
Expand All @@ -114,6 +114,9 @@ class RichardsonLucyPVCImageFilter:public ImageToImageFilter< TInputImage, TInpu
/** Does the real work. */
virtual void GenerateData() ITK_OVERRIDE;

// Calculate threshold at which a value is zeroed
float GetZeroThreshold( typename TInputImage::ConstPointer img );

ITKVectorType m_vecVariance;
unsigned int m_nIterations;
float m_fStopCriterion;
Expand Down
97 changes: 82 additions & 15 deletions lib/petpvcRLPVCImageFilter.txx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,25 @@ RichardsonLucyPVCImageFilter< TInputImage >
this->m_fStopCriterion = -3e+06;
}

template< class TInputImage >
float RichardsonLucyPVCImageFilter< TInputImage >
::GetZeroThreshold( typename TInputImage::ConstPointer img )
{
// Default threshold to zero values at:
const float fZeroThreshold = 1e-4f;

// Calculate image statistics
typename StatisticsFilterType::Pointer statsFilter = StatisticsFilterType::New();
statsFilter->SetInput( img );
statsFilter->Update();

// Return default or (image max * default ) as new threshold
const float fNewThreshold = std::min( fZeroThreshold, statsFilter->GetMaximum() * fZeroThreshold );

// Set to zero if somehow new threshold is negative!
return std::max( fNewThreshold , 0.0f );
}

template< class TInputImage >
void RichardsonLucyPVCImageFilter< TInputImage >
::GenerateData()
Expand Down Expand Up @@ -79,50 +98,98 @@ void RichardsonLucyPVCImageFilter< TInputImage >
typename TInputImage::Pointer imageEstimate;
//Set image estimate to the original non-negative PET data for the first iteration.
imageEstimate = duplicator->GetOutput();
imageEstimate->DisconnectPipeline();

// Create a blank image with same dimensions as input to use for division
duplicator->SetInputImage(imageEstimate);
duplicator->Update();

typedef itk::CastImageFilter< TInputImage, TInputImage > CastImageFilterType;
typename CastImageFilterType::Pointer castFilter = CastImageFilterType::New();
castFilter->SetInput( duplicator->GetOutput() );
castFilter->Update();
typename TInputImage::Pointer blankImage = castFilter->GetOutput();

typedef typename TInputImage::PixelType PixelType;
blankImage->FillBuffer( itk::NumericTraits< PixelType >::Zero );

// Image to store result of division
typename TInputImage::Pointer dividedImage;

int nMaxNumOfIters = this->m_nIterations;
int n=1;

bool bStopped = false;


while ( ( n <= nMaxNumOfIters ) && ( !bStopped ) ) {
float fLog = 0.0;
float fLog = 0.0;
// f_k * h
blurFilter->SetInput( imageEstimate );
divideFilter->SetInput1( thresholdFilter->GetOutput() );
divideFilter->SetInput2( blurFilter->GetOutput() );
blurFilter->Update();

// Perform f(x) / [ f_k(x) * h ] voxel-by-voxel as itk::DivideFilterType sets image
// to max if denominator is 0.
ConstImageIterator numeratorIt( thresholdFilter->GetOutput(), thresholdFilter->GetOutput()->GetLargestPossibleRegion() );
ConstImageIterator denomIt( blurFilter->GetOutput(), blurFilter->GetOutput()->GetLargestPossibleRegion() );

duplicator->SetInputImage(blankImage);
duplicator->Update();
dividedImage = duplicator->GetOutput();
dividedImage->DisconnectPipeline();

ImageRegionIterator<TInputImage> divIt( dividedImage, dividedImage->GetLargestPossibleRegion() );

numeratorIt.GoToBegin();
denomIt.GoToBegin();
divIt.GoToBegin();

// Get zero threshold
const float fSmallNum = this->GetZeroThreshold( blurFilter->GetOutput() );

while ( !divIt.IsAtEnd() )
{
if ( denomIt.Get() > fSmallNum )
divIt.Set(numeratorIt.Get() / denomIt.Get());
else
divIt.Set(itk::NumericTraits< PixelType >::Zero);

++numeratorIt;
++denomIt;
++divIt;
}

// Reblur correction factors
blurFilter2->SetInput( dividedImage );
blurFilter2->Update();

// Multiply current image estimate by reblurred correction factors
multiplyFilter->SetInput1( imageEstimate );
multiplyFilter->SetInput2( divideFilter->GetOutput() );
multiplyFilter->SetInput2( blurFilter2->GetOutput() );
multiplyFilter->Update();


// Update image estimate
imageEstimate = multiplyFilter->GetOutput();
imageEstimate->DisconnectPipeline();

blurFilter2->SetInput( imageEstimate );
blurFilter2->Update();

ConstImageIterator origIt( thresholdFilter->GetOutput(), thresholdFilter->GetOutput()->GetLargestPossibleRegion() );
ConstImageIterator currIt( blurFilter2->GetOutput(), blurFilter2->GetOutput()->GetLargestPossibleRegion() );
ConstImageIterator currIt( imageEstimate, imageEstimate->GetLargestPossibleRegion() );

origIt.GoToBegin();
currIt.GoToBegin();

while ( !currIt.IsAtEnd() )
{
if (currIt.Get() > 0.0) {
float diff = origIt.Get() * log(currIt.Get()) - currIt.Get();
fLog += diff;
fLog += origIt.Get() * log(currIt.Get()) - currIt.Get();
}

++currIt;
++origIt;
}

float fCurrentEval = fLog;
std::cout << n << "\t" << fCurrentEval << std::endl;
n++;

//if ( fCurrentEval < this->m_fStopCriterion )
// bStopped = true;
}
std::cout << std::endl;

Expand Down