Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
FFT2D.cpp
1 /*
2 This file is part of the BIAS library (Basic ImageAlgorithmS).
3 
4 Copyright (C) 2003-2009 (see file CONTACT for details)
5 Multimediale Systeme der Informationsverarbeitung
6 Institut fuer Informatik
7 Christian-Albrechts-Universitaet Kiel
8 
9 
10 BIAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
14 
15 BIAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Lesser General Public License for more details.
19 
20 You should have received a copy of the GNU Lesser General Public License
21 along with BIAS; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24 
25 
26 #include "FFT2D.hh"
27 #include <fftw3.h>
28 #include <Base/Debug/Error.hh>
29 
30 #include <complex>
31 #include <iomanip>
32 
33 using namespace BIAS;
34 using namespace std;
35 
36 template <class InputStorageType, class OutputStorageType>
39 {
40  _SizeX=0;
41  _SizeY=0;
42  _OutNum=0;
43  _in=NULL;
44  _out=NULL;
45  _p_forward=NULL;
46 }
47 
48 template <class InputStorageType, class OutputStorageType>
50 {
51  Release();
52  fftw_cleanup();
53 }
54 
55 template <class InputStorageType, class OutputStorageType>
57 Init(int width, int height)
58 {
59 #ifdef BIAS_DEBUG
60  if (_SizeX!=0 || _SizeY!=0 || _OutNum!=0 || _out || _in || _p_forward){
61  BIASERR("FFT2D: call Release() before calling Init() a second time");
62  BIASABORT;
63  }
64 #endif
65  _SizeX=height;
66  _SizeY=width;
67  _Size = _SizeX*_SizeY;
68  _OutSizeY = (_SizeY>>1)+1;
69  _OutNum=_SizeX * _OutSizeY;
70  _out =(fftw_complex*)fftw_malloc(sizeof(fftw_complex) * _OutNum);
71  _in = (double*)fftw_malloc(sizeof(double) * _Size);
72  // this is slow a few seconds
73  _p_forward = fftw_plan_dft_r2c_2d(_SizeX, _SizeY, _in, _out, FFTW_MEASURE);
74  _p_reverse = fftw_plan_dft_c2r_2d(_SizeX, _SizeY, _out, _in, FFTW_ESTIMATE);
75 }
76 
77 
78 
79 
80 
81 
82 template <class InputStorageType, class OutputStorageType>
85 {
86  if (_p_forward) fftw_destroy_plan(_p_forward);
87  if (_in) fftw_free(_in);
88  if (_out) fftw_free(_out);
89  _in=NULL;
90  _out=NULL;
91  _p_forward=NULL;
92  _SizeX=_SizeY=_Size=_OutNum=0;
93 }
94 
95 
96 template <class InputStorageType, class OutputStorageType>
99 {
100 #ifdef BIAS_DEBUG
101  if (_SizeX==0 || _SizeY==0 ){
102  BIASERR("FFT2D: call Init() before calling Filter() ");
103  BIASABORT;
104  }
105 #endif
106 
107  BIASASSERT(src.GetChannelCount() ==1);
108  BIASASSERT((int)src.GetWidth() == _SizeY);
109  BIASASSERT((int)src.GetHeight() == _SizeX);
110  // first, copy and cast src into _in
111  double *inp = _in;
112  const InputStorageType *imgp = src.GetImageData();
113  for ( int i=0;i<_Size; i++) {
114  inp[i] = (double) imgp[i];
115  }
116 
117  // run fft via _plan
118  fftw_execute(_p_forward);
119  return 0;
120 }
121 
122 
123 template <class InputStorageType, class OutputStorageType>
126 {
127 #ifdef BIAS_DEBUG
128  if (_SizeX==0 || _SizeY==0 ){
129  BIASERR("FFT2D: call Init() before calling Filter() ");
130  BIASABORT;
131  }
132 #endif
133 
134  BIASASSERT(src.GetChannelCount() ==2);
135  BIASASSERT((int)src.GetWidth() == _OutSizeY);
136  BIASASSERT((int)src.GetHeight() == _SizeX);
137  // first, copy and cast src into _in
138  fftw_complex *outp = _out;
139  const OutputStorageType *imgp = src.GetImageData();
140  for ( int i=0;i<_OutNum; i++) {
141  outp[i][0] = (double) imgp[2*i];
142  outp[i][1] = (double) imgp[2*i+1];
143  }
144 
145  // run fft via _plan
146  fftw_execute(_p_reverse);
147  return 0;
148 }
149 
150 
151 
152 
153 /** dst.GetChannelCount()==2*src.GetCHannelCount() */
154 template <class InputStorageType, class OutputStorageType>
157 {
158  Forward_(src);
159 
160  if (!dst.IsEmpty()) dst.Release();
161  dst.Init(_OutSizeY, _SizeX, 2);
162  // copy and cast back int dst, two channel mode
163  fftw_complex *outp = _out;
164  OutputStorageType *oimgp = dst.GetImageData();
165  for ( int i=0;i<_OutNum; i++){
166  oimgp[2*i] = (OutputStorageType) outp[i][0];
167  oimgp[2*i+1] = (OutputStorageType) outp[i][1];
168  }
169  return 0;
170 }
171 
172 
173 
174 /** dstX.GetChannelCount()==src.GetCHannelCount() */
175 template <class InputStorageType, class OutputStorageType>
179 {
180  Forward_(src);
181 
182  if (!dst1.IsEmpty()) dst1.Release();
183  dst1.Init(_OutSizeY, _SizeX,1);
184  if (!dst2.IsEmpty()) dst2.Release();
185  dst2.Init(_OutSizeY, _SizeX,1);
186  // copy and cast back int dst, two channel mode
187  fftw_complex *outp = _out;
188  OutputStorageType *oimgp1 = dst1.GetImageData();
189  OutputStorageType *oimgp2 = dst2.GetImageData();
190  for ( int i=0;i<_OutNum; i++){
191  oimgp1[i] = (OutputStorageType) (outp[i][0]);
192  oimgp2[i] = (OutputStorageType) (outp[i][1]);
193  }
194 
195  return 0;
196 }
197 
198 
199 /** dstX.GetChannelCount()==src.GetCHannelCount() */
200 template <class InputStorageType, class OutputStorageType>
203 {
204  Forward_(src);
205  if (!dst.IsEmpty()) dst.Release();
206  dst.Init(_OutSizeY ,_SizeX,1);
207  // copy and cast back int dst, abs mode
208  fftw_complex *outp = _out;
209  OutputStorageType *oimgp = dst.GetImageData();
210  for ( int i=0;i<_OutNum; i++){
211 
212  oimgp[i] =
213  (OutputStorageType) (sqrt((outp[i][0] * outp[i][0]) + (outp[i][1] * outp[i][1]))/_Size);
214  }
215 
216  return 0;
217 }
218 
219 /** dstX.GetChannelCount()==src.GetCHannelCount() */
220 template <class InputStorageType, class OutputStorageType>
223 {
224  Forward_(src);
225  if (!dst.IsEmpty()) dst.Release();
226  dst.Init( _OutSizeY ,_SizeX,1);
227  // copy and cast back int dst, abs mode
228  fftw_complex *outp = _out;
229  OutputStorageType *oimgp = dst.GetImageData();
230  for ( int i=0;i<_OutNum; i++){
231  oimgp[i] = (OutputStorageType) log(sqrt((outp[i][0]* outp[i][0]) + (outp[i][1]* outp[i][1])));
232  }
233 
234  return 0;
235 }
236 
237 /** dstX.GetChannelCount()==src.GetCHannelCount() */
238 template <class InputStorageType, class OutputStorageType>
241 {
242  Forward_(src);
243  if (!dst.IsEmpty()) dst.Release();
244  dst.Init( _OutSizeY ,_SizeX,1);
245  // copy and cast back int dst, abs mode
246  fftw_complex *outp = _out;
247  OutputStorageType *oimgp = dst.GetImageData();
248  for ( int i=0;i<_OutNum; i++){
249  oimgp[i] = (OutputStorageType) atan2f((float)outp[i][0], (float)outp[i][1]);
250  }
251 
252  return 0;
253 }
254 
255 #include <Base/Common/BIASpragmaStart.hh>
256 template <class InputStorageType, class OutputStorageType>
259 {
260  OutputStorageType *d = dst.GetImageData();
261  unsigned int count = dst.GetWidth() * dst.GetHeight() *dst.GetChannelCount();
262  for (unsigned int i=0; i<count; i++)
263  {
264  // TODO
265  ///\todo fix the cast by explicit template JW
266  d[i] /= (OutputStorageType) _Size;
267  }
268  return 0;
269 }
270 
271 template <class InputStorageType, class OutputStorageType>
274 
275  fftw_complex *_out2;
276  _out2 =(fftw_complex*)fftw_malloc(sizeof(fftw_complex) * _OutNum);
277  Forward_(src2);
278  //copy second FFT to _out2;
279  fftw_complex *outp1 = _out;
280  fftw_complex *outp2 = _out2;
281  for ( int i=0;i<_OutNum; i++){
282  outp2[i][0] = outp1[i][0];
283  outp2[i][1] = outp1[i][1];
284  }
285  Forward_(src1);
286 
287  if (!dst1.IsEmpty()) dst1.Release();
288  //dst1.Init(_OutSizeY, _SizeX,2);
289  dst1.Init(_OutSizeY, _SizeX,2);
290  // copy and cast back int dst, two channel mode
291  double abs;
292  outp2 = _out2;
293  outp1 = _out;
294  OutputStorageType *oimgp1 = dst1.GetImageData();
295 
296  for ( int i=0;i<_OutNum; i++){
297  abs = (double)(outp2[i][0] * outp2[i][0] + outp2[i][1] * outp2[i][1]);
298  oimgp1[2*i] = (OutputStorageType) ((outp1[i][0] * outp2[i][0] + outp1[i][1] * outp2[i][1])/abs);
299  oimgp1[2*i+1] = (OutputStorageType) ((outp2[i][0] * outp1[i][1] - outp1[i][0] * outp2[i][1])/abs);
300  }
301 
302  return 0;
303 }
304 
305 #include <Base/Common/BIASpragmaEnd.hh>
306 
307 
308 
309 template <class InputStorageType, class OutputStorageType>
313 {
314  Reverse_(src);
315  if (!dst.IsEmpty()) dst.Release();
316  dst.Init(_SizeY, _SizeX,1);
317  // copy and cast back int dst, abs mode
318  double *inp = _in;
319  InputStorageType *oimgp = dst.GetImageData();
320  for ( int i=0;i<_Size; i++){
321  oimgp[i] = (InputStorageType) inp[i];
322  }
323  return 0;
324 }
325 
326 template <class InputStorageType, class OutputStorageType>
328 GetBordersValid_(int& /*border_x*/, int& /*border_y*/) const
329 {
330  BIASERR("no parameter support, yet");
331  BIASABORT;
332 }
333 
334 
335 
336 //////////////////////////////////////////////////////////////////////////
337 // explicit instantiation (must be at end of file)
338 //////////////////////////////////////////////////////////////////////////
339 
340 #if defined(BUILD_IMAGE_FLOAT)
341 template class BIASImage_EXPORT FFT2D<float, float>;
342 #endif
343 #if defined(BUILD_IMAGE_DOUBLE)
344 template class BIASImage_EXPORT FFT2D<double, double>;
345 #endif
346 #if defined(BUILD_IMAGE_UCHAR) && defined(BUILD_IMAGE_FLOAT)
347 template class BIASImage_EXPORT FFT2D<unsigned char, float>;
348 #endif
349 #if defined(BUILD_IMAGE_UCHAR) && defined(BUILD_IMAGE_DOUBLE)
350 template class BIASImage_EXPORT FFT2D<unsigned char, double>;
351 #endif
352 
void Release()
reimplemented from ImageBase
Definition: Image.cpp:1579
virtual int Forward_(const Image< InputStorageType > &src)
Definition: FFT2D.cpp:98
bool IsEmpty() const
check if ImageData_ points to allocated image buffer or not
Definition: ImageBase.hh:245
unsigned int GetWidth() const
Definition: ImageBase.hh:312
virtual int TransformLogAbs(const Image< InputStorageType > &src, Image< OutputStorageType > &dst)
dstX.GetChannelCount()==src.GetCHannelCount()
Definition: FFT2D.cpp:222
virtual int TransformAbs(const Image< InputStorageType > &src, Image< OutputStorageType > &dst)
Transform forward and get absolute value from complex result The result is not normalized! ...
Definition: FFT2D.cpp:202
unsigned int GetChannelCount() const
returns the number of Color channels, e.g.
Definition: ImageBase.hh:382
unsigned int GetHeight() const
Definition: ImageBase.hh:319
void Init(unsigned int Width, unsigned int Height, unsigned int channels=1, enum EStorageType storageType=ST_unsignedchar, const bool interleaved=true)
calls Init from ImageBase storageType is ignored, just dummy argument
Definition: Image.cpp:421
const StorageType * GetImageData() const
overloaded GetImageData() from ImageBase
Definition: Image.hh:137
void Init(int width, int height)
initializes for forward transformation on complete image.
Definition: FFT2D.cpp:57
virtual int TransformPhase(const Image< InputStorageType > &src, Image< OutputStorageType > &dst)
dstX.GetChannelCount()==src.GetCHannelCount()
Definition: FFT2D.cpp:240
virtual int Filter(const Image< InputStorageType > &src, Image< OutputStorageType > &dst)
dst.GetChannelCount()==2*src.GetCHannelCount() The result is not normalized!
Definition: FFT2D.cpp:156
virtual int Reverse_(const Image< OutputStorageType > &src)
Definition: FFT2D.cpp:125
virtual void GetBordersValid_(int &border_x, int &border_y) const
Definition: FFT2D.cpp:328
void Release()
call this before a second call to Init()
Definition: FFT2D.cpp:84
virtual int CrossPowerSpectrum(const Image< InputStorageType > &src1, const Image< InputStorageType > &src2, Image< OutputStorageType > &dst1)
Definition: FFT2D.cpp:273
virtual int Normalize(Image< OutputStorageType > &dst)
Normalize output after transformation.
Definition: FFT2D.cpp:258
Wrapper to the fftw3 library adapted for 2D image filtering.
Definition: FFT2D.hh:50
virtual int TransformReverse(const Image< OutputStorageType > &src, Image< InputStorageType > &dst)
Transform reverse, src must be of _SizeX,_OutSizeY,2.
Definition: FFT2D.cpp:311
virtual ~FFT2D()
Definition: FFT2D.cpp:49