Viewing is open to everyone. Downloading and starring need a GitHub sign-in. Sign in with GitHub

image_decode_tests.cpp

v0.1.0-build.85 Latest Commit ede38f5

Size
4.3 KB
Lines
85
Language
cpp
SHA-256
c46ef46f3b09…
View on GitHub

Sign in with GitHub to download. Each download is recorded with your GitHub username.

1#include "ckey/ckey.h"
2
3#include <array>
4#include "check.h"
5#include <cstdint>
6#include <fstream>
7#include <iostream>
8#include <iterator>
9#include <string>
10#include <vector>
11
12struct Pgm { size_t width, height; std::vector<uint8_t> pixels; };
13
14static Pgm load_pgm(const std::string &path, size_t expected_side) {
15 std::ifstream file(path, std::ios::binary);
16 CKEY_CHECK(file && "optical image fixture is required");
17 std::string magic; size_t width=0,height=0; unsigned maxval=0;
18 file >> magic >> width >> height >> maxval;
19 file.get();
20 CKEY_CHECK(magic=="P5" && width==expected_side && height==expected_side && maxval==255);
21 std::vector<uint8_t> pixels((std::istreambuf_iterator<char>(file)),{});
22 CKEY_CHECK(pixels.size()==width*height);
23 return {width,height,std::move(pixels)};
24}
25
26int main() {
27 const std::string base=std::string(CKEY_TEST_SOURCE_DIR)+"/tests/vectors/";
28 auto fixture=load_pgm(base+"locator-v8-preview.pgm",670);
29 auto &image=fixture.pixels; const size_t width=fixture.width, height=fixture.height;
30
31 // The PGM is a crop of a browser-rendered v0.8 locator, not a raw generated
32 // bit matrix. The symbol's 31-unit SVG canvas maps canonical [0,29]^2 to
33 // [1,30]^2 within this 670 px crop.
34 const double unit=static_cast<double>(width)/31.0;
35 const double x0=unit, x1=30.0*unit;
36 const double quad[8]={x0,x0,x1,x0,x1,x1,x0,x1};
37 constexpr std::array<uint8_t,16> expected={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
38 std::array<uint8_t,16> decoded{}; ckey_diagnostics diag{};
39 CKEY_CHECK(ckey_calibration_score_gray8(image.data(),width,height,width,quad) > 40.0);
40 CKEY_CHECK(ckey_decode_gray8(image.data(),width,height,width,quad,decoded.data(),decoded.size(),&diag)==CKEY_OK);
41 CKEY_CHECK(decoded==expected && diag.status==CKEY_OK);
42
43 // This crop is taken from the user's exact reader target image and resized
44 // to 20 px/module. It verifies this image's marks and framing reach the core.
45 auto target=load_pgm(base+"locator-v8-reader-target.pgm",580);
46 const double target_edge=580.0/934.0;
47 const double target_far=933.0*target_edge;
48 const double target_quad[8]={target_edge,target_edge,target_far,target_edge,
49 target_far,target_far,target_edge,target_far};
50 decoded.fill(0);
51 CKEY_CHECK(ckey_decode_gray8(target.pixels.data(),target.width,target.height,target.width,
52 target_quad,decoded.data(),decoded.size(),&diag)==CKEY_OK);
53 CKEY_CHECK(decoded==expected);
54
55 // Regression fixture cropped from the user's iPhone camera preview while
56 // viewing the CKey on a laptop display. It includes screen rasterization,
57 // camera blur, and slight projective skew instead of a generated bitmap.
58 auto camera=load_pgm(base+"locator-v8-phone-camera.pgm",500);
59 const double camera_quad[8]={24,24,462,24,462,450,24,450};
60 decoded.fill(0);
61 CKEY_CHECK(ckey_decode_gray8(camera.pixels.data(),camera.width,camera.height,camera.width,
62 camera_quad,decoded.data(),decoded.size(),&diag)==CKEY_OK);
63 CKEY_CHECK(decoded==expected);
64
65 // Far-distance phone preview: the target is only about 135 px across
66 // (~4.7 px/module), but still decodes when localization supplies its field.
67 auto far_camera=load_pgm(base+"locator-v8-far-camera.pgm",180);
68 const double far_quad[8]={14,14,149,14,149,149,14,149};
69 decoded.fill(0);
70 CKEY_CHECK(ckey_decode_gray8(far_camera.pixels.data(),far_camera.width,far_camera.height,
71 far_camera.width,far_quad,decoded.data(),decoded.size(),&diag)==CKEY_OK);
72 CKEY_CHECK(decoded==expected);
73
74 // A rotated corner order and inverted monochrome polarity are both valid.
75 const double rotated[8]={x1,x0,x1,x1,x0,x1,x0,x0};
76 for (uint8_t &pixel : image) pixel=static_cast<uint8_t>(255-pixel);
77 decoded.fill(0);
78 CKEY_CHECK(ckey_decode_gray8(image.data(),width,height,width,rotated,decoded.data(),decoded.size(),&diag)==CKEY_OK);
79 CKEY_CHECK(decoded==expected);
80
81 const double invalid[8]={1,1,2,2,3,3,4,4};
82 CKEY_CHECK(ckey_decode_gray8(image.data(),width,height,width,invalid,decoded.data(),decoded.size(),&diag)==CKEY_INVALID_ARGUMENT);
83 CKEY_CHECK(ckey_calibration_score_extended_gray8(nullptr,width,height,width,target_quad) < 0.0);
84 std::cout << "CKey optical image decode tests passed\n";
85}