90 m_origin_image_width(0),
91 m_origin_image_height(0)
101 m_origin_image_width(aFFT.m_origin_image_width),
102 m_origin_image_height(aFFT.m_origin_image_height)
111 m_real = aFFT.m_real;
113 m_origin_image_width = aFFT.m_origin_image_width;
114 m_origin_image_height = aFFT.m_origin_image_height;
126 fft.m_origin_image_width = anImage.
getWidth();
127 fft.m_origin_image_height = anImage.
getHeight();
129 unsigned int width_power_of_two(powerOfTwo(fft.m_origin_image_width));
130 unsigned int height_power_of_two(powerOfTwo(fft.m_origin_image_height));
132 if (width_power_of_two != 1)
134 width_power_of_two = (std::max(width_power_of_two, height_power_of_two));
137 if (height_power_of_two != 1)
139 height_power_of_two = (std::max(width_power_of_two, height_power_of_two));
142 fft.m_real =
Image<T>(width_power_of_two, height_power_of_two, anImage.
getDepth());
143 fft.m_img =
Image<T>(width_power_of_two, height_power_of_two, anImage.
getDepth());
145 fftw_complex *in_src, *out_src;
148 in_src =
reinterpret_cast<fftw_complex*
>(fftw_malloc(
sizeof(fftw_complex) * width_power_of_two * height_power_of_two));
149 out_src =
reinterpret_cast<fftw_complex*
>(fftw_malloc(
sizeof(fftw_complex) * width_power_of_two * height_power_of_two));
151 if (width_power_of_two == 1 || height_power_of_two == 1)
153 p_forw = fftw_plan_dft_1d(std::max(width_power_of_two, height_power_of_two), in_src, out_src, FFTW_FORWARD, FFTW_ESTIMATE);
157 p_forw = fftw_plan_dft_2d(width_power_of_two, height_power_of_two, in_src, out_src, FFTW_FORWARD, FFTW_ESTIMATE);
161 bool y_forward_copy(
false);
164 for (
unsigned int k(0); k < anImage.
getDepth(); ++k)
166 for (
int j1 = 0 ; j1 < height_power_of_two ; ++j1)
168 if (!(j1 % fft.m_origin_image_height))
170 y_forward_copy = !y_forward_copy;
178 j2 = fft.m_origin_image_height - 1;
182 bool x_forward_copy(
false);
184 for (
int i1 = 0 ; i1 < width_power_of_two ; ++i1)
186 if (!(i1 % fft.m_origin_image_width))
188 x_forward_copy = !x_forward_copy;
196 i2 = fft.m_origin_image_width - 1;
200 in_src[j1 * width_power_of_two + i1][0] = anImage(i2, j2, k);
201 in_src[j1 * width_power_of_two + i1][1] = 0.0;
224 fftw_execute(p_forw);
227 double square_size(width_power_of_two * height_power_of_two);
229 for (
int j = 0 ; j < height_power_of_two ; ++j)
231 for (
int i = 0 ; i < width_power_of_two ; ++i)
233 fft.m_real(i, j, k) = out_src[j * width_power_of_two + i][0] / square_size;
234 fft.m_img( i, j, k) = out_src[j * width_power_of_two + i][1] / square_size;
239 fftw_destroy_plan(p_forw);
245 throw Exception(__FILE__, __FUNCTION__, __LINE__,
"FFTW not supported");
255 Image<T> temp(m_real.getWidth(), m_real.getHeight(), m_real.getDepth());
258 fftw_complex *in_src, *out_src;
261 in_src =
reinterpret_cast<fftw_complex*
>(fftw_malloc(
sizeof(fftw_complex) * m_real.getWidth() * m_real.getHeight()));
262 out_src =
reinterpret_cast<fftw_complex*
>(fftw_malloc(
sizeof(fftw_complex) * m_real.getWidth() * m_real.getHeight()));
265 if (m_real.getWidth() == 1 || m_real.getHeight() == 1)
267 p_back = fftw_plan_dft_1d(std::max(m_real.getWidth(), m_real.getHeight()), in_src, out_src, FFTW_BACKWARD, FFTW_ESTIMATE);
271 p_back = fftw_plan_dft_2d(m_real.getWidth(), m_real.getHeight(), in_src, out_src, FFTW_BACKWARD, FFTW_ESTIMATE);
275 for (
unsigned int k(0); k < m_real.getDepth(); ++k)
277 for (
unsigned int j(0); j < m_real.getHeight(); ++j)
279 for (
unsigned int i(0); i < m_real.getWidth(); ++i)
281 in_src[j * m_real.getWidth() + i][0] = m_real(i, j, k);
282 in_src[j * m_real.getWidth() + i][1] = m_img(i, j, k);
287 fftw_execute(p_back);
290 for (
unsigned int j(0); j < m_real.getHeight(); ++j)
292 for (
unsigned int i(0); i < m_real.getWidth(); ++i)
294 temp(i, j, k) = out_src[j * m_real.getWidth() + i][0];
301 fftw_destroy_plan(p_back);
302 fftw_free(in_src); fftw_free(out_src);
304 return (temp.getROI(0, 0, 0, m_origin_image_width, m_origin_image_height, m_real.getDepth()));
306 throw Exception(__FILE__, __FUNCTION__, __LINE__,
"FFTW not supported");
315 FFT filtered_fft(*
this);
317 if (filtered_fft.m_real.getWidth() == 1 || filtered_fft.m_real.getHeight() == 1)
319 double half_size(std::max(filtered_fft.m_real.getWidth(), filtered_fft.m_real.getHeight()) / 2.0);
321 for (
unsigned int i(0); i < filtered_fft.m_real.getWidth() * filtered_fft.m_real.getHeight(); ++i)
323 double distance(
std::abs(half_size - i));
324 distance /= half_size;
326 filtered_fft.m_real[i] *= 1.0 - distance;
327 filtered_fft.m_img[ i] *= 1.0 - distance;
332 double half_diagonal_size(std::sqrt(std::pow(filtered_fft.m_real.getWidth(), 2) + std::pow(filtered_fft.m_real.getHeight(), 2)) / 2.0);
333 double half_size(filtered_fft.m_real.getWidth() / 2.0);
335 for (
unsigned int j(0); j < filtered_fft.m_real.getHeight(); ++j)
337 for (
unsigned int i(0); i < filtered_fft.m_real.getWidth(); ++i)
339 double distance(std::sqrt(std::pow(half_size - i, 2) + std::pow(half_size - j, 2)));
340 distance /= half_diagonal_size;
342 filtered_fft.m_real(i, j) *= 1.0 - distance;
343 filtered_fft.m_img(i, j) *= 1.0 - distance;
348 return (filtered_fft);
354 FFT<T> filtered_fft(*
this);
356 unsigned int size(filtered_fft.m_real.getWidth());
357 unsigned int half_size(size / 2);
359 std::vector<double> p_filter(half_size, 1.0);
363 if ((aFilterType !=
"none" && aFilterType !=
"None" && aFilterType !=
"NONE") ||
364 aFilterType ==
"ramp" || aFilterType ==
"Ramp" || aFilterType ==
"RAMP")
366 for (
unsigned int i(0); i < p_filter.size(); ++i)
368 double distance(
std::abs(
double(half_size - i)));
369 distance /= half_size;
370 distance = aScalingFactor * (1.0 - distance);
372 p_filter[i] = distance;
376 if (aFilterType ==
"hamming" || aFilterType ==
"Hamming" || aFilterType ==
"HAMMING")
381 for (
unsigned int i(0); i < half_size; ++i)
385 float c1 = 1.0 - (0.54 - 0.46 * std::cos (2.0 *
Pi *
float(i) /
float(
m)));
392 else if (aFilterType ==
"hann" || aFilterType ==
"Hann" || aFilterType ==
"HANN" || aFilterType ==
"hanning" || aFilterType ==
"Hanning" || aFilterType ==
"HANNING")
394 throw Exception(__FILE__, __FUNCTION__, __LINE__,
"rho_filter: Unknown window type");
396 else if (aFilterType ==
"cosine" || aFilterType ==
"Cosine" || aFilterType ==
"COSINE")
400 throw Exception(__FILE__, __FUNCTION__, __LINE__,
"rho_filter: Unknown window type");
402 else if (aFilterType ==
"shepp-logan" || aFilterType ==
"Shepp-logan" || aFilterType ==
"Shepp-Logan" || aFilterType ==
"SHEPP-LOGAN")
408 throw Exception(__FILE__, __FUNCTION__, __LINE__,
"rho_filter: Unknown window type");
410 else if (!(aFilterType ==
"ramp" || aFilterType ==
"Ramp" || aFilterType ==
"RAMP"))
412 throw Exception(__FILE__, __FUNCTION__, __LINE__,
"rho_filter: Unknown window type");
415 for (
unsigned int k(0); k < filtered_fft.m_real.getDepth(); ++k)
417 for (
unsigned int j(0); j < filtered_fft.m_real.getHeight(); ++j)
419 for (
unsigned int i(0); i < p_filter.size(); ++i)
421 filtered_fft.m_real(i, j, k) *= p_filter[i];
422 filtered_fft.m_img( i, j, k) *= p_filter[i];
424 filtered_fft.m_real(size - 1 - i, j, k) *= p_filter[i];
425 filtered_fft.m_img( size - 1 - i, j, k) *= p_filter[i];
430 return (filtered_fft);
436 return (rhoFilter(std::string(aFilterType), aScalingFactor));
444 Image<T> temp(m_real.getWidth(), m_real.getHeight());
446 double square_size(m_real.getWidth() * m_real.getHeight());
448 for(
int j = 0 ; j < m_real.getHeight() ; ++j)
450 for(
int i = 0 ; i < m_real.getWidth() ; ++i)
452 unsigned int index(j * m_real.getWidth() + i);
453 double real(m_real[index] / square_size);
454 double img(m_img[index] / square_size);
456 temp[index] = std::sqrt(real * real + img * img);
460 return (swapQuadrants(temp));
469 Image<T> temp(m_real.getWidth(), m_real.getHeight());
471 double square_size(m_real.getWidth() * m_real.getHeight());
473 for(
int j = 0 ; j < m_real.getHeight() ; ++j)
475 for(
int i = 0 ; i < m_real.getWidth() ; ++i)
477 unsigned int index(j * m_real.getWidth() + i);
478 double real(m_real[index] / square_size);
479 double img(m_img[index] / square_size);
482 std::complex<double> complex_value(real, img);
483 double phase_value = arg(complex_value) +
Pi;
485 temp[index] = (phase_value / (2.0 *
Pi));
489 return (swapQuadrants(temp));
497 while (j < i) j *= 2;
503 template<
typename T> Image<T> FFT<T>::swapQuadrants(
const Image<T>& anImage)
505 Image<T> temp_image(anImage);
508 int half_width(temp_image.getWidth() / 2);
511 int half_height(temp_image.getHeight() / 2);
513 if (temp_image.getWidth() == 1)
515 for(
unsigned int i = 0; i < half_width; ++i)
518 unsigned int index_i(i + half_width);
520 float temp(temp_image[i]);
521 temp_image[i] = temp_image[index_i];
522 temp_image[index_i] = temp;
525 else if (temp_image.getHeight() == 1)
527 for(
unsigned int j = 0; j < half_height; ++j)
530 unsigned int index_j(j + half_height);
532 float temp(temp_image[j * temp_image.getWidth()]);
533 temp_image[j * temp_image.getWidth()] = temp_image[index_j * temp_image.getWidth()];
534 temp_image[index_j * temp_image.getWidth()] = temp;
540 for(
unsigned int j = 0; j < half_height; ++j)
543 unsigned int index_j(j + half_height);
545 for(
unsigned int i = 0; i < half_width; ++i)
548 unsigned int index_i(i + half_width);
550 float temp(temp_image[j * temp_image.getWidth() + i]);
551 temp_image[j * temp_image.getWidth() + i] = temp_image[index_j * temp_image.getWidth() + index_i];
552 temp_image[index_j * temp_image.getWidth() + index_i] = temp;
554 temp = temp_image[index_j * temp_image.getWidth() + i];
555 temp_image[index_j * temp_image.getWidth() + i] = temp_image[j * temp_image.getWidth() + index_i];
556 temp_image[j * temp_image.getWidth() + index_i] = temp;
FFT()
Default constructor.
static FFT< T > computeFFT(const Image< T > &anImage)
FFT< T > rhoFilter(const std::string &aFilterType, float aScalingFactor)
Exception is a class to handle exceptions.
Generic class to handle exceptions.
Image is a class to manage a greyscale image.
Image< T > getPhase() const
unsigned int getHeight() const
Number of pixels along the vertical axis.
unsigned int getDepth() const
Number of pixels along the Z axis.
unsigned int getWidth() const
Number of pixels along the horizontal axis.
Image< T > abs(const Image< T > &anImage)
Image< T > getInverseFFT() const
FFT is a class to compute the FFT of a greyscale image.
Image< T > getMagnitude() const
FFT< T > & operator=(const FFT< T > &aFFT)
Assignment operator (also called copy operator).
FFT< T > filterRamp() const