Diff of /vector_region_growing.cxx [000000] .. [4c12f9]

Switch to unified view

a b/vector_region_growing.cxx
1
#include <iostream>
2
#include <string>
3
#include "stdlib.h"
4
#include <math.h>  
5
#include <unordered_set>
6
7
#include "itkImageRegionIterator.h"
8
#include "itkImageRegionConstIterator.h"
9
#include "itkImageRegionIteratorWithIndex.h"
10
#include "itkHessianRecursiveGaussianImageFilter.h"
11
#include "itkCastImageFilter.h"
12
#include "itkImageFileReader.h"
13
#include "itkImageFileWriter.h"
14
#include "itkImportImageFilter.h"
15
#include "itkMedianImageFilter.h"
16
17
const unsigned short dimension = 3;
18
typedef int VoxelType;
19
typedef float outVoxelType;
20
typedef itk::Image<VoxelType, dimension> InputImageType;
21
typedef itk::Image<outVoxelType, dimension> OutputImageType;
22
typedef itk::Point< float, InputImageType::ImageDimension > PointType;
23
24
typedef float HessianVoxelType;
25
typedef itk::Image<HessianVoxelType, dimension> HessianInnerImageType;
26
typedef itk::CastImageFilter<InputImageType, HessianInnerImageType> CastFilterType;
27
28
typedef itk::HessianRecursiveGaussianImageFilter<HessianInnerImageType> HFilterType;
29
typedef itk::Vector<HessianVoxelType, dimension> VecVoxType;
30
typedef itk::Matrix<HessianVoxelType, dimension, dimension> MatVoxType;
31
typedef itk::Image<VecVoxType, dimension> VecEigHImageType;
32
typedef itk::Image<MatVoxType, dimension> MatEigHImageType;
33
34
typedef itk::MedianImageFilter<OutputImageType, OutputImageType > MedianImageFilterType;
35
typedef itk::ImportImageFilter< outVoxelType, dimension >   ImportFilterType;
36
typedef itk::ImageRegionIterator<OutputImageType> OutputImageIterType;
37
typedef itk::ImageRegionIterator<VecEigHImageType> OutputIterType;
38
typedef itk::ImageRegionIterator<InputImageType> InputImageIterType;
39
typedef itk::SymmetricEigenAnalysis<MatVoxType, VecVoxType, MatVoxType> EigValAnalysisType;
40
typedef MatEigHImageType::Pointer MatEigHImagePointerType;
41
typedef MatEigHImageType::RegionType MatRegionType;
42
typedef MatEigHImageType::PointType MatPointType;
43
typedef MatEigHImageType::SpacingType MatSpacingType;
44
45
typedef VecEigHImageType::Pointer VecEigHImagePointerType;
46
typedef itk::ImageRegionIteratorWithIndex<HFilterType::OutputImageType> HIterType;
47
48
class cmp
49
{
50
public:
51
    bool operator() (  HessianVoxelType a,  HessianVoxelType b )
52
    {
53
        return std::abs(a) < std::abs(b) ;
54
    }
55
};
56
57
class EigValHessian {
58
public:
59
    MatRegionType region;
60
    MatSpacingType spacing;
61
    MatPointType origin;
62
63
    CastFilterType::Pointer CastFilter;
64
    HFilterType::Pointer HFilter;
65
66
    EigValAnalysisType EigValAnalysis;
67
68
    VecEigHImagePointerType VecEigHImagePointer;
69
70
    OutputImageType::Pointer OutputImage;
71
72
    ImportFilterType::Pointer importFilter;
73
74
    std::unordered_set<outVoxelType> label_set;
75
76
    MedianImageFilterType::Pointer medianFilter;
77
78
    EigValHessian(const InputImageType::Pointer& image, float sigma, float alpha, float beta, float gama) {
79
        // This method is to compute the Hessian matrix by ITK filter: HessianRecursiveGaussianImageFilter
80
        // Furthermore, calculte the fissure structure measurement with given parameters and then using vector 
81
        // based region growing method to segment fissures.
82
        // :params image: the 3D lung mask image
83
        // :params sigma: the standard deviation for Gaussian function in Hessian matrix
84
        // :params alpha, beta, gama: parameters for fissure representation
85
        VecVoxType EigVal;
86
        MatVoxType EigMat,tmpMat;
87
        for(int i=0;i<3;i++)
88
            for(int j=0;j<3;j++)
89
                EigMat[i][j]=0;
90
91
        region=image->GetLargestPossibleRegion();
92
        spacing=image->GetSpacing();
93
        origin=image->GetOrigin();
94
95
        // initialize the Hassian filter
96
        CastFilter = CastFilterType::New();
97
        HFilter = HFilterType::New();
98
        HFilter->SetSigma(sigma);
99
100
        EigValAnalysis.SetDimension(3);
101
        CastFilter->SetInput(image);
102
        HFilter->SetInput(CastFilter->GetOutput());
103
104
        printf("Processing HFilter\n");
105
        HFilter->Update();
106
107
        VecEigHImagePointer=VecEigHImageType::New();
108
        VecEigHImagePointer->SetRegions(region);
109
        VecEigHImagePointer->SetOrigin(origin);
110
        VecEigHImagePointer->SetSpacing(spacing);
111
        VecEigHImagePointer->Allocate();
112
113
        EigVal[0]=EigVal[1]=EigVal[2]=0;
114
        VecEigHImagePointer->FillBuffer(EigMat[0]);
115
116
        OutputImage = OutputImageType::New();
117
        OutputImage->SetRegions( region );
118
        OutputImage->Allocate(true); // initialize buffer to zero
119
120
        HIterType HIter(HFilter->GetOutput(),region);
121
122
        OutputIterType OutputIter(VecEigHImagePointer,region);
123
124
        itk::SymmetricSecondRankTensor<float,3> Tensor;
125
126
        bool fissure_cond = true;
127
128
        InputImageIterType InputImageIter(image, region);
129
130
        // this is the mean and std value for vessel which is compute according to
131
        // histogram analysis in previous result.
132
        outVoxelType mean = 198.275350;
133
        outVoxelType std = 42.571917;
134
135
        outVoxelType vessel_thesh = mean - 3 * std;
136
137
        for(HIter.GoToBegin(),OutputIter.GoToBegin(),InputImageIter.GoToBegin();
138
            !HIter.IsAtEnd()&&!OutputIter.IsAtEnd()&&!InputImageIter.IsAtEnd();
139
            ++HIter,++OutputIter,++InputImageIter){
140
            Tensor=HIter.Get();
141
            tmpMat[0][0]=Tensor[0];
142
            tmpMat[0][1]=Tensor[1];
143
            tmpMat[1][0]=Tensor[1];
144
            tmpMat[0][2]=Tensor[2];
145
            tmpMat[2][0]=Tensor[2];
146
            tmpMat[1][1]=Tensor[3];
147
            tmpMat[2][1]=Tensor[4];
148
            tmpMat[1][2]=Tensor[4];
149
            tmpMat[2][2]=Tensor[5];
150
151
            // compute the eigenvalues given a 3*3 Hessian matrix.
152
            EigValAnalysis.ComputeEigenValuesAndVectors(tmpMat,EigVal,EigMat);
153
154
            // obtain the maximum absolute value for eigenvalues
155
            HessianVoxelType sortedEigVal[3] = {EigVal[0],EigVal[1],EigVal[2]};
156
157
            std::sort(sortedEigVal, sortedEigVal+3, cmp());
158
159
            // Compute Structure
160
            HessianVoxelType theta;
161
            if (sortedEigVal[2] >= 0){
162
              theta = 0;
163
            }else{
164
              theta = 1;
165
            }
166
            HessianVoxelType Fstructure, Fsheet, Sfissure;
167
            Fstructure = theta * exp(-1*(pow((std::abs(sortedEigVal[2])-alpha)/beta,6)));
168
            Fsheet = exp(-1*(pow(sortedEigVal[1]/gama,6)));
169
170
            Sfissure = Fstructure * Fsheet;
171
172
            // Convert to uint8 value
173
            VoxelType pixel_val = (InputImageIter.Get() + 1024) / 4;
174
175
            // Thresholding the result fissure structure measurement
176
            fissure_cond = Sfissure > 0.8 && pixel_val < vessel_thesh ? true : false;
177
178
            // Save the corresponding eigenvector for the maximum eigenvalue
179
            for (int i = 0; i < 3; i++){
180
              if (EigVal[i] == sortedEigVal[2] && fissure_cond){
181
                OutputIter.Set(EigMat[i]);
182
                break;
183
              }
184
            }
185
186
        }
187
188
        printf("Processing computing eigenvalues and eigenvectors\n");
189
        VecEigHImagePointer->Update();
190
        printf("Finish computing eigenvalues and eigenvectors\n");
191
192
        // Compute the vector based region growing with given eigenvector.
193
        const OutputImageType::RegionType region = VecEigHImagePointer->GetBufferedRegion();
194
        const OutputImageType::SizeType size = region.GetSize();
195
        const unsigned int xs = size[0];
196
        const unsigned int ys = size[1];
197
        const unsigned int zs = size[2];
198
        float label = 1;
199
        for (int z = 0; z < zs; z++){
200
          for (int y = 0; y < ys; y++){
201
            for (int x = 0; x < xs; x++){
202
              PointType point;
203
              point[0] = x;    
204
              point[1] = y;
205
              point[2] = z;  
206
              OutputImageType::IndexType out_index;
207
              VecEigHImageType::IndexType vec_index;
208
  
209
              OutputImage->TransformPhysicalPointToIndex( point, out_index );
210
              VecEigHImagePointer->TransformPhysicalPointToIndex( point, vec_index );
211
              VecEigHImageType::PixelType p_vec = VecEigHImagePointer->GetPixel(vec_index);
212
213
              if (OutputImage->GetPixel(out_index) == 0 && p_vec[0]+p_vec[1]+p_vec[2] != 0){
214
                int volume = 1;
215
                int *vol_point = &volume;
216
                this->region_growing(point, label, vol_point);
217
                label = label + 1;
218
              }
219
            }
220
          }
221
        }
222
    }
223
    void region_growing(PointType, float, int *);
224
};
225
void EigValHessian::region_growing(PointType point, float label, int *vol_point){
226
  // This function is to compute the vector based region growing.
227
  // :params point: the point for region growing
228
  // :params label: point label
229
  // :params vol_point: the volume for given label to limit the number of recursive.
230
  int x = point[0]; int y = point[1]; int z = point[2];
231
  const OutputImageType::RegionType region = VecEigHImagePointer->GetBufferedRegion();
232
  const OutputImageType::SizeType size = region.GetSize();
233
  const unsigned int xs = size[0];
234
  const unsigned int ys = size[1];
235
  const unsigned int zs = size[2];
236
237
  PointType neighbors[6];
238
  neighbors[0][0] = x+1; neighbors[1][0] = x-1; neighbors[2][0] = x; neighbors[3][0] = x; neighbors[4][0] = x; neighbors[5][0] = x;    
239
  neighbors[0][1] = y; neighbors[1][1] = y; neighbors[2][1] = y+1; neighbors[3][1] = y-1; neighbors[4][1] = y; neighbors[5][1] = y;   
240
  neighbors[0][2] = z; neighbors[1][2] = z; neighbors[2][2] = z; neighbors[3][2] = z; neighbors[4][2] = z+1; neighbors[5][2] = z-1;   
241
  
242
  VecEigHImageType::IndexType p_index;
243
  VecEigHImagePointer->TransformPhysicalPointToIndex( point, p_index );
244
    VecEigHImageType::PixelType p = VecEigHImagePointer->GetPixel( p_index );
245
    
246
  for (int i = 0; i < 6; i++){
247
    if (neighbors[i][0] >= 0 && neighbors[i][0] < xs &&
248
        neighbors[i][1] >= 0 && neighbors[i][1] < ys &&
249
        neighbors[i][2] >= 0 && neighbors[i][2] < zs){
250
      OutputImageType::IndexType out_index;
251
      OutputImage->TransformPhysicalPointToIndex( neighbors[i], out_index );
252
      if (OutputImage->GetPixel(out_index) == 0){
253
        VecEigHImageType::IndexType vec_index;
254
        VecEigHImagePointer->TransformPhysicalPointToIndex( neighbors[i], vec_index );
255
        VecEigHImageType::PixelType np = VecEigHImagePointer->GetPixel( vec_index );
256
        float product = np[0] * p[0] + np[1] * p[1] + np[2] * p[2];
257
        if (product > 0.9){
258
          *vol_point = *vol_point + 1;
259
          OutputImage->SetPixel( out_index, label);
260
          this->region_growing(neighbors[i], label, vol_point);
261
        } 
262
      }
263
    }  
264
  }
265
}
266
267
268
269
int main( int argc, char * argv[] )
270
{
271
  time_t tStart = clock();
272
273
  if( argc < 2 ) {
274
      std::cerr << "Usage: " << std::endl;
275
      std::cerr << argv[0] << "  inputImageFile  outputImageFile" << std::endl;
276
      return EXIT_FAILURE;
277
  }
278
    
279
  typedef itk::ImageFileReader< InputImageType >  readerType;
280
281
  float sigma = 0.5;
282
  float alpha = 90;
283
  float beta = 120;
284
  float gama = 100;
285
286
  // Read Image
287
  readerType::Pointer reader = readerType::New();
288
  reader->SetFileName( argv[1] );
289
  reader->Update();
290
291
  // Compute eigenvalues
292
  std::cout << "  Compute Eigenvalues " << std::endl;
293
  EigValHessian eigenvalues = EigValHessian::EigValHessian( reader->GetOutput(), sigma, alpha, beta, gama );
294
295
  std::cout << "   Saving Image..." << std::endl;
296
  typedef itk::ImageFileWriter < OutputImageType > WriterType;
297
  WriterType::Pointer writer = WriterType::New();
298
  writer->SetFileName( argv[2] );
299
  writer->SetInput( eigenvalues.OutputImage );
300
301
  writer->Update();
302
  printf("Time taken: %.2fs\n", (float)(clock() - tStart)/CLOCKS_PER_SEC);
303
304
  return EXIT_SUCCESS;
305
}