92 unsigned int aNumberOfSlices):
93 Image<T>(aWidth, aHeight, aNumberOfSlices)
99 Image<T> projection_set(this->m_width, this->m_number_of_slices, this->m_height);
103 #pragma omp parallel for 105 #pragma omp parallel for collapse(2) 108 for (
int angle_id = 0; angle_id < this->m_height; ++angle_id)
110 for (
int row_projection_id = 0; row_projection_id < this->m_number_of_slices; ++row_projection_id)
112 const T* p_input(this->getRawData() + angle_id * this->m_width + row_projection_id * this->m_width * this->m_height);
113 T* p_output(projection_set.
getRawData() + angle_id * this->m_width * this->m_number_of_slices + this->m_width * row_projection_id);
115 std::copy(p_input, p_input + this->m_width, p_output);
118 return (projection_set);
125 unsigned int aNumberOfIterations,
126 const char* aDirectory,
130 unsigned int image_width(2 * floor (this->m_width / (2.0 * std::sqrt(2.0))));
133 Image<T> new_estimated_image(image_width, image_width, this->m_number_of_slices, this->getSum() / (image_width * image_width));
134 Image<T> old_estimated_image(image_width, image_width, this->m_number_of_slices, this->getSum() / (image_width * image_width));
140 unsigned int iteration(1);
144 old_estimated_image = new_estimated_image;
147 double angle(aFirstAngle);
148 for (
unsigned int angle_id(0); angle_id < this->m_height; ++angle_id, angle += anAngleStep)
151 Image<T> estimated_projection(new_estimated_image.
radonTransform(angle, 0.0, angle).setCanvasSize(this->m_width, 1, this->m_number_of_slices));
155 Image<T> real_projection(this->getROI(0, angle_id, 0, this->m_width, 1, this->m_number_of_slices));
158 Sinogram<T> error_in_projections = (real_projection - estimated_projection);
163 new_estimated_image += error_back_projection.
setCanvasSize(image_width, image_width, this->m_number_of_slices);
166 for (
unsigned int i(0); i < new_estimated_image.
getWidth() * new_estimated_image.
getHeight() * new_estimated_image.
getDepth(); ++i, ++p_temp)
168 *p_temp = std::max(0.0f, *p_temp);
173 std::stringstream filename;
174 filename << aDirectory <<
"/iteration_" << iteration <<
"_" << angle_id <<
".mha";
175 (new_estimated_image.
setCanvasSize(image_width, image_width, this->m_number_of_slices).normalised() * 255).savePGM(filename.str());
180 (*aCallback)(&new_estimated_image, &estimated_projection, &error_back_projection);
185 Image<T> estimated_projections(new_estimated_image.
radonTransform(aFirstAngle, anAngleStep, this->m_height).setCanvasSize(this->m_width, this->m_height, this->m_number_of_slices));
188 double ncc_projections(100.0 * this->computeNCC(estimated_projections));
189 double ncc_reconstructions(100.0 * new_estimated_image.
computeNCC(old_estimated_image));
191 if ((ncc_projections > 99.50 || ncc_reconstructions > 99.50) )
195 else if (aNumberOfIterations == iteration)
200 old_ncc = ncc_reconstructions;
207 (*aCallback)(&new_estimated_image, &estimated_projections, &error_back_projection);
211 return (new_estimated_image.
setCanvasSize(image_width, image_width, this->m_number_of_slices));
218 unsigned int aNumberOfIterations,
219 const char* aDirectory,
223 unsigned int image_width(2 * floor (this->m_width / (2.0 * std::sqrt(2.0))));
226 Image<T> new_estimated_image(image_width, image_width, this->m_number_of_slices, this->getSum() / (image_width * image_width));
227 Image<T> old_estimated_image(image_width, image_width, this->m_number_of_slices, this->getSum() / (image_width * image_width));
233 unsigned int iteration(1);
237 old_estimated_image = new_estimated_image;
240 double angle(aFirstAngle);
241 for (
unsigned int angle_id(0); angle_id < this->m_height; ++angle_id, angle += anAngleStep)
244 Image<T> estimated_projection(new_estimated_image.
radonTransform(angle, 0.0, angle).setCanvasSize(this->m_width, 1, this->m_number_of_slices));
248 Image<T> real_projection(this->getROI(0, angle_id, 0, this->m_width, 1, this->m_number_of_slices));
251 Sinogram<T> error_in_projections(real_projection - estimated_projection);
256 new_estimated_image *= error_back_projection.
setCanvasSize(image_width, image_width, this->m_number_of_slices);
259 for (
unsigned int i(0); i < new_estimated_image.
getWidth() * new_estimated_image.
getHeight() * new_estimated_image.
getDepth(); ++i, ++p_temp)
261 *p_temp = std::max(0.0f, *p_temp);
266 std::stringstream filename;
267 filename << aDirectory <<
"/iteration_" << iteration <<
"_" << angle_id <<
".mha";
268 (new_estimated_image.
setCanvasSize(image_width, image_width, this->m_number_of_slices).normalised() * 255).savePGM(filename.str());
273 (*aCallback)(&new_estimated_image, &estimated_projection, &error_back_projection);
278 Image<T> estimated_projections(new_estimated_image.
radonTransform(aFirstAngle, anAngleStep, this->m_height).setCanvasSize(this->m_width, this->m_height, this->m_number_of_slices));
281 double ncc_projections(100.0 * this->computeNCC(estimated_projections));
282 double ncc_reconstructions(100.0 * new_estimated_image.
computeNCC(old_estimated_image));
284 if ((ncc_projections > 99.50 || ncc_reconstructions > 99.50) )
288 else if (aNumberOfIterations == iteration)
293 old_ncc = ncc_reconstructions;
300 (*aCallback)(&new_estimated_image, &estimated_projections, &error_back_projection);
304 return (new_estimated_image.
setCanvasSize(image_width, image_width, this->m_number_of_slices));
311 unsigned int aNumberOfIterations,
312 const char* aDirectory,
316 unsigned int image_width(2 * floor (this->m_width / (2.0 * std::sqrt(2.0))));
319 Image<T> new_estimated_image(image_width, image_width, this->m_number_of_slices, this->getSum() / (image_width * image_width));
320 Image<T> old_estimated_image(image_width, image_width, this->m_number_of_slices, this->getSum() / (image_width * image_width));
325 unsigned int iteration(1);
329 old_estimated_image = new_estimated_image;
331 Image<T> estimated_projection(new_estimated_image.
radonTransform(aFirstAngle, anAngleStep, this->m_height));
334 Sinogram<T> error_in_projections(*
this - estimated_projection);
336 this->saveASCII(
"real_projection.mat");
337 estimated_projection.saveASCII(
"estimated_projection.mat");
338 error_in_projections.
saveASCII(
"error_in_projections.mat");
340 Image<T> error_back_projection(error_in_projections.simpleBackProjection(aFirstAngle, anAngleStep));
341 error_back_projection.
saveASCII(
"error_back_projection.mat");
344 new_estimated_image += error_back_projection.
setCanvasSize(image_width, image_width, this->m_number_of_slices);
345 new_estimated_image.
saveASCII(
"new_estimated_image.mat");
346 old_estimated_image.
saveASCII(
"old_estimated_image.mat");
349 for (
unsigned int i(0); i < new_estimated_image.
getWidth() * new_estimated_image.
getHeight() * new_estimated_image.
getDepth(); ++i, ++p_temp)
351 *p_temp = std::max(0.0f, *p_temp);
356 std::stringstream filename;
357 filename << aDirectory <<
"/iteration_" << iteration <<
".mha";
358 (new_estimated_image.
setCanvasSize(image_width, image_width, this->m_number_of_slices).normalised() * 255).savePGM(filename.str());
364 (*aCallback)(&new_estimated_image, &estimated_projection, &error_back_projection);
368 Image<T> estimated_projections(new_estimated_image.
radonTransform(aFirstAngle, anAngleStep, this->m_height).setCanvasSize(this->m_width, this->m_height, this->m_number_of_slices));
369 estimated_projections.
saveASCII(
"simulated_projection.mat");
372 double ncc_projections(100.0 * this->computeNCC(estimated_projections));
373 double ncc_reconstructions(100.0 * new_estimated_image.
computeNCC(old_estimated_image));
375 if ((ncc_projections > 99.50 || ncc_reconstructions > 99.50) )
379 else if (aNumberOfIterations == iteration)
384 old_ncc = ncc_reconstructions;
390 return (new_estimated_image.
setCanvasSize(image_width, image_width, this->m_number_of_slices));
397 const char* aDirectory,
401 Image<T> sinogram(this->resize(this->m_width * 2, this->m_height, this->m_number_of_slices));
403 unsigned int image_width(2 * floor (sinogram.
getWidth() / (2.0 * std::sqrt(2.0))));
407 double angle(aFirstAngle);
408 for (
unsigned int angle_id(0);
409 angle_id < this->m_height;
410 ++angle_id, angle += anAngleStep)
416 #pragma omp parallel for 418 #pragma omp parallel for collapse(3) 421 for (
int k = 0; k < reconstruction.getDepth(); ++k)
423 for (
int j = 0; j < reconstruction.getHeight(); ++j)
425 for (
int i = 0; i < reconstruction.getWidth(); ++i)
427 back_projection(i, j, k) += sinogram.
getPixel(i, angle_id, k);
432 reconstruction += back_projection.rotate(-angle) / reconstruction.getHeight();
436 std::stringstream filename;
437 filename << aDirectory <<
"/angle_" << angle_id <<
".mha";
438 (reconstruction.setCanvasSize(image_width, image_width, reconstruction.getDepth()).resize(image_width / 2, image_width / 2, reconstruction.getDepth()).normalised() * 255).savePGM(filename.str());
444 (*aCallback)(&reconstruction, &back_projection,
this);
450 reconstruction = reconstruction.setCanvasSize(image_width, image_width, this->m_number_of_slices);
451 reconstruction *=
Pi / ( this->getHeight());
453 return (reconstruction.resize(image_width / 2, image_width / 2, this->getDepth()));
460 const char* aFilterType,
461 float aScalingFactor,
462 const char* aDirectory,
466 typedef FFT<T> FAST_FOURIER_TRANSFORM;
469 std::vector<FAST_FOURIER_TRANSFORM> p_fft_set;
470 for (
unsigned int j(0); j < this->m_height; ++j)
472 p_fft_set.push_back(this->getROI(0, j, 0, this->m_width, 1, this->m_number_of_slices).getFFT());
476 for (
typename std::vector<FAST_FOURIER_TRANSFORM>::iterator ite(p_fft_set.begin());
477 ite != p_fft_set.end();
480 *ite = ite->rhoFilter(aFilterType, aScalingFactor);
484 std::vector<Image<T> > p_ifft_set(this->m_height);
485 for (
unsigned int j(0); j < this->m_height; ++j)
487 p_ifft_set[j] = p_fft_set[j].getInverseFFT();
491 Sinogram<T> filtered_sinogram(this->m_width, this->m_height, this->m_number_of_slices);
493 for (
unsigned int k(0); k < this->m_number_of_slices; ++k)
495 for (
unsigned int j(0); j < this->m_height; ++j)
497 for (
unsigned int i(0); i < this->m_width; ++i)
499 filtered_sinogram(i, j, k) = p_ifft_set[j](i, 0, k);
517 unsigned int aNumberOfIterations,
518 const std::string& aDirectory,
522 return (art(aFirstAngle,
533 unsigned int aNumberOfIterations,
534 const std::string& aDirectory,
538 return (mart(aFirstAngle,
549 unsigned int aNumberOfIterations,
550 const std::string& aDirectory,
554 return (sirt(aFirstAngle,
565 const std::string& aDirectory,
569 return (simpleBackProjection(aFirstAngle,
579 const std::string& aFilterType,
580 float aScalingFactor,
581 const std::string& aDirectory,
585 return (filteredBackProjection(aFirstAngle,
Image< T > simpleBackProjection(double aFirstAngle, double anAngleStep, const char *aDirectorye=0, void(*aCallback)(const Image< T > *, const Image< T > *, const Image< T > *)=0) const
void saveASCII(const char *aFileName) const
Save the image in an ASCII file.
T & getPixel(unsigned int i, unsigned int j, unsigned int k=0)
Accessor on a pixel value.
Sinogram is a class to reconstruct images from a sinogram.
T * getRawData()
Accessor on the raw data.
gVirtualXRay::Sinogram< T > radonTransform(double aFirstAngle, double anAngleStep, double aLastAngle) const
Image is a class to manage a greyscale image.
unsigned int getHeight() const
Number of pixels along the vertical axis.
unsigned int getDepth() const
Number of pixels along the Z axis.
Class to compute the FFT of a greyscale image.
Image< T > setCanvasSize(unsigned int aNewWidth, unsigned int aNewHeight, unsigned int aNewNumberOfSlices) const
unsigned int getWidth() const
Number of pixels along the horizontal axis.
FFT is a class to compute the FFT of a greyscale image.
double computeNCC(const Image< T > &anImage) const