// // Copyright 2021 Prathamesh Tagore // // Use, modification and distribution are subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // #include #include #include namespace gil = boost::gil; // This function helps us fill pixels of a view given as 2nd argument with // elements of the vector given as 1st argument. void pixel_fill(std::vector>& original_binary_vector, boost::gil::gray8_image_t& original_img) { for (std::ptrdiff_t view_row = 0; view_row < view(original_img).height(); ++view_row) { for (std::ptrdiff_t view_col = 0; view_col < view(original_img).width(); ++view_col) { view(original_img)(view_col, view_row) = gil::gray8_pixel_t(original_binary_vector[view_row][view_col]); } } } int main() { std::vector> original_binary_vector{ {0, 0, 0, 0, 0, 0}, {0, 0, 127, 144, 143, 0}, {0, 0, 128, 0, 142, 0}, {0, 0, 129, 0, 141, 0}, {0, 0, 130, 140, 139, 0}, {0, 0, 131, 0, 0, 0}, {0, 0, 132, 137, 136, 138}, {0, 0, 133, 134, 135, 0}}; std::vector> orig_dil_imp{ {255, 100, 100, 100}, {100, 100, 100, 100}, {100, 100, 100, 100}}; // All vectors defined below will be used for creating expected image views // which are supposed to match the views obtained after applying morphological // operations. std::vector> exp_dil{ {0, 127, 144, 144, 144, 143}, {0, 128, 144, 144, 144, 143}, {0, 129, 144, 144, 144, 143}, {0, 130, 140, 142, 142, 142}, {0, 131, 140, 141, 141, 141}, {0, 132, 140, 140, 140, 139}, {0, 133, 137, 137, 138, 138}, {0, 133, 137, 137, 138, 138}}; // Following vector intends to check result of dilation operation when it is // applied 2 times on the original image. std::vector> exp_dil_iter2{ {128, 144, 144, 144, 144, 144}, {129, 144, 144, 144, 144, 144}, {130, 144, 144, 144, 144, 144}, {131, 144, 144, 144, 144, 144}, {132, 140, 142, 142, 142, 142}, {133, 140, 141, 141, 141, 141}, {133, 140, 140, 140, 140, 140}, {133, 137, 137, 138, 138, 138}}; std::vector> exp_er{ {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 132, 0, 0}}; // Following vector intends to check result of erosion operation when it is // applied 2 times on the original image. std::vector> exp_er_iter2{ {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}}; std::vector> exp_opening{ {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 132, 132, 132, 0}, {0, 0, 132, 132, 132, 0}}; std::vector> exp_closing{ {0, 0, 127, 144, 143, 143}, {0, 0, 127, 144, 143, 143}, {0, 0, 128, 140, 142, 142}, {0, 0, 129, 140, 141, 141}, {0, 0, 130, 140, 139, 139}, {0, 0, 131, 137, 137, 138}, {0, 0, 132, 137, 137, 138}, {0, 0, 133, 137, 137, 138}}; std::vector> exp_mg{{0, 127, 144, 144, 144, 143}, {0, 128, 144, 144, 144, 143}, {0, 129, 144, 144, 144, 143}, {0, 130, 140, 142, 142, 142}, {0, 131, 140, 141, 141, 141}, {0, 132, 140, 140, 140, 139}, {0, 133, 137, 137, 138, 138}, {0, 133, 137, 5, 138, 138}}; std::vector> exp_top_hat{{0, 0, 0, 0, 0, 0}, {0, 0, 127, 144, 143, 0}, {0, 0, 128, 0, 142, 0}, {0, 0, 129, 0, 141, 0}, {0, 0, 130, 140, 139, 0}, {0, 0, 131, 0, 0, 0}, {0, 0, 0, 5, 4, 138}, {0, 0, 1, 2, 3, 0}}; std::vector> exp_black_hat{ {0, 0, 127, 144, 143, 143}, {0, 0, 0, 0, 0, 143}, {0, 0, 0, 140, 0, 142}, {0, 0, 0, 140, 0, 141}, {0, 0, 0, 0, 0, 139}, {0, 0, 0, 137, 137, 138}, {0, 0, 0, 0, 1, 0}, {0, 0, 0, 3, 2, 138}}; std::vector> exp_dil_imp{ {255, 255, 100, 100}, {255, 255, 100, 100}, {100, 100, 100, 100}}; gil::gray8_image_t original_img(6, 8), obtained_dilation(6, 8), expected_dilation(6, 8); gil::gray8_image_t obtained_erosion(6, 8), expected_erosion(6, 8); gil::gray8_image_t obtained_opening(6, 8), expected_opening(6, 8); gil::gray8_image_t obtained_closing(6, 8), expected_closing(6, 8); gil::gray8_image_t obtained_mg(6, 8), expected_mg(6, 8); gil::gray8_image_t obtained_top_hat(6, 8), expected_top_hat(6, 8); gil::gray8_image_t obtained_black_hat(6, 8), expected_black_hat(6, 8); gil::gray8_image_t obtained_dil_iter2(6, 8), expected_dil_iter2(6, 8); gil::gray8_image_t obtained_er_iter2(6, 8), expected_er_iter2(6, 8); gil::gray8_image_t obtained_imp_dil(4, 3), expected_imp_dil(4, 3), original_imp_dil(4, 3); std::vector ker_vec(9, 1.0f); // Structuring element gil::detail::kernel_2d ker_mat(ker_vec.begin(), ker_vec.size(), 1, 1); pixel_fill(original_binary_vector, original_img); pixel_fill(exp_dil, expected_dilation); pixel_fill(exp_er, expected_erosion); pixel_fill(exp_opening, expected_opening); pixel_fill(exp_closing, expected_closing); pixel_fill(exp_mg, expected_mg); pixel_fill(exp_top_hat, expected_top_hat); pixel_fill(exp_black_hat, expected_black_hat); pixel_fill(exp_dil_iter2, expected_dil_iter2); pixel_fill(orig_dil_imp, original_imp_dil); pixel_fill(exp_dil_imp, expected_imp_dil); pixel_fill(exp_er_iter2, expected_er_iter2); // Different morphological operations are applied on the same initial image to // obtain results of our implementation which are then compared with expected // results. gil::dilate(view(original_img), view(obtained_dilation), ker_mat, 1); gil::erode(view(original_img), view(obtained_erosion), ker_mat, 1); gil::opening(view(original_img), view(obtained_opening), ker_mat); gil::closing(view(original_img), view(obtained_closing), ker_mat); gil::morphological_gradient(view(original_img), view(obtained_mg), ker_mat); gil::top_hat(view(original_img), view(obtained_top_hat), ker_mat); gil::black_hat(view(original_img), view(obtained_black_hat), ker_mat); gil::dilate(view(original_imp_dil), view(obtained_imp_dil), ker_mat, 1); gil::dilate(view(original_img), view(obtained_dil_iter2), ker_mat, 2); gil::erode(view(original_img), view(obtained_er_iter2), ker_mat, 2); // Testing obtained results with expected results. BOOST_TEST(gil::equal_pixels(gil::view(obtained_dilation), gil::view(expected_dilation))); BOOST_TEST(gil::equal_pixels(gil::view(obtained_erosion), gil::view(expected_erosion))); BOOST_TEST(gil::equal_pixels(gil::view(obtained_opening), gil::view(expected_opening))); BOOST_TEST(gil::equal_pixels(gil::view(obtained_closing), gil::view(expected_closing))); BOOST_TEST(gil::equal_pixels(gil::view(obtained_mg), gil::view(expected_mg))); BOOST_TEST(gil::equal_pixels(gil::view(obtained_top_hat), gil::view(expected_top_hat))); BOOST_TEST(gil::equal_pixels(gil::view(obtained_black_hat), gil::view(expected_black_hat))); BOOST_TEST(gil::equal_pixels(gil::view(obtained_imp_dil), gil::view(expected_imp_dil))); BOOST_TEST(gil::equal_pixels(gil::view(obtained_dil_iter2), gil::view(expected_dil_iter2))); BOOST_TEST(gil::equal_pixels(gil::view(obtained_er_iter2), gil::view(expected_er_iter2))); return boost::report_errors(); }