00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
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 }
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
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
00217 }
00218
00219 }
00220
00221 }
00222
00223 }
00224
00225 #endif // OLENA_CONVOL_FAST_CONVOLUTION_HH