Contour finding tests run through
This commit is contained in:
parent
d175570177
commit
bbf1c02e79
4 changed files with 83 additions and 22 deletions
|
|
@ -35,9 +35,11 @@ BASE64_INCLUDES ?= -I$(UPSTREAM_DIR)/cpp-base64
|
|||
ARGAGG_INCLUDES ?= -I$(UPSTREAM_DIR)/argagg/include/argagg
|
||||
CAVC_INCLUDES ?= -I$(UPSTREAM_DIR)/CavalierContours/include/cavc/
|
||||
SUBPROCESS_INCLUDES ?= -I$(UPSTREAM_DIR)/subprocess.h
|
||||
MINUNIT_INCLUDES ?= -I$(UPSTREAM_DIR)/minunit
|
||||
STB_INCLUDES ?= -isystem$(UPSTREAM_DIR)/stb
|
||||
|
||||
SOURCES += $(CLIPPER_SOURCES)
|
||||
INCLUDES := -Iinclude -Isrc $(CLIPPER_INCLUDES) $(VORONOI_INCLUDES) $(POISSON_INCLUDES) $(BASE64_INCLUDES) $(ARGAGG_INCLUDES) $(CAVC_INCLUDES) $(SUBPROCESS_INCLUDES)
|
||||
INCLUDES := -Iinclude -Isrc $(CLIPPER_INCLUDES) $(VORONOI_INCLUDES) $(POISSON_INCLUDES) $(BASE64_INCLUDES) $(ARGAGG_INCLUDES) $(CAVC_INCLUDES) $(SUBPROCESS_INCLUDES) $(MINUNIT_INCLUDES) $(STB_INCLUDES)
|
||||
|
||||
PKG_CONFIG_DEPS := pugixml
|
||||
CXXFLAGS := -std=c++2a -g -Wall -Wextra -O0
|
||||
|
|
@ -74,6 +76,14 @@ $(BUILDDIR)/$(TARGET): $(SOURCES:%.cpp=$(BUILDDIR)/%.o)
|
|||
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ -Wl,--start-group $^ -lstdc++fs -Wl,--end-group; \
|
||||
fi
|
||||
|
||||
$(BUILDDIR)/nopencv-tests: src/nopencv_test.cpp src/nopencv.cpp
|
||||
@mkdir -p $(dir $@)
|
||||
$(CXX) $(CXXFLAGS) $(INCLUDES) $(LDFLAGS) -o $@ $^
|
||||
|
||||
|
||||
.PHONY: tests
|
||||
tests: $(BUILDDIR)/nopencv-tests
|
||||
|
||||
.PHONY: install
|
||||
install:
|
||||
$(INSTALL) $(BUILDDIR)/$(TARGET) $(PREFIX)/bin
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ static Direction flip_direction[8] = {
|
|||
D_SE
|
||||
};
|
||||
|
||||
static void follow(gerbolyze::nopencv::Image32 img, int start_x, int start_y, Direction initial_direction, int nbd, int connectivity, Polygon &poly) {
|
||||
static void follow(gerbolyze::nopencv::Image32 &img, int start_x, int start_y, Direction initial_direction, int nbd, int connectivity, Polygon &poly) {
|
||||
|
||||
//cerr << "follow " << start_x << " " << start_y << " | dir=" << dir_str[initial_direction] << " nbd=" << nbd << " conn=" << connectivity << endl;
|
||||
int dir_inc = (connectivity == 4) ? 2 : 1;
|
||||
|
|
@ -122,7 +122,7 @@ static void follow(gerbolyze::nopencv::Image32 img, int start_x, int start_y, Di
|
|||
}
|
||||
|
||||
|
||||
void gerbolyze::nopencv::find_blobs(gerbolyze::nopencv::Image32 img, gerbolyze::nopencv::ContourCallback cb) {
|
||||
void gerbolyze::nopencv::find_blobs(gerbolyze::nopencv::Image32 &img, gerbolyze::nopencv::ContourCallback cb) {
|
||||
int nbd = 1;
|
||||
Polygon poly;
|
||||
for (int y=0; y<img.rows(); y++) {
|
||||
|
|
|
|||
|
|
@ -65,6 +65,14 @@ namespace gerbolyze {
|
|||
return m_data[y*m_cols + x];
|
||||
};
|
||||
|
||||
void set_at(int x, int y, int val) {
|
||||
assert(x >= 0 && y >= 0 && x < m_cols && y < m_rows);
|
||||
assert(m_data != nullptr);
|
||||
|
||||
m_data[y*m_cols + x] = val;
|
||||
cerr << "set_at " << x << " " << y << ": " << val << " -> " << at(x, y) << endl;
|
||||
};
|
||||
|
||||
const int32_t &at(int x, int y) const {
|
||||
assert(x >= 0 && y >= 0 && x < m_cols && y < m_rows);
|
||||
assert(m_data != nullptr);
|
||||
|
|
@ -92,7 +100,7 @@ namespace gerbolyze {
|
|||
int m_rows=0, m_cols=0;
|
||||
};
|
||||
|
||||
void find_blobs(Image32 img, ContourCallback cb);
|
||||
void find_blobs(Image32 &img, ContourCallback cb);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,17 @@ using namespace gerbolyze::nopencv;
|
|||
|
||||
char msg[1024];
|
||||
|
||||
class TempfileHack {
|
||||
public:
|
||||
TempfileHack(const string ext) : m_path { filesystem::temp_directory_path() / (std::tmpnam(nullptr) + ext) } {}
|
||||
~TempfileHack() { remove(m_path); }
|
||||
|
||||
const char *c_str() { return m_path.c_str(); }
|
||||
|
||||
private:
|
||||
filesystem::path m_path;
|
||||
};
|
||||
|
||||
MU_TEST(test_complex_example_from_paper) {
|
||||
int32_t img_data[6*9] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
|
@ -116,38 +127,39 @@ MU_TEST(test_complex_example_from_paper) {
|
|||
}
|
||||
}
|
||||
|
||||
MU_TEST(test_round_trip) {
|
||||
static void testdata_roundtrip(const char *fn) {
|
||||
int x, y;
|
||||
uint8_t *data = stbi_load("testdata/paper-example.png", &x, &y, nullptr, 1);
|
||||
uint8_t *data = stbi_load(fn, &x, &y, nullptr, 1);
|
||||
Image32 ref_img(x, y);
|
||||
for (int cy=0; cy<y; cy++) {
|
||||
for (int cx=0; cx<x; cx++) {
|
||||
ref_img.at(cx, cy) = data[cy*x + cx];
|
||||
ref_img.at(cx, cy) = data[cy*x + cx] / 255;
|
||||
}
|
||||
}
|
||||
stbi_image_free(data);
|
||||
Image32 ref_img_copy(ref_img);
|
||||
|
||||
filesystem::path tmp_svg = { filesystem::temp_directory_path() /= (std::tmpnam(nullptr) + string(".svg")) };
|
||||
filesystem::path tmp_png = { filesystem::temp_directory_path() /= (std::tmpnam(nullptr) + string(".png")) };
|
||||
TempfileHack tmp_svg(".svg");
|
||||
TempfileHack tmp_png(".png");
|
||||
|
||||
ofstream svg(tmp_svg.c_str());
|
||||
|
||||
svg << "<svg width=\"" << x << "px\" height=\"" << y << "px\" viewBox=\"0 0 "
|
||||
<< x << " " << y << "\" "
|
||||
<< "xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">" << endl;
|
||||
svg << "<rect width=\"100%\" height=\"100%\" fill=\"black\">" << endl;
|
||||
svg << "<rect width=\"100%\" height=\"100%\" fill=\"black\"/>" << 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 << "<path fill=\"" << (pol == CP_HOLE ? "black" : "white") << "\" d=\"";
|
||||
svg << "<path fill=\"" << ((pol == CP_HOLE) ? "black" : "white") << "\" d=\"";
|
||||
svg << "M " << poly[0][0] << " " << poly[0][1];
|
||||
for (size_t i=1; i<poly.size(); i++) {
|
||||
svg << " L " << poly[i][0] << " " << poly[i][1];
|
||||
}
|
||||
svg << " Z\">" << endl;
|
||||
svg << " Z\"/>" << endl;
|
||||
});
|
||||
svg << "</svg>" << endl;
|
||||
svg.close();
|
||||
|
|
@ -155,27 +167,27 @@ MU_TEST(test_round_trip) {
|
|||
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);
|
||||
mu_assert_int_eq(0, rc);
|
||||
|
||||
int resvg_rc = -1;
|
||||
rc = subprocess_join(&subprocess, &resvg_rc);
|
||||
mu_assert_int_eq(rc, 0);
|
||||
mu_assert_int_eq(resvg_rc, 0);
|
||||
mu_assert_int_eq(0, rc);
|
||||
mu_assert_int_eq(0, resvg_rc);
|
||||
|
||||
rc = subprocess_destroy(&subprocess);
|
||||
mu_assert_int_eq(rc, 0);
|
||||
mu_assert_int_eq(0, rc);
|
||||
|
||||
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);
|
||||
mu_assert_int_eq(x, out_x);
|
||||
mu_assert_int_eq(y, out_y);
|
||||
|
||||
for (int cy=0; cy<y; cy++) {
|
||||
for (int cx=0; cx<x; cx++) {
|
||||
int actual = out_data[cy*x + cx];
|
||||
int expected = ref_img_copy.at(x, y);
|
||||
int expected = ref_img_copy.at(cx, cy)*255;
|
||||
if (actual != expected) {
|
||||
snprintf(msg, sizeof(msg), "Result does not match input @(%d, %d): %d != %d\n", cx, cy, actual, expected);
|
||||
snprintf(msg, sizeof(msg), "%s: Result does not match input @(%d, %d): %d != %d\n", fn, cx, cy, actual, expected);
|
||||
mu_fail(msg);
|
||||
}
|
||||
}
|
||||
|
|
@ -183,10 +195,41 @@ MU_TEST(test_round_trip) {
|
|||
stbi_image_free(out_data);
|
||||
}
|
||||
|
||||
MU_TEST(test_round_trip_blank) { testdata_roundtrip("testdata/blank.png"); }
|
||||
MU_TEST(test_round_trip_white) { testdata_roundtrip("testdata/white.png"); }
|
||||
MU_TEST(test_round_trip_blob_border_w) { testdata_roundtrip("testdata/blob-border-w.png"); }
|
||||
MU_TEST(test_round_trip_blobs_borders) { testdata_roundtrip("testdata/blobs-borders.png"); }
|
||||
MU_TEST(test_round_trip_blobs_corners) { testdata_roundtrip("testdata/blobs-corners.png"); }
|
||||
MU_TEST(test_round_trip_blobs_crossing) { testdata_roundtrip("testdata/blobs-crossing.png"); }
|
||||
MU_TEST(test_round_trip_cross) { testdata_roundtrip("testdata/cross.png"); }
|
||||
MU_TEST(test_round_trip_letter_e) { testdata_roundtrip("testdata/letter-e.png"); }
|
||||
MU_TEST(test_round_trip_paper_example) { testdata_roundtrip("testdata/paper-example.png"); }
|
||||
MU_TEST(test_round_trip_paper_example_inv) { testdata_roundtrip("testdata/paper-example-inv.png"); }
|
||||
MU_TEST(test_round_trip_single_px) { testdata_roundtrip("testdata/single-px.png"); }
|
||||
MU_TEST(test_round_trip_single_px_inv) { testdata_roundtrip("testdata/single-px-inv.png"); }
|
||||
MU_TEST(test_round_trip_two_blobs) { testdata_roundtrip("testdata/two-blobs.png"); }
|
||||
MU_TEST(test_round_trip_two_px) { testdata_roundtrip("testdata/two-px.png"); }
|
||||
MU_TEST(test_round_trip_two_px_inv) { testdata_roundtrip("testdata/two-px-inv.png"); }
|
||||
|
||||
|
||||
MU_TEST_SUITE(nopencv_contours_suite) {
|
||||
MU_RUN_TEST(test_complex_example_from_paper);
|
||||
// MU_RUN_TEST(test_round_trip);
|
||||
}
|
||||
MU_RUN_TEST(test_round_trip_blank);
|
||||
MU_RUN_TEST(test_round_trip_white);
|
||||
MU_RUN_TEST(test_round_trip_blob_border_w);
|
||||
MU_RUN_TEST(test_round_trip_blobs_borders);
|
||||
MU_RUN_TEST(test_round_trip_blobs_corners);
|
||||
MU_RUN_TEST(test_round_trip_blobs_crossing);
|
||||
MU_RUN_TEST(test_round_trip_cross);
|
||||
MU_RUN_TEST(test_round_trip_letter_e);
|
||||
MU_RUN_TEST(test_round_trip_paper_example);
|
||||
MU_RUN_TEST(test_round_trip_paper_example_inv);
|
||||
MU_RUN_TEST(test_round_trip_single_px);
|
||||
MU_RUN_TEST(test_round_trip_single_px_inv);
|
||||
MU_RUN_TEST(test_round_trip_two_blobs);
|
||||
MU_RUN_TEST(test_round_trip_two_px);
|
||||
MU_RUN_TEST(test_round_trip_two_px_inv);
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
(void)argc;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue