fast_convolution.hh

00001 // Copyright (C) 2004, 2006  EPITA Research and Development Laboratory
00002 //
00003 // This file is part of the Olena Library.  This library is free
00004 // software; you can redistribute it and/or modify it under the terms
00005 // of the GNU General Public License version 2 as published by the
00006 // Free Software Foundation.
00007 //
00008 // This library is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011 // General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU General Public License
00014 // along with this library; see the file COPYING.  If not, write to
00015 // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00016 // Boston, MA 02110-1301, USA.
00017 //
00018 // As a special exception, you may use this file as part of a free
00019 // software library without restriction.  Specifically, if other files
00020 // instantiate templates or use macros or inline functions from this
00021 // file, or you compile this file and link it with other files to
00022 // produce an executable, this file does not by itself cause the
00023 // resulting executable to be covered by the GNU General Public
00024 // License.  This exception does not however invalidate any other
00025 // reasons why the executable file might be covered by the GNU General
00026 // Public License.
00027 
00028 
00029 #ifndef OLENA_CONVOL_FAST_CONVOLUTION_HH
00030 # define OLENA_CONVOL_FAST_CONVOLUTION_HH
00031 
00032 # include <mlc/cmp.hh>
00033 # include <mlc/array/all.hh>
00034 # include <oln/transforms/fft.hh>
00035 # include <oln/morpher/piece_morpher.hh>
00036 # include <oln/morpher/border_morpher.hh>
00037 
00038 namespace oln {
00039 
00042   namespace convol {
00043 
00046     namespace fast {
00047 
00049       namespace internal {
00050 
00051         inline const coord
00052         center_dst(coord n)
00053         {
00054           return n % 2 ? n / 2 + 1 : n / 2;
00055         }
00056 
00057         inline const coord
00058         center_src(coord n)
00059         {
00060           return n % 2 ? n / 2 : (n - 1) / 2;
00061         }
00062 
00063         template <class I, class J, class P>
00064         const P
00065         center(const abstract::image<I>& big_ima, const abstract::image<J>& ima)
00066         {
00067           P p;
00068           for (unsigned i = 0; i < image_id<I>::dim; i++)
00069             p.nth(i) = internal::center_dst(big_ima.size().nth(0)) -
00070               internal::center_src(ima.size().nth(0)) - 1;
00071           return p;
00072         }
00073 
00074       } // end of namespace internal
00075 
00124       template<class DestValue, class I, class J>
00125       typename mute<I, DestValue>::ret
00126       convolve(const abstract::image< I >& input,
00127                const abstract::image< J >& k)
00128       {
00129 # ifdef HAVE_FFTW
00130         mlc::eq<I::dim, J::dim>::ensure();
00131         mlc::eq<I::dim, 2>::ensure();
00132 
00133         oln_size_type(I) big_size;
00134         coord width_input = 0;
00135         coord width_k = 0;
00136         for (unsigned i = 0; i < I::dim; i++)
00137         {
00138           big_size.nth(i) = input.size().nth(i) + k.size().nth(i) - 1;
00139           if (width_input < k.size().nth(i) - 1)
00140           {
00141             width_input = k.size().nth(i) - 1;
00142             width_k = input.size().nth(i) - 1;
00143           }
00144         }
00145         big_size.border() = input.border();
00146 
00147         const morpher::border_morpher< const image2d<oln_value_type(I)>, replicate_behavior<> >
00148           big_input(input.exact(), (width_input + 1) / 2, replicate_bhv());
00149 
00150         J big_k(big_size);
00151         oln_iter_type(J) big_iter(big_k);
00152         for_all(big_iter)
00153           big_k[big_iter] = 0;
00154         oln_iter_type(J) k_iter(k);
00155         oln_iter_type(J) input_iter(input);
00156 
00157         morpher::piece_morpher<J>
00158           piece_k(big_k, internal::center<J, J, oln_dpoint_type(J)>(big_k, k), k.size());
00159 
00160         for_all(k_iter)
00161           piece_k[k_iter] = k[k_iter];
00162 
00164         I big_input_(big_input.size());
00165         for_all(big_iter)
00166           big_input_[big_iter] = big_input[big_iter];
00167 
00168         transforms::fft<oln_value_type(I), ntg::rect> tr_input(big_input_.exact());
00169         transforms::fft<oln_value_type(J), ntg::rect> tr_k(big_k.exact());
00170 
00171         tr_input.transform();
00172         typename mute<I, ntg::cplx<ntg::rect, ntg::float_d> >::ret&
00173           Input = tr_input.transformed_image();
00174         const typename mute<J, ntg::cplx<ntg::rect, ntg::float_d> >::ret
00175           K = tr_k.transform();
00176 
00177         for_all(big_iter) {
00178           Input[big_iter] *= K[big_iter];
00179           // Scale.
00180           Input[big_iter] *= Input.nrows() * Input.ncols();
00181         }
00182 
00183         typename mute<I, DestValue>::ret big_output = tr_input.shift_transform_inv();
00184         typename mute<I, DestValue>::ret output(input.size());
00185 
00186         morpher::piece_morpher<J>
00187           piece_output(big_output, internal::center<J, J, oln_dpoint_type(J)>(big_input_, input), input.size());
00188         for_all(input_iter)
00189             output[input_iter] = piece_output[input_iter];
00190 
00191         return output;
00192 # else
00193         assert(0);
00194 # endif // !HAVE_FFTW
00195       }
00196 
00210       template<class DestValue, class I, class Info, class Win>
00211       typename mute<I, DestValue>::ret
00212       convolve(const abstract::image < I >& input,
00213                const mlc::array2d<Info, Win >& arr)
00214       {
00215         return convolve<DestValue>(input, static_cast< image2d<Win> >(arr));
00216         // FIXME: Should be abstract::w_window<T_arr>.  Adjust #include once done.
00217       }
00218 
00219     } // end namespace fast
00220 
00221   } // end namespace convol
00222 
00223 } // end namespace oln
00224 
00225 #endif // OLENA_CONVOL_FAST_CONVOLUTION_HH

Generated on Tue Feb 20 20:18:52 2007 for Olena by  doxygen 1.5.1