|
a |
|
b/region_growing.cxx |
|
|
1 |
#include <iostream> |
|
|
2 |
#include <string> |
|
|
3 |
#include "stdlib.h" |
|
|
4 |
|
|
|
5 |
#include "itkImageRegionIterator.h" |
|
|
6 |
#include "itkImageRegionConstIterator.h" |
|
|
7 |
#include "itkImageRegionIteratorWithIndex.h" |
|
|
8 |
#include "itkImageFileReader.h" |
|
|
9 |
#include "itkImageFileWriter.h" |
|
|
10 |
#include "itkImportImageFilter.h" |
|
|
11 |
|
|
|
12 |
const unsigned short dimension = 3; |
|
|
13 |
|
|
|
14 |
typedef float floatVoxelType; |
|
|
15 |
typedef itk::Image<floatVoxelType, dimension> ImageType; |
|
|
16 |
typedef itk::Point< float, ImageType::ImageDimension > PointType; |
|
|
17 |
typedef itk::ImageRegionIterator<ImageType> OutputIterType; |
|
|
18 |
|
|
|
19 |
class Regiongrowing { |
|
|
20 |
public: |
|
|
21 |
ImageType::Pointer OutputImage; |
|
|
22 |
|
|
|
23 |
unsigned int xs; |
|
|
24 |
unsigned int ys; |
|
|
25 |
unsigned int zs; |
|
|
26 |
|
|
|
27 |
Regiongrowing(const ImageType::Pointer& image, float thresh_val) { |
|
|
28 |
// This method is to compute the 3D region growing |
|
|
29 |
// :params image: the 3D lung mask image |
|
|
30 |
// :params thresh_val: the threshold value for region growing |
|
|
31 |
OutputImage = ImageType::New(); |
|
|
32 |
OutputImage->SetRegions( image->GetLargestPossibleRegion() ); |
|
|
33 |
OutputImage->Allocate(true); // initialize buffer to zero |
|
|
34 |
|
|
|
35 |
OutputIterType OutputIter(OutputImage,image->GetLargestPossibleRegion()); |
|
|
36 |
|
|
|
37 |
int shape[3]; |
|
|
38 |
xs = image->GetLargestPossibleRegion().GetSize()[0]; |
|
|
39 |
ys = image->GetLargestPossibleRegion().GetSize()[1]; |
|
|
40 |
zs = image->GetLargestPossibleRegion().GetSize()[2]; |
|
|
41 |
|
|
|
42 |
// compute region growing |
|
|
43 |
float label = 1; |
|
|
44 |
for (int z = 0; z < zs; z++){ |
|
|
45 |
for (int y = 0; y < ys; y++){ |
|
|
46 |
for (int x = 0; x < xs; x++){ |
|
|
47 |
PointType point; |
|
|
48 |
point[0] = x; |
|
|
49 |
point[1] = y; |
|
|
50 |
point[2] = z; |
|
|
51 |
ImageType::IndexType out_index; |
|
|
52 |
|
|
|
53 |
image->TransformPhysicalPointToIndex( point, out_index ); |
|
|
54 |
ImageType::PixelType p_vec = image->GetPixel(out_index); |
|
|
55 |
if (OutputImage->GetPixel(out_index) == 0 && p_vec != 0){ |
|
|
56 |
int volume = 1; |
|
|
57 |
int *vol_point = &volume; |
|
|
58 |
this->region_growing(image, point, label, thresh_val, vol_point); |
|
|
59 |
label = label + 1; |
|
|
60 |
} |
|
|
61 |
} |
|
|
62 |
} |
|
|
63 |
} |
|
|
64 |
} |
|
|
65 |
void region_growing(const ImageType::Pointer& , PointType, float, float, int *); |
|
|
66 |
}; |
|
|
67 |
void Regiongrowing::region_growing(const ImageType::Pointer& image, PointType point, float label, float thresh_val, int *vol_point){ |
|
|
68 |
//This function is to compute region growing. |
|
|
69 |
// :params image: the image for region growing |
|
|
70 |
// :params point: the point for region growing |
|
|
71 |
// :params label: point label |
|
|
72 |
// :params thresh_val: the threshold value |
|
|
73 |
// :params vol_point: the volume for given label to limit the number of recursive. |
|
|
74 |
float x = point[0]; float y = point[1]; float z = point[2]; |
|
|
75 |
|
|
|
76 |
PointType neighbors[6]; |
|
|
77 |
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; |
|
|
78 |
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; |
|
|
79 |
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; |
|
|
80 |
|
|
|
81 |
ImageType::IndexType p_index; |
|
|
82 |
image->TransformPhysicalPointToIndex( point, p_index ); |
|
|
83 |
ImageType::PixelType p = image->GetPixel( p_index ); |
|
|
84 |
|
|
|
85 |
for (int i = 0; i < 6; i++){ |
|
|
86 |
if (neighbors[i][0] >= 0 && neighbors[i][0] < xs && |
|
|
87 |
neighbors[i][1] >= 0 && neighbors[i][1] < ys && |
|
|
88 |
neighbors[i][2] >= 0 && neighbors[i][2] < zs){ |
|
|
89 |
ImageType::IndexType out_index; |
|
|
90 |
image->TransformPhysicalPointToIndex( neighbors[i], out_index ); |
|
|
91 |
if (OutputImage->GetPixel(out_index) == 0){ |
|
|
92 |
ImageType::PixelType np = image->GetPixel( out_index ); |
|
|
93 |
float diff = std::abs(np - p); |
|
|
94 |
if (np > 0 && *vol_point < 20000){ |
|
|
95 |
OutputImage->SetPixel( out_index, label); |
|
|
96 |
*vol_point = *vol_point + 1; |
|
|
97 |
this->region_growing(image, neighbors[i], label, thresh_val, vol_point); |
|
|
98 |
|
|
|
99 |
} |
|
|
100 |
} |
|
|
101 |
} |
|
|
102 |
} |
|
|
103 |
} |
|
|
104 |
|
|
|
105 |
|
|
|
106 |
|
|
|
107 |
int main( int argc, char * argv[] ) |
|
|
108 |
{ |
|
|
109 |
time_t tStart = clock(); |
|
|
110 |
|
|
|
111 |
if( argc < 2 ) { |
|
|
112 |
std::cerr << "Usage: " << std::endl; |
|
|
113 |
std::cerr << argv[0] << " inputImageFile outputImageFile" << std::endl; |
|
|
114 |
return EXIT_FAILURE; |
|
|
115 |
} |
|
|
116 |
|
|
|
117 |
typedef itk::ImageFileReader< ImageType > readerType; |
|
|
118 |
|
|
|
119 |
float thresh = 0.1; |
|
|
120 |
|
|
|
121 |
// Read Image |
|
|
122 |
readerType::Pointer reader = readerType::New(); |
|
|
123 |
reader->SetFileName( argv[1] ); |
|
|
124 |
reader->Update(); |
|
|
125 |
|
|
|
126 |
// Compute eigenvalues |
|
|
127 |
std::cout << " Region Growing " << std::endl; |
|
|
128 |
Regiongrowing rg = Regiongrowing::Regiongrowing( reader->GetOutput(), thresh ); |
|
|
129 |
|
|
|
130 |
std::cout << " Saving Image..." << std::endl; |
|
|
131 |
typedef itk::ImageFileWriter < ImageType > WriterType; |
|
|
132 |
WriterType::Pointer writer = WriterType::New(); |
|
|
133 |
writer->SetFileName( argv[2] ); |
|
|
134 |
writer->SetInput( rg.OutputImage ); |
|
|
135 |
|
|
|
136 |
writer->Update(); |
|
|
137 |
printf("Time taken: %.2fs\n", (float)(clock() - tStart)/CLOCKS_PER_SEC); |
|
|
138 |
|
|
|
139 |
return EXIT_SUCCESS; |
|
|
140 |
} |