KJB

A class for performing 2d convolution using the FFTW library. More...
#include <m_convolve.h>
Classes  
struct  Sizes 
utility aggregate stores all sizes – rarely used by caller More...  
Public Types  
typedef std::pair < boost::shared_ptr < FFTW_real_vector > , boost::shared_ptr < FFTW_complex_vector > >  Work_buffer 
Public Member Functions  
Fftw_convolution_2d (int data_num_rows, int data_num_cols, int mask_max_rows, int mask_max_cols, int fft_alg_type=FFTW_MEASURE)  
Initialize the convolver by specifying data and mask dimensions. More...  
void  set_mask (const Matrix &) 
set mask, which must fit with mask size maxima given to ctor More...  
void  set_gaussian_mask (double sigma) 
set mask to a circular gaussian kernel of given sigma (pixels) More...  
void  convolve (const Matrix &, Matrix &) const 
void  reflect_and_convolve (const Matrix &, Matrix &) const 
convolve with mask, assuming input reflects at its boundaries More...  
void  execute (const Matrix &i, Matrix &o) const 
deprecated synonym for convolve method More...  
Work_buffer  allocate_work_buffer () const 
get a handle to a work buffer needed for threadsafe convolution. More...  
void  convolve (const Matrix &, Matrix &, Work_buffer) const 
void  reflect_and_convolve (const Matrix &, Matrix &, Work_buffer) const 
convolve with mask, assuming input reflects at its boundaries More...  
const Sizes &  get_sizes () const 
read access to the sizes specified at ctor time More...  
bool  is_mask_set () const 
read access of the flag indicating whether the mask has been set More...  
A class for performing 2d convolution using the FFTW library.
This should run faster than kjb_c::fourier_convolve_matrix() for applications that perform similarsized convolutions many times, because this class reuses the plans constructed by FFTW, the construction of which is usually the bottleneck for FFTW. The results from the convolve() method should be the same as those of fourier_convolve_matrix() except for numerical noise.
If you use the convolve() method, boundary conditions are handled by padding the data and mask with zeros before operating on them. This padding is removed before a result is returned. Note that kjb_c::convolve_matrix() behaves differently (it reflects the input matrix at its boundary). To emulate this behavior, use the reflect_and_convolve() method.
Storage is allocated only once when the object is created. Because of this, all data used for convolutions must be of the same size. Masks may differ in size, but dimensions cannot exceed the maximums specified during construction. Setting maximum mask dimensions higher than needed won't affect correctness, but will reduce performance. Setting the maximum mask dimensions too low will raise an exception when a larger mask is used.
If your application does not need to be parallelized, you may simply disregard any methods that mention Work_buffer. In other words, use only the twoparameter convolve() and reflect_and_convolve() methods.
A few methods are reentrant (i.e., threadsafe). If you wish to use multiple threads to convolve a common mask with multiple matrices (each convolution using ONE thread), this class can accomodate. Here is the general strategy:
Because the Work_buffer is a shared pointer to a block of memory that must be deallocated sequentially (using fftw_free, which is not reentrant), the last copy of any Work_buffer cannot be destroyed simultaneously with any other FFTW calls (except for its threadsafe functions). Thus, if a threadsafe function is to call allocate_work_buffer or initiate the destruction of the work buffer, it must serialize those steps. There are a number of ways to do so.
The following code snippet shows the general outline of a thread function that performs convolution, returning NULL or nonNULL to indicate error or success. Also it accesses two global objects, c and mtx.
typedef std::pair< boost::shared_ptr<FFTW_real_vector>, boost::shared_ptr<FFTW_complex_vector> > kjb::Fftw_convolution_2d::Work_buffer 
kjb::Fftw_convolution_2d::Fftw_convolution_2d  (  int  data_num_rows, 
int  data_num_cols,  
int  mask_max_rows,  
int  mask_max_cols,  
int  fft_alg_type = FFTW_MEASURE 

) 
Initialize the convolver by specifying data and mask dimensions.
data_num_rows  exact number of rows in each data matrix 
data_num_cols  exact number of col in each data matrix 
mask_max_rows  maximum number of rows in convolution mask (kernel) 
mask_max_cols  maximum number of cols in convolution mask (kernel) 
tuning_algorithm  The approach that FFTW should use to tune its fft algorithm. Acceptable values in order of increaing performance (and initialization time) are FFTW_ESTIMATE, FFTW_MEASURE, FFTW_PATIENT, FFTW_EXHAUSTIVE. Default is FFTW_MEASURE, which is a good balance of performance and startuptime. FFT_PATIENT gives ~1.4x speedup, at the expense of several extra seconds of additional startup time. In parallel mode, FFT_PATIENT should show even greater speedup (unconfirmed claim). 
Mask data is specified later by calling set_mask(). This ctor sets up the FFTW plans, and thus it will may take a few seconds.
Fftw_convolution_2d::Work_buffer kjb::Fftw_convolution_2d::allocate_work_buffer  (  )  const 
get a handle to a work buffer needed for threadsafe convolution.
If you call this function, you are probably going to use the reentrant convolution methods, and therefore you will probably not need the memory in the data_ field, if any. Thus we check whether data_ has memory, and if so we give it away in the expectation (no guarantees) that it would probably never otherwise be used.
To repeat: the object this returns is a handle, an opaque pointer – when originally written, a pair of smart pointers but we make no promises about implementation – and you should pass it around BY VALUE, via copying. It is fine to store them in an array or vector, if you like.
void kjb::Fftw_convolution_2d::convolve  (  const Matrix &  , 
Matrix &  ,  
Work_buffer  
)  const 
deprecated synonym for convolve method

inline 
read access to the sizes specified at ctor time

inline 
read access of the flag indicating whether the mask has been set
convolve with mask, assuming input reflects at its boundaries
void kjb::Fftw_convolution_2d::reflect_and_convolve  (  const Matrix &  , 
Matrix &  ,  
Work_buffer  
)  const 
convolve with mask, assuming input reflects at its boundaries
void kjb::Fftw_convolution_2d::set_gaussian_mask  (  double  sigma  ) 
set mask to a circular gaussian kernel of given sigma (pixels)
void kjb::Fftw_convolution_2d::set_mask  (  const Matrix &  ) 
set mask, which must fit with mask size maxima given to ctor