Skip to content

Commit 8ecfae0

Browse files
committed
Add tests for checking boundary options in 1D convolution
Second Draft Third draft Fourth draft Fifth draft Sixth draft Seventh draft Eight draft Ninth draft Tenth draft Eleventh draft Add tests for checking boundary options in 1D convolution Add tests for checking boundary options in 1D convolution Add tests for checking boundary options in 1D convolution
1 parent fe1621e commit 8ecfae0

File tree

3 files changed

+585
-1
lines changed

3 files changed

+585
-1
lines changed

test/extension/numeric/convolve.cpp

Lines changed: 233 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//
22
// Copyright 2019-2020 Mateusz Loskot <mateusz at loskot dot net>
3+
// Copyright 2021 Prathamesh Tagore <[email protected]>
34
//
45
// Distributed under the Boost Software License, Version 1.0
56
// See accompanying file LICENSE_1_0.txt or copy at
@@ -100,7 +101,6 @@ struct test_image_5x5_kernel_3x3_identity
100101

101102
auto const kernel = fixture::create_kernel<channel_t>({0, 0, 0, 0, 1, 0, 0, 0, 0});
102103
gil::detail::convolve_1d<pixel_t>(gil::const_view(img_out), kernel, gil::view(img_out));
103-
// TODO: Test different boundary options
104104

105105
BOOST_TEST(gil::equal_pixels(gil::const_view(img), gil::const_view(img_out)));
106106
}
@@ -110,12 +110,244 @@ struct test_image_5x5_kernel_3x3_identity
110110
}
111111
};
112112

113+
// Convention used for naming variables :
114+
// 1. img : Original image which is to be used for testing.
115+
// 2. img_out : Output image obtained after applying 1D row and column convolution using library
116+
// function.
117+
// 3. img_expected_row : Expected image after applying row convolution on "img".
118+
// 4. img_expected_col : Expected image after applying column convolution on "img_expected_row".
119+
120+
struct test_image_5x5_kernel_1x9_boundary_extend_zero
121+
{
122+
template <typename Image>
123+
void operator()(Image const&)
124+
{
125+
using image_t = Image;
126+
using pixel_t = typename image_t::value_type;
127+
using channel_t = typename gil::channel_type<pixel_t>::type;
128+
auto img = fixture::generate_image<image_t>(5, 5, fixture::random_value<channel_t>{});
129+
auto img_view = gil::view(img);
130+
image_t img_out(img), img_expected_row(img_view.width(), img_view.height());
131+
image_t img_expected_col(img_view.width(), img_view.height());
132+
133+
for (std::ptrdiff_t y = 0; y < img_view.height(); ++y)
134+
{
135+
auto img_it = img_view.row_begin(y);
136+
auto img_expected_row_it = gil::view(img_expected_row).row_begin(y);
137+
for (std::ptrdiff_t x = 2; x < img_view.width(); ++x)
138+
img_expected_row_it[x] = img_it[x - 2];
139+
}
140+
for (std::ptrdiff_t x = 0; x < img_view.width(); ++x)
141+
{
142+
auto img_expected_row_it = gil::view(img_expected_row).col_begin(x);
143+
auto img_expected_col_it = gil::view(img_expected_col).col_begin(x);
144+
for (std::ptrdiff_t y = 2; y < img_view.height(); ++y)
145+
img_expected_col_it[y] = img_expected_row_it[y - 2];
146+
}
147+
148+
auto const kernel = fixture::create_kernel<channel_t>({0, 0, 0, 0, 0, 0, 1, 0, 0});
149+
gil::detail::convolve_1d<pixel_t>(gil::const_view(img_out), kernel, gil::view(img_out),
150+
boost::gil::boundary_option::extend_zero);
151+
152+
BOOST_TEST(gil::equal_pixels(gil::const_view(img_out), gil::const_view(img_expected_col)));
153+
}
154+
static void run()
155+
{
156+
boost::mp11::mp_for_each<fixture::image_types>(
157+
test_image_5x5_kernel_1x9_boundary_extend_zero{});
158+
}
159+
};
160+
161+
struct test_image_5x5_kernel_1x9_boundary_extend_constant
162+
{
163+
template <typename Image>
164+
void operator()(Image const&)
165+
{
166+
using image_t = Image;
167+
using pixel_t = typename image_t::value_type;
168+
using channel_t = typename gil::channel_type<pixel_t>::type;
169+
auto img = fixture::generate_image<image_t>(5, 5, fixture::random_value<channel_t>{});
170+
auto img_view = gil::view(img);
171+
image_t img_out(img), img_expected_row(img);
172+
173+
for (std::ptrdiff_t y = 0; y < img_view.height(); ++y)
174+
{
175+
auto img_it = img_view.row_begin(y);
176+
auto img_expected_row_it = gil::view(img_expected_row).row_begin(y);
177+
for (std::ptrdiff_t x = 2; x < img_view.width(); ++x)
178+
img_expected_row_it[x] = img_it[x - 2];
179+
img_expected_row_it[1] = img_it[0];
180+
}
181+
image_t img_expected_col(img_expected_row);
182+
for (std::ptrdiff_t x = 0; x < img_view.width(); ++x)
183+
{
184+
auto img_expected_row_it = gil::view(img_expected_row).col_begin(x);
185+
auto img_expected_col_it = gil::view(img_expected_col).col_begin(x);
186+
for (std::ptrdiff_t y = 2; y < img_view.height(); ++y)
187+
img_expected_col_it[y] = img_expected_row_it[y - 2];
188+
img_expected_col_it[1] = img_expected_row_it[0];
189+
}
190+
191+
auto const kernel = fixture::create_kernel<channel_t>({0, 0, 0, 0, 0, 0, 1, 0, 0});
192+
gil::detail::convolve_1d<pixel_t>(gil::const_view(img_out), kernel, gil::view(img_out),
193+
boost::gil::boundary_option::extend_constant);
194+
195+
BOOST_TEST(gil::equal_pixels(gil::const_view(img_out), gil::const_view(img_expected_col)));
196+
}
197+
static void run()
198+
{
199+
boost::mp11::mp_for_each<fixture::image_types>(
200+
test_image_5x5_kernel_1x9_boundary_extend_constant{});
201+
}
202+
};
203+
204+
struct test_image_5x5_kernel_1x9_boundary_output_zero
205+
{
206+
template <typename Image>
207+
void operator()(Image const&)
208+
{
209+
using image_t = Image;
210+
using pixel_t = typename image_t::value_type;
211+
using channel_t = typename gil::channel_type<pixel_t>::type;
212+
auto img = fixture::generate_image<image_t>(5, 5, fixture::random_value<channel_t>{});
213+
auto img_view = gil::view(img);
214+
image_t img_out(img), img_expected_row(img_view.width(), img_view.height());
215+
image_t img_expected_col(img_view.width(), img_view.height());
216+
217+
for (std::ptrdiff_t y = 0; y < img_view.height(); ++y)
218+
{
219+
auto img_it = img_view.row_begin(y);
220+
auto img_expected_row_it = gil::view(img_expected_row).row_begin(y);
221+
for (std::ptrdiff_t x = 1; x < img_view.width() - 1; ++x)
222+
img_expected_row_it[x] = img_it[x - 1];
223+
}
224+
for (std::ptrdiff_t x = 0; x < img_view.width(); ++x)
225+
{
226+
auto img_expected_row_it = gil::view(img_expected_row).col_begin(x);
227+
auto img_expected_col_it = gil::view(img_expected_col).col_begin(x);
228+
for (std::ptrdiff_t y = 1; y < img_view.height() - 1; ++y)
229+
img_expected_col_it[y] = img_expected_row_it[y - 1];
230+
}
231+
232+
auto const kernel = fixture::create_kernel<channel_t>({0, 0, 1});
233+
gil::detail::convolve_1d<pixel_t>(gil::const_view(img_out), kernel, gil::view(img_out),
234+
boost::gil::boundary_option::output_zero);
235+
236+
BOOST_TEST(gil::equal_pixels(gil::const_view(img_out), gil::const_view(img_expected_col)));
237+
}
238+
static void run()
239+
{
240+
boost::mp11::mp_for_each<fixture::image_types>(
241+
test_image_5x5_kernel_1x9_boundary_output_zero{});
242+
}
243+
};
244+
245+
struct test_image_5x5_kernel_1x9_boundary_output_ignore
246+
{
247+
template <typename Image>
248+
void operator()(Image const&)
249+
{
250+
using image_t = Image;
251+
using pixel_t = typename image_t::value_type;
252+
using channel_t = typename gil::channel_type<pixel_t>::type;
253+
auto img = fixture::generate_image<image_t>(5, 5, fixture::random_value<channel_t>{});
254+
auto img_view = gil::view(img);
255+
image_t img_out(img), img_expected_row(img);
256+
257+
for (std::ptrdiff_t y = 0; y < img_view.height(); ++y)
258+
{
259+
auto img_it = img_view.row_begin(y);
260+
auto img_expected_row_it = gil::view(img_expected_row).row_begin(y);
261+
for (std::ptrdiff_t x = 1; x < img_view.width() - 1; ++x)
262+
img_expected_row_it[x] = img_it[x - 1];
263+
}
264+
image_t img_expected_col(img_expected_row);
265+
for (std::ptrdiff_t x = 0; x < img_view.width(); ++x)
266+
{
267+
auto img_expected_row_it = gil::view(img_expected_row).col_begin(x);
268+
auto img_expected_col_it = gil::view(img_expected_col).col_begin(x);
269+
for (std::ptrdiff_t y = 1; y < img_view.height() - 1; ++y)
270+
img_expected_col_it[y] = img_expected_row_it[y - 1];
271+
}
272+
273+
auto const kernel = fixture::create_kernel<channel_t>({0, 0, 1});
274+
gil::detail::convolve_1d<pixel_t>(gil::const_view(img_out), kernel, gil::view(img_out),
275+
gil::boundary_option::output_ignore);
276+
277+
BOOST_TEST(gil::equal_pixels(gil::const_view(img_out), gil::const_view(img_expected_col)));
278+
}
279+
static void run()
280+
{
281+
boost::mp11::mp_for_each<fixture::image_types>(
282+
test_image_5x5_kernel_1x9_boundary_output_ignore{});
283+
}
284+
};
285+
286+
struct test_image_5x5_kernel_1x9_boundary_extend_padded
287+
{
288+
template <typename Image>
289+
void operator()(Image const&)
290+
{
291+
using image_t = Image;
292+
using pixel_t = typename image_t::value_type;
293+
using channel_t = typename gil::channel_type<pixel_t>::type;
294+
auto img = fixture::generate_image<image_t>(5, 5, fixture::random_value<channel_t>{});
295+
auto img_view = gil::view(img);
296+
image_t img_out(img), img_expected_row(img);
297+
298+
for (std::ptrdiff_t y = 0; y < img_view.height(); ++y)
299+
{
300+
auto img_it = img_view.row_begin(y);
301+
auto img_expected_row_it = gil::view(img_expected_row).row_begin(y);
302+
for (std::ptrdiff_t x = 1; x < img_view.width(); ++x)
303+
img_expected_row_it[x] = img_it[x - 1];
304+
}
305+
image_t img_expected_col(img_expected_row);
306+
for (std::ptrdiff_t x = 0; x < img_view.width(); ++x)
307+
{
308+
auto img_expected_row_it = gil::view(img_expected_row).col_begin(x);
309+
auto img_expected_col_it = gil::view(img_expected_col).col_begin(x);
310+
for (std::ptrdiff_t y = 1; y < img_view.width(); ++y)
311+
img_expected_col_it[y] = img_expected_row_it[y - 1];
312+
}
313+
314+
auto const kernel = fixture::create_kernel<channel_t>({0, 0, 1});
315+
gil::detail::convolve_1d<pixel_t>(gil::const_view(img_out), kernel, gil::view(img_out),
316+
gil::boundary_option::extend_padded);
317+
318+
// First row and first column of "img_out" and "img_expected_col" are intentionally made
319+
// similar.
320+
auto img_out_it1 = gil::view(img_out).col_begin(0);
321+
auto img_expected_col_it1 = gil::view(img_expected_col).col_begin(0);
322+
for (std::ptrdiff_t x = 0; x < gil::view(img_out).width(); ++x)
323+
img_expected_col_it1[x] = img_out_it1[x];
324+
325+
auto img_out_it2 = gil::view(img_out).row_begin(0);
326+
auto img_expected_col_it2 = gil::view(img_expected_col).row_begin(0);
327+
for (std::ptrdiff_t y = 0; y < gil::view(img_out).height(); ++y)
328+
img_expected_col_it2[y] = img_out_it2[y];
329+
330+
BOOST_TEST(gil::equal_pixels(gil::const_view(img_out), gil::const_view(img_expected_col)));
331+
332+
}
333+
static void run()
334+
{
335+
boost::mp11::mp_for_each<fixture::image_types>(
336+
test_image_5x5_kernel_1x9_boundary_extend_padded{});
337+
}
338+
};
339+
113340
int main()
114341
{
115342
test_image_1x1_kernel_1x1_identity::run();
116343
test_image_1x1_kernel_3x3_identity::run();
117344
test_image_3x3_kernel_3x3_identity::run();
118345
test_image_5x5_kernel_3x3_identity::run();
119346

347+
test_image_5x5_kernel_1x9_boundary_extend_zero::run();
348+
test_image_5x5_kernel_1x9_boundary_extend_constant::run();
349+
test_image_5x5_kernel_1x9_boundary_output_zero::run();
350+
test_image_5x5_kernel_1x9_boundary_output_ignore::run();
351+
test_image_5x5_kernel_1x9_boundary_extend_padded::run();
120352
return ::boost::report_errors();
121353
}

0 commit comments

Comments
 (0)