From d1755701779b88389dc1d2e30d2430320a17f78e Mon Sep 17 00:00:00 2001 From: jaseg Date: Sun, 30 May 2021 19:39:45 +0200 Subject: Add beginnings of minimalist contour tracing code --- svg-flatten/src/nopencv_test.cpp | 198 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 svg-flatten/src/nopencv_test.cpp (limited to 'svg-flatten/src/nopencv_test.cpp') diff --git a/svg-flatten/src/nopencv_test.cpp b/svg-flatten/src/nopencv_test.cpp new file mode 100644 index 0000000..cc1c988 --- /dev/null +++ b/svg-flatten/src/nopencv_test.cpp @@ -0,0 +1,198 @@ + +#include +#include +#include +#include +#include + +#include "nopencv.hpp" + +#include +#include + +#define STB_IMAGE_IMPLEMENTATION +#include "stb_image.h" + +using namespace gerbolyze; +using namespace gerbolyze::nopencv; + +char msg[1024]; + +MU_TEST(test_complex_example_from_paper) { + int32_t img_data[6*9] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 0, 0, 1, 0, 0, 1, 0, + 0, 1, 0, 0, 1, 0, 0, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + }; + Image32 test_img(9, 6, static_cast(img_data)); + + const Polygon expected_polys[3] = { + { + {1,1}, {1,2}, {1,3}, {1,4}, {1,5}, + {2,5}, {3,5}, {4,5}, {5,5}, {6,5}, {7,5}, {8,5}, + {8,4}, {8,3}, {8,2}, {8,1}, + {7,1}, {6,1}, {5,1}, {4,1}, {3,1}, {2,1} + }, + { + {2,2}, {2,3}, {2,4}, + {3,4}, {4,4}, + {4,3}, {4,2}, + {3,2} + }, + { + {5,2}, {5,3}, {5,4}, + {6,4}, {7,4}, + {7,3}, {7,2}, + {6,2} + } + }; + + const ContourPolarity expected_polarities[3] = {CP_CONTOUR, CP_HOLE, CP_HOLE}; + + int invocation_count = 0; + gerbolyze::nopencv::find_blobs(test_img, [&invocation_count, &expected_polarities, &expected_polys](Polygon poly, ContourPolarity pol) { + invocation_count += 1; + mu_assert((invocation_count <= 3), "Too many contours returned"); + + mu_assert(poly.size() > 0, "Empty contour returned"); + mu_assert_int_eq(pol, expected_polarities[invocation_count-1]); + + d2p last; + bool first = true; + Polygon exp = expected_polys[invocation_count-1]; + //cout << "poly: "; + for (d2p &p : poly) { + //cout << "(" << p[0] << ", " << p[1] << "), "; + if (!first) { + mu_assert((fabs(p[0] - last[0]) + fabs(p[1] - last[1]) == 1), "Subsequent contour points have distance other than one"); + mu_assert(find(exp.begin(), exp.end(), p) != exp.end(), "Got unexpected contour point"); + } + last = p; + } + //cout << endl; + }); + mu_assert_int_eq(3, invocation_count); + + int32_t tpl[6*9] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 2, 2, 2, 2, 2,-2, 0, + 0,-3, 0, 0,-4, 0, 0,-2, 0, + 0,-3, 0, 0,-4, 0, 0,-2, 0, + 0, 2, 2, 2, 2, 2, 2,-2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + }; + + + for (int y=0; y<6; y++) { + for (int x=0; x<9; x++) { + int a = test_img.at(x, y), b = tpl[y*9+x]; + if (a != b) { + cout << "Result:" << endl; + cout << " "; + for (int x=0; x<9; x++) { + cout << x << " "; + } + cout << endl; + cout << " "; + for (int x=0; x<9; x++) { + cout << "---"; + } + cout << endl; + for (int y=0; y<6; y++) { + cout << y << " | "; + for (int x=0; x<9; x++) { + cout << setfill(' ') << setw(2) << test_img.at(x, y) << " "; + } + cout << endl; + } + + snprintf(msg, sizeof(msg), "Result does not match template @(%d, %d): %d != %d\n", x, y, a, b); + mu_fail(msg); + } + } + } +} + +MU_TEST(test_round_trip) { + int x, y; + uint8_t *data = stbi_load("testdata/paper-example.png", &x, &y, nullptr, 1); + Image32 ref_img(x, y); + for (int cy=0; cy" << endl; + svg << "" << endl; + + gerbolyze::nopencv::find_blobs(ref_img, [&svg](Polygon poly, ContourPolarity pol) { + mu_assert(poly.size() > 0, "Empty contour returned"); + mu_assert(poly.size() > 2, "Contour has less than three points, no area"); + mu_assert(pol == CP_CONTOUR || pol == CP_HOLE, "Contour has invalid polarity"); + + svg << "" << endl; + }); + svg << "" << endl; + svg.close(); + + const char *command_line[] = {"resvg", tmp_svg.c_str(), tmp_png.c_str()}; + struct subprocess_s subprocess; + int rc = subprocess_create(command_line, subprocess_option_inherit_environment, &subprocess); + mu_assert_int_eq(rc, 0); + + int resvg_rc = -1; + rc = subprocess_join(&subprocess, &resvg_rc); + mu_assert_int_eq(rc, 0); + mu_assert_int_eq(resvg_rc, 0); + + rc = subprocess_destroy(&subprocess); + mu_assert_int_eq(rc, 0); + + int out_x, out_y; + uint8_t *out_data = stbi_load(tmp_png.c_str(), &out_x, &out_y, nullptr, 1); + mu_assert_int_eq(out_x, x); + mu_assert_int_eq(out_y, y); + + for (int cy=0; cy