23 #ifndef _SEFRAMEWORK_CONVOLUTION_DFT_H
24 #define _SEFRAMEWORK_CONVOLUTION_DFT_H
46 template<
typename T = SeFloat,
class TPadding = PaddedImage<T, Reflect101Coordinates>>
107 auto context = Euclid::make_unique<ConvolutionContext>();
110 context->m_padded_width = model_ptr->getWidth() +
m_kernel->getWidth() - 1;
111 context->m_padded_height = model_ptr->getHeight() +
m_kernel->getHeight() - 1;
119 context->m_transform_padding = 2 * (context->m_padded_width / 2 + 1) - context->m_padded_width;
120 int work_area_size = context->m_padded_height * (context->m_padded_width / 2 + 1) * 2;
123 context->m_kernel_transform.resize(work_area_size);
124 context->m_work_area.resize(work_area_size);
128 context->m_work_area);
130 context->m_work_area);
151 template <
typename ...Args>
154 Args... padding_args)
const {
155 assert(image_ptr->getWidth() <= context->m_padded_width);
156 assert(image_ptr->getHeight() <= context->m_padded_height);
159 auto padded = TPadding::create(image_ptr,
160 context->m_padded_width, context->m_padded_height,
161 std::forward<Args>(padding_args)...);
170 complex_t* kernel_complex =
reinterpret_cast<complex_t*
>(context->m_kernel_transform.data());
172 size_t ncomplex = (context->m_padded_width / 2 + 1) * context->m_padded_height;
173 for (
size_t i = 0; i < ncomplex; ++i) {
174 const auto& a = img_complex[i];
175 const auto& b = kernel_complex[i];
176 float re = a[0] * b[0] - a[1] * b[1];
177 float im = a[0] * b[1] + a[1] * b[0];
179 img_complex[i][0] = re;
180 img_complex[i][1] = im;
187 auto wpad = ::div(context->m_padded_width - image_ptr->getWidth(), 2);
188 auto lpad = wpad.quot;
189 auto rpad = wpad.quot + wpad.rem;
190 auto hpad = ::div(context->m_padded_height - image_ptr->getHeight(), 2);
191 auto tpad = hpad.quot;
192 auto bpad = hpad.quot + hpad.rem;
208 template <
typename ...Args>
210 auto context =
prepare(image_ptr);
234 const auto chunk = img->getChunk(0, 0, img->getWidth(), img->getHeight());