Skip to content

Commit a44f65b

Browse files
authored
RL: Perform voxel-by-voxel division (#82)
* RL: Perform voxel-by-voxel division * Set zero clipping based on image max * Bump version to 1.2.10
1 parent 088efae commit a44f65b

File tree

3 files changed

+87
-17
lines changed

3 files changed

+87
-17
lines changed

CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ endif()
2828

2929
SET(VERSION_MAJOR 1)
3030
SET(VERSION_MINOR 2)
31-
SET(VERSION_PATCH 9)
31+
SET(VERSION_PATCH 10)
3232

3333
MAKE_DIRECTORY(${PROJECT_BINARY_DIR}/config)
3434

lib/petpvcRLPVCImageFilter.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include <itkExtractImageFilter.h>
3030
#include <itkMultiplyImageFilter.h>
3131
#include <itkDivideImageFilter.h>
32+
#include <itkCastImageFilter.h>
3233
#include <itkAddImageFilter.h>
3334
#include <itkSubtractImageFilter.h>
3435
#include <itkDiscreteGaussianImageFilter.h>
@@ -89,7 +90,6 @@ class RichardsonLucyPVCImageFilter:public ImageToImageFilter< TInputImage, TInpu
8990
this->m_vecVariance = vec;
9091
}
9192

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

117+
// Calculate threshold at which a value is zeroed
118+
float GetZeroThreshold( typename TInputImage::ConstPointer img );
119+
117120
ITKVectorType m_vecVariance;
118121
unsigned int m_nIterations;
119122
float m_fStopCriterion;

lib/petpvcRLPVCImageFilter.txx

+82-15
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,25 @@ RichardsonLucyPVCImageFilter< TInputImage >
4242
this->m_fStopCriterion = -3e+06;
4343
}
4444

45+
template< class TInputImage >
46+
float RichardsonLucyPVCImageFilter< TInputImage >
47+
::GetZeroThreshold( typename TInputImage::ConstPointer img )
48+
{
49+
// Default threshold to zero values at:
50+
const float fZeroThreshold = 1e-4f;
51+
52+
// Calculate image statistics
53+
typename StatisticsFilterType::Pointer statsFilter = StatisticsFilterType::New();
54+
statsFilter->SetInput( img );
55+
statsFilter->Update();
56+
57+
// Return default or (image max * default ) as new threshold
58+
const float fNewThreshold = std::min( fZeroThreshold, statsFilter->GetMaximum() * fZeroThreshold );
59+
60+
// Set to zero if somehow new threshold is negative!
61+
return std::max( fNewThreshold , 0.0f );
62+
}
63+
4564
template< class TInputImage >
4665
void RichardsonLucyPVCImageFilter< TInputImage >
4766
::GenerateData()
@@ -79,50 +98,98 @@ void RichardsonLucyPVCImageFilter< TInputImage >
7998
typename TInputImage::Pointer imageEstimate;
8099
//Set image estimate to the original non-negative PET data for the first iteration.
81100
imageEstimate = duplicator->GetOutput();
101+
imageEstimate->DisconnectPipeline();
102+
103+
// Create a blank image with same dimensions as input to use for division
104+
duplicator->SetInputImage(imageEstimate);
105+
duplicator->Update();
106+
107+
typedef itk::CastImageFilter< TInputImage, TInputImage > CastImageFilterType;
108+
typename CastImageFilterType::Pointer castFilter = CastImageFilterType::New();
109+
castFilter->SetInput( duplicator->GetOutput() );
110+
castFilter->Update();
111+
typename TInputImage::Pointer blankImage = castFilter->GetOutput();
112+
113+
typedef typename TInputImage::PixelType PixelType;
114+
blankImage->FillBuffer( itk::NumericTraits< PixelType >::Zero );
115+
116+
// Image to store result of division
117+
typename TInputImage::Pointer dividedImage;
82118

83119
int nMaxNumOfIters = this->m_nIterations;
84120
int n=1;
85121

86122
bool bStopped = false;
87-
88123

89124
while ( ( n <= nMaxNumOfIters ) && ( !bStopped ) ) {
90-
float fLog = 0.0;
125+
float fLog = 0.0;
126+
// f_k * h
91127
blurFilter->SetInput( imageEstimate );
92-
divideFilter->SetInput1( thresholdFilter->GetOutput() );
93-
divideFilter->SetInput2( blurFilter->GetOutput() );
128+
blurFilter->Update();
129+
130+
// Perform f(x) / [ f_k(x) * h ] voxel-by-voxel as itk::DivideFilterType sets image
131+
// to max if denominator is 0.
132+
ConstImageIterator numeratorIt( thresholdFilter->GetOutput(), thresholdFilter->GetOutput()->GetLargestPossibleRegion() );
133+
ConstImageIterator denomIt( blurFilter->GetOutput(), blurFilter->GetOutput()->GetLargestPossibleRegion() );
134+
135+
duplicator->SetInputImage(blankImage);
136+
duplicator->Update();
137+
dividedImage = duplicator->GetOutput();
138+
dividedImage->DisconnectPipeline();
139+
140+
ImageRegionIterator<TInputImage> divIt( dividedImage, dividedImage->GetLargestPossibleRegion() );
141+
142+
numeratorIt.GoToBegin();
143+
denomIt.GoToBegin();
144+
divIt.GoToBegin();
145+
146+
// Get zero threshold
147+
const float fSmallNum = this->GetZeroThreshold( blurFilter->GetOutput() );
148+
149+
while ( !divIt.IsAtEnd() )
150+
{
151+
if ( denomIt.Get() > fSmallNum )
152+
divIt.Set(numeratorIt.Get() / denomIt.Get());
153+
else
154+
divIt.Set(itk::NumericTraits< PixelType >::Zero);
155+
156+
++numeratorIt;
157+
++denomIt;
158+
++divIt;
159+
}
160+
161+
// Reblur correction factors
162+
blurFilter2->SetInput( dividedImage );
163+
blurFilter2->Update();
164+
165+
// Multiply current image estimate by reblurred correction factors
94166
multiplyFilter->SetInput1( imageEstimate );
95-
multiplyFilter->SetInput2( divideFilter->GetOutput() );
167+
multiplyFilter->SetInput2( blurFilter2->GetOutput() );
96168
multiplyFilter->Update();
97-
169+
170+
// Update image estimate
98171
imageEstimate = multiplyFilter->GetOutput();
99172
imageEstimate->DisconnectPipeline();
100-
101-
blurFilter2->SetInput( imageEstimate );
102-
blurFilter2->Update();
103173

104174
ConstImageIterator origIt( thresholdFilter->GetOutput(), thresholdFilter->GetOutput()->GetLargestPossibleRegion() );
105-
ConstImageIterator currIt( blurFilter2->GetOutput(), blurFilter2->GetOutput()->GetLargestPossibleRegion() );
175+
ConstImageIterator currIt( imageEstimate, imageEstimate->GetLargestPossibleRegion() );
106176

107177
origIt.GoToBegin();
108178
currIt.GoToBegin();
109179

110180
while ( !currIt.IsAtEnd() )
111181
{
112182
if (currIt.Get() > 0.0) {
113-
float diff = origIt.Get() * log(currIt.Get()) - currIt.Get();
114-
fLog += diff;
183+
fLog += origIt.Get() * log(currIt.Get()) - currIt.Get();
115184
}
185+
116186
++currIt;
117187
++origIt;
118188
}
119189

120190
float fCurrentEval = fLog;
121191
std::cout << n << "\t" << fCurrentEval << std::endl;
122192
n++;
123-
124-
//if ( fCurrentEval < this->m_fStopCriterion )
125-
// bStopped = true;
126193
}
127194
std::cout << std::endl;
128195

0 commit comments

Comments
 (0)