scanner: Check clarity of left mid of qr
This commit is contained in:
parent
d33836099c
commit
55fd00d35e
@ -260,6 +260,6 @@ install-scanner: qrtool.wx.wasm.br
|
|||||||
@cp -v qrtool.wx.js ../scanner/worker
|
@cp -v qrtool.wx.js ../scanner/worker
|
||||||
|
|
||||||
install-web: qrtool.web.wasm
|
install-web: qrtool.web.wasm
|
||||||
@cp -v qrtool.web.js qrtool.web.wasm ../web/public/camera-4.0/js/
|
@cp -v qrtool.web.js qrtool.web.wasm ../web/public/camera-5.0/js/
|
||||||
|
|
||||||
install: install-web install-scanner
|
install: install-web install-scanner
|
||||||
|
|||||||
267
alg/libqr.cpp
267
alg/libqr.cpp
@ -111,14 +111,12 @@ bool detect_qr(ProcessState &ps, float margin_ratio, bool warp, string &err)
|
|||||||
cvtColor(ps.straighten, g, COLOR_BGR2GRAY);
|
cvtColor(ps.straighten, g, COLOR_BGR2GRAY);
|
||||||
equalizeHist(g, g);
|
equalizeHist(g, g);
|
||||||
|
|
||||||
Rect dot_rect;
|
Rect left_mid_rect;
|
||||||
dot_rect.x = 0;
|
left_mid_rect.x = 0;
|
||||||
dot_rect.y = 0;
|
left_mid_rect.y = ps.straighten.rows / 6;
|
||||||
dot_rect.width = margin / 2;
|
left_mid_rect.width = ps.straighten.cols / 3;
|
||||||
dot_rect.height = margin / 2;
|
left_mid_rect.height = ps.straighten.rows / 3;
|
||||||
ps.dot_area = ps.straighten(dot_rect);
|
ps.left_mid_area = ps.straighten(left_mid_rect);
|
||||||
Mat dot_area_gray = g(dot_rect);
|
|
||||||
resize(dot_area_gray, ps.dot_area_gray, Size(64, 64));
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,107 +136,6 @@ bool preprocess(ProcessState &ps)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct EnergyGradient {
|
|
||||||
double x;
|
|
||||||
double y;
|
|
||||||
};
|
|
||||||
|
|
||||||
static
|
|
||||||
EnergyGradient energy_gradient(Mat &gray_img)
|
|
||||||
{
|
|
||||||
|
|
||||||
Mat smd_image_x, smd_image_y, G;
|
|
||||||
|
|
||||||
Mat kernel_x(3, 3, CV_32F, Scalar(0));
|
|
||||||
kernel_x.at<float>(1, 2) = -1.0;
|
|
||||||
kernel_x.at<float>(1, 1) = 1.0;
|
|
||||||
Mat kernel_y(3, 3, CV_32F, Scalar(0));
|
|
||||||
kernel_y.at<float>(1, 1) = 1.0;
|
|
||||||
kernel_y.at<float>(2, 1) = -1.0;
|
|
||||||
filter2D(gray_img, smd_image_x, gray_img.depth(), kernel_x);
|
|
||||||
filter2D(gray_img, smd_image_y, gray_img.depth(), kernel_y);
|
|
||||||
|
|
||||||
multiply(smd_image_x, smd_image_x, smd_image_x);
|
|
||||||
multiply(smd_image_y, smd_image_y, smd_image_y);
|
|
||||||
|
|
||||||
EnergyGradient ret = { mean(smd_image_x)[0], mean(smd_image_y)[0], };
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
bool check_blur_by_energy_gradient(Mat &gray, string &err)
|
|
||||||
{
|
|
||||||
const int thres = 85;
|
|
||||||
auto a = energy_gradient(gray);
|
|
||||||
|
|
||||||
float angle = 45;
|
|
||||||
auto m = getRotationMatrix2D(Point2f(gray.cols / 2, gray.rows / 2), angle, 1.0);
|
|
||||||
Mat rotated;
|
|
||||||
warpAffine(gray, rotated, m, gray.size());
|
|
||||||
|
|
||||||
auto b = energy_gradient(rotated);
|
|
||||||
|
|
||||||
auto diffa = fabs(a.x - a.y);
|
|
||||||
auto diffb = fabs(b.x - b.y);
|
|
||||||
auto diffa_percent = 100 * diffa / max(a.x, a.y);
|
|
||||||
auto diffb_percent = 100 * diffb / max(b.x, b.y);
|
|
||||||
bool ret =
|
|
||||||
((a.x > thres && a.y > thres) || (b.x > thres && b.y > thres)) &&
|
|
||||||
diffa_percent < 15 && diffb_percent < 15;
|
|
||||||
|
|
||||||
cout << "energy: "
|
|
||||||
+ to_string(a.x) + " "
|
|
||||||
+ to_string(a.y) + " "
|
|
||||||
+ to_string(b.x) + " "
|
|
||||||
+ to_string(b.y) << endl;
|
|
||||||
if (!ret) {
|
|
||||||
err = "energy: "
|
|
||||||
+ to_string(a.x) + " "
|
|
||||||
+ to_string(a.y) + " "
|
|
||||||
+ to_string(b.x) + " "
|
|
||||||
+ to_string(b.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
double laplacian(Mat &gray, string &err)
|
|
||||||
{
|
|
||||||
int ddepth = CV_16S;
|
|
||||||
Mat check, lap;
|
|
||||||
GaussianBlur(gray, check, Size(5, 5), 0, 0, BORDER_DEFAULT);
|
|
||||||
Laplacian(check, lap, ddepth, 3);
|
|
||||||
convertScaleAbs(lap, lap);
|
|
||||||
|
|
||||||
Mat mean, stddev;
|
|
||||||
meanStdDev(lap, mean, stddev);
|
|
||||||
if (stddev.cols * stddev.rows == 1) {
|
|
||||||
double area = gray.rows * gray.cols;
|
|
||||||
double sd = stddev.at<double>(0, 0);
|
|
||||||
double var = sd * sd;
|
|
||||||
return var / area;
|
|
||||||
}
|
|
||||||
err = "wrong shape of stddev result";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
bool check_blur_by_laplacian(ProcessState &ps, Mat &gray, string &err)
|
|
||||||
{
|
|
||||||
auto var = laplacian(gray, err);
|
|
||||||
if (var < 0) return false;
|
|
||||||
|
|
||||||
ps.clarity = var;
|
|
||||||
if (var <= ps.laplacian_thres) {
|
|
||||||
err = string_format("image (%d x %d) too blurry: %lf <= %lf",
|
|
||||||
gray.cols, gray.rows,
|
|
||||||
var, ps.laplacian_thres
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
static
|
||||||
bool check_blur_by_sobel(ProcessState &ps, Mat &gray, string &err)
|
bool check_blur_by_sobel(ProcessState &ps, Mat &gray, string &err)
|
||||||
{
|
{
|
||||||
@ -253,6 +150,7 @@ bool check_blur_by_sobel(ProcessState &ps, Mat &gray, string &err)
|
|||||||
|
|
||||||
Scalar meanMagnitude = mean(magnitude);
|
Scalar meanMagnitude = mean(magnitude);
|
||||||
double sharpness = meanMagnitude[0] / (gray.rows * gray.cols) * 1000;
|
double sharpness = meanMagnitude[0] / (gray.rows * gray.cols) * 1000;
|
||||||
|
ps.clarity = sharpness;
|
||||||
if (sharpness < thres) {
|
if (sharpness < thres) {
|
||||||
err = string_format("image too blurry: %lf < %lf", sharpness, thres);
|
err = string_format("image too blurry: %lf < %lf", sharpness, thres);
|
||||||
return false;
|
return false;
|
||||||
@ -286,151 +184,6 @@ static bool is_valid_pattern(Mat &img)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static
|
|
||||||
int find_score(Mat &img)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
for (int row = 0; row < img.rows; row++) {
|
|
||||||
int row_sum = 0;
|
|
||||||
for (int col = 0; col < img.cols; col++) {
|
|
||||||
auto p = img.at<bool>(row, col);
|
|
||||||
if (p) {
|
|
||||||
row_sum += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (row_sum) {
|
|
||||||
ret += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void clear_connected(Mat &bin, Point p)
|
|
||||||
{
|
|
||||||
vector<Point> q;
|
|
||||||
q.push_back(p);
|
|
||||||
while (q.size()) {
|
|
||||||
auto p = q[q.size() - 1];
|
|
||||||
q.pop_back();
|
|
||||||
bin.at<uint8_t>(p.y, p.x) = 0;
|
|
||||||
for (int i = -1; i <= 1; i++) {
|
|
||||||
for (int j = -1; j <= 1; j++) {
|
|
||||||
int nx = p.x + i;
|
|
||||||
int ny = p.y + j;
|
|
||||||
if (nx < 0 || nx >= bin.cols || ny < 0 || ny >= bin.rows) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (bin.at<bool>(ny, nx)) {
|
|
||||||
q.push_back(Point(nx, ny));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
vector<Point> find_points(Mat bin)
|
|
||||||
{
|
|
||||||
vector<Point> ret;
|
|
||||||
for (int x = 0; x < bin.cols; x++) {
|
|
||||||
for (int y = 0; y < bin.rows; y++) {
|
|
||||||
auto p = bin.at<uint8_t>(y, x);
|
|
||||||
if (!p) continue;
|
|
||||||
auto point = Point(x, y);
|
|
||||||
ret.push_back(point);
|
|
||||||
clear_connected(bin, point);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
int adaptive_erode(Mat &bin, Mat &eroded, string &err)
|
|
||||||
{
|
|
||||||
auto kernel = getStructuringElement(MORPH_ELLIPSE, Size(3, 3));
|
|
||||||
const int min_points = 25;
|
|
||||||
int max_erodes = 5;
|
|
||||||
|
|
||||||
printf("adaptiveThreshold\n");
|
|
||||||
eroded = bin.clone();
|
|
||||||
while (max_erodes-- > 0) {
|
|
||||||
// In this loop we erode a "full" image in order to get enough detached components
|
|
||||||
auto points = find_points(bin.clone());
|
|
||||||
printf("points: %zu\n", points.size());
|
|
||||||
if (points.size() == 0) {
|
|
||||||
err = "cannot find enough points";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (points.size() > min_points) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
erode(eroded, eroded, kernel);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (max_erodes-- > 0) {
|
|
||||||
// In this loop we further erode a "lean" image in order to get clarity until it's too much
|
|
||||||
Mat next;
|
|
||||||
erode(eroded, next, kernel);
|
|
||||||
auto points = find_points(next.clone());
|
|
||||||
if (points.size() < min_points) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
eroded = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
int emblem_detect_angle(Mat &gray, bool check_orthogonal, string &err)
|
|
||||||
{
|
|
||||||
Mat bin;
|
|
||||||
int min_score = gray.cols;
|
|
||||||
int max_score = 0;
|
|
||||||
int lowest_score_angle = -1;
|
|
||||||
|
|
||||||
adaptiveThreshold(gray, bin, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY_INV, 11, 2);
|
|
||||||
|
|
||||||
Mat inverted;
|
|
||||||
bitwise_not(bin, inverted);
|
|
||||||
const int MAX_ROT_ANGLE = 180;
|
|
||||||
int scores[MAX_ROT_ANGLE] = { 0 };
|
|
||||||
const int score_diff_thres = 5;
|
|
||||||
|
|
||||||
Mat eroded;
|
|
||||||
adaptive_erode(bin, eroded, err);
|
|
||||||
|
|
||||||
for (int angle = 0; angle < MAX_ROT_ANGLE; angle += 1) {
|
|
||||||
auto m = getRotationMatrix2D(Point2f(gray.cols / 2, gray.rows / 2), angle, 1.0);
|
|
||||||
Mat rotated;
|
|
||||||
warpAffine(eroded, rotated, m, gray.size());
|
|
||||||
int score = find_score(rotated);
|
|
||||||
scores[angle] = score;
|
|
||||||
if (score < min_score) {
|
|
||||||
lowest_score_angle = angle;
|
|
||||||
}
|
|
||||||
min_score = min(score, min_score);
|
|
||||||
max_score = max(max_score, score);
|
|
||||||
}
|
|
||||||
if (max_score - min_score > score_diff_thres) {
|
|
||||||
int orthogonal_angle = lowest_score_angle + 90;
|
|
||||||
if (orthogonal_angle > 180) {
|
|
||||||
orthogonal_angle -= 180;
|
|
||||||
}
|
|
||||||
int orthogonal_score = scores[orthogonal_angle];
|
|
||||||
printf("lowest_score_angle %d, min score %d, max score %d, orthogonal_angle %d, orthogonal score: %d\n",
|
|
||||||
lowest_score_angle, min_score, max_score, orthogonal_angle, orthogonal_score);
|
|
||||||
lowest_score_angle = lowest_score_angle > 90 ? lowest_score_angle - 90 : lowest_score_angle;
|
|
||||||
if (lowest_score_angle > 45)
|
|
||||||
lowest_score_angle = 90 - lowest_score_angle;
|
|
||||||
if (max_score - orthogonal_score > score_diff_thres || !check_orthogonal) {
|
|
||||||
return lowest_score_angle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool emblem_dot_angle(ProcessState &ps, InputArray in, float &angle, string &qrcode, string &err)
|
bool emblem_dot_angle(ProcessState &ps, InputArray in, float &angle, string &qrcode, string &err)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
@ -438,7 +191,7 @@ bool emblem_dot_angle(ProcessState &ps, InputArray in, float &angle, string &qrc
|
|||||||
ps.orig = (Mat *)in.getObj();
|
ps.orig = (Mat *)in.getObj();
|
||||||
preprocess(ps);
|
preprocess(ps);
|
||||||
|
|
||||||
if (!detect_qr(ps, 0.20, true, err)) {
|
if (!detect_qr(ps, 0, true, err)) {
|
||||||
qrcode = ps.qrcode;
|
qrcode = ps.qrcode;
|
||||||
err = "detect_qr: " + err;
|
err = "detect_qr: " + err;
|
||||||
return false;
|
return false;
|
||||||
@ -446,7 +199,9 @@ bool emblem_dot_angle(ProcessState &ps, InputArray in, float &angle, string &qrc
|
|||||||
|
|
||||||
qrcode = ps.qrcode;
|
qrcode = ps.qrcode;
|
||||||
|
|
||||||
if (!check_sharpness(ps, ps.dot_area_gray, ps.sharpness_method, err)) {
|
Mat lma_gray;
|
||||||
|
cvtColor(ps.left_mid_area, lma_gray, COLOR_BGR2GRAY);
|
||||||
|
if (!check_sharpness(ps, lma_gray, ps.sharpness_method, err)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -20,13 +20,11 @@ struct ProcessState {
|
|||||||
CvImg straighten;
|
CvImg straighten;
|
||||||
Rect qr_rect_in_straighten;
|
Rect qr_rect_in_straighten;
|
||||||
CvImg qr_straighten;
|
CvImg qr_straighten;
|
||||||
CvImg dot_area;
|
CvImg left_mid_area;
|
||||||
CvImg dot_area_gray;
|
|
||||||
string qrcode = "";
|
string qrcode = "";
|
||||||
double clarity;
|
|
||||||
float laplacian_thres = 0.1;
|
|
||||||
float sobel_thres = 15;
|
float sobel_thres = 15;
|
||||||
int sharpness_method = 2;
|
int sharpness_method = 2;
|
||||||
|
float clarity = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool preprocess(ProcessState &ps);
|
bool preprocess(ProcessState &ps);
|
||||||
@ -37,7 +35,6 @@ enum SimilarityAlg {
|
|||||||
FuzzyPixelCmp,
|
FuzzyPixelCmp,
|
||||||
};
|
};
|
||||||
double emblem_roi_similarity(SimilarityAlg alg, InputArray a, InputArray b, string &err);
|
double emblem_roi_similarity(SimilarityAlg alg, InputArray a, InputArray b, string &err);
|
||||||
double laplacian(Mat &gray, string &err);
|
|
||||||
|
|
||||||
static inline void showimg_(const char *title, Mat &img) {
|
static inline void showimg_(const char *title, Mat &img) {
|
||||||
imshow(title, img);
|
imshow(title, img);
|
||||||
|
|||||||
541
alg/qrtool.cpp
541
alg/qrtool.cpp
@ -81,218 +81,10 @@ int dot_cmd(char **argv, int argc)
|
|||||||
printf("angle: %.1f\n", angle);
|
printf("angle: %.1f\n", angle);
|
||||||
printf("qrcode: %s\n", qrcode.c_str());
|
printf("qrcode: %s\n", qrcode.c_str());
|
||||||
printf("saving dot file: %s\n", outfile.c_str());
|
printf("saving dot file: %s\n", outfile.c_str());
|
||||||
imwrite(outfile, ps.dot_area);
|
imwrite(outfile, ps.left_mid_area);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
|
||||||
int clarity_cmd(char **argv, int argc)
|
|
||||||
{
|
|
||||||
string err;
|
|
||||||
|
|
||||||
char *file = argv[0];
|
|
||||||
printf("file: %s\n", file);
|
|
||||||
Mat orig = imread(file);
|
|
||||||
Mat gray;
|
|
||||||
cvtColor(orig, gray, COLOR_BGR2GRAY);
|
|
||||||
auto c = laplacian(gray, err);
|
|
||||||
printf("clarity: %lf\n", c);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
int rectify_cmd(char **argv, int argc)
|
|
||||||
{
|
|
||||||
char *file = argv[0];
|
|
||||||
string err;
|
|
||||||
ProcessState ps;
|
|
||||||
Mat orig = imread(file);
|
|
||||||
|
|
||||||
ps.orig = &orig;
|
|
||||||
preprocess(ps);
|
|
||||||
|
|
||||||
if (!detect_qr(ps, 0.20, false, err)) {
|
|
||||||
cerr << err << endl;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
string outfile = string(file) + ".qr.jpg";
|
|
||||||
imwrite(outfile, ps.straighten);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
int topleft_cmd(char **argv, int argc)
|
|
||||||
{
|
|
||||||
char *file = argv[0];
|
|
||||||
string err;
|
|
||||||
ProcessState ps;
|
|
||||||
Mat orig = imread(file);
|
|
||||||
|
|
||||||
ps.orig = &orig;
|
|
||||||
preprocess(ps);
|
|
||||||
|
|
||||||
if (!detect_qr(ps, 0.02, true, err)) {
|
|
||||||
cerr << err << endl;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
string outfile = string(file) + ".topleft.jpg";
|
|
||||||
Mat &base = ps.straighten;
|
|
||||||
auto crop = Rect(0, 0, base.cols / 2, base.rows / 2);
|
|
||||||
Mat result = base(crop);
|
|
||||||
imwrite(outfile, result);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
int find_roi_start_point(Mat &bin, Point &p)
|
|
||||||
{
|
|
||||||
int npoints = 4;
|
|
||||||
|
|
||||||
for (int i = 0; i < bin.cols / 3; i++) {
|
|
||||||
uchar sum = 0;
|
|
||||||
for (int j = 0; j < npoints; j++) {
|
|
||||||
int v = i + j;
|
|
||||||
sum += bin.at<uchar>(v, v);
|
|
||||||
}
|
|
||||||
if (sum == 0) {
|
|
||||||
p = Point(i, i);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cerr << "find_roi_start_point" << endl;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
vector<int> count_black(Mat &bin, bool count_rows, int size)
|
|
||||||
{
|
|
||||||
vector<int> ret;
|
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
int count = 0;
|
|
||||||
for (int j = 0; j < size; j++) {
|
|
||||||
int x = count_rows ? j : i;
|
|
||||||
int y = count_rows ? i : j;
|
|
||||||
if (bin.at<uchar>(y, x) == 0) count++;
|
|
||||||
}
|
|
||||||
ret.push_back(count);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int find_start_of_first_black_range(const vector<int> &data)
|
|
||||||
{
|
|
||||||
size_t i = 0;
|
|
||||||
int m = *std::max_element(data.begin(), data.end());
|
|
||||||
int thres = m * 50 / 100;
|
|
||||||
while (i < data.size() - 3) {
|
|
||||||
if (data[i] >= thres && data[i + 1] >= thres && data[i + 2] >= thres) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (i >= data.size() - 3) return -1;
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int find_end_of_first_black_range(const vector<int> &data)
|
|
||||||
{
|
|
||||||
size_t i = 0;
|
|
||||||
int m = *std::max_element(data.begin(), data.end());
|
|
||||||
int thres = m * 50 / 100;
|
|
||||||
while (i < data.size() - 3) {
|
|
||||||
if (data[i] >= thres && data[i + 1] >= thres && data[i + 2] >= thres) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (i >= data.size() - 3) return -1;
|
|
||||||
while (i < data.size() - 3) {
|
|
||||||
if (data[i] < thres || data[i + 1] < thres || data[i + 2] < thres) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if (i >= data.size() - 3) return -1;
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
int find_roi_rect(Mat &bin, Point &start, Rect &rect, bool inner, string &err)
|
|
||||||
{
|
|
||||||
Mat visited;
|
|
||||||
bin.copyTo(visited);
|
|
||||||
vector<Point> q;
|
|
||||||
q.push_back(start);
|
|
||||||
int min_x = bin.rows, min_y = bin.rows, max_x = 0, max_y = 0;
|
|
||||||
int orig_size = max(bin.rows, bin.cols);
|
|
||||||
|
|
||||||
while (q.size()) {
|
|
||||||
Point p = q.back();
|
|
||||||
q.pop_back();
|
|
||||||
visited.at<uchar>(p.y, p.x) = 255;
|
|
||||||
min_x = min(min_x, p.x);
|
|
||||||
min_y = min(min_y, p.y);
|
|
||||||
max_x = max(max_x, p.x);
|
|
||||||
max_y = max(max_y, p.y);
|
|
||||||
for (int xoff = -1; xoff <= 1; xoff++) {
|
|
||||||
for (int yoff = -1; yoff <= 1; yoff++) {
|
|
||||||
int x = p.x + xoff;
|
|
||||||
int y = p.y + yoff;
|
|
||||||
if (x >= 0 && x < visited.cols && y >= 0 && y < visited.rows) {
|
|
||||||
auto v = visited.at<uchar>(y, x);
|
|
||||||
if (v == 0) {
|
|
||||||
if (q.size() >= 20000) {
|
|
||||||
err = string("roi detected range too large: ") + to_string(q.size());
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
q.push_back(Point(x, y));
|
|
||||||
visited.at<uchar>(y, x) = 255;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (max_x - min_x < 50 || max_y - min_y < 50) {
|
|
||||||
err = "detected roi outer region too small";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto size = std::max(max_x, max_y);
|
|
||||||
|
|
||||||
auto row_sums = count_black(bin, true, size);
|
|
||||||
auto col_sums = count_black(bin, false, size);
|
|
||||||
|
|
||||||
min_x = inner ? find_end_of_first_black_range(col_sums) : find_start_of_first_black_range(col_sums);
|
|
||||||
min_y = inner ? find_end_of_first_black_range(row_sums) : find_start_of_first_black_range(row_sums);
|
|
||||||
|
|
||||||
if (min_x < 0 || min_y < 0) {
|
|
||||||
err = "min_x or min_y is negative";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// find the max values, similarly
|
|
||||||
std::reverse(col_sums.begin(), col_sums.end());
|
|
||||||
std::reverse(row_sums.begin(), row_sums.end());
|
|
||||||
max_x = size - (inner ? find_end_of_first_black_range(col_sums) : find_start_of_first_black_range(col_sums));
|
|
||||||
max_y = size - (inner ? find_end_of_first_black_range(row_sums) : find_start_of_first_black_range(row_sums));
|
|
||||||
|
|
||||||
if (max_x < 0 || max_y < 0) return -1;
|
|
||||||
|
|
||||||
if (max_x - min_x < 50 || max_y - min_y < 50) {
|
|
||||||
err = "detected roi region too small";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
size = (max_x - min_x + max_y - min_y) / 2;
|
|
||||||
|
|
||||||
if (size < orig_size / 5 || size > orig_size * 3 / 5) {
|
|
||||||
err = "size of found region is out of valid range";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
rect = Rect(min_x + 1, min_y + 1, size, size);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void get_bin(Mat &orig, Mat &out)
|
static void get_bin(Mat &orig, Mat &out)
|
||||||
{
|
{
|
||||||
@ -307,297 +99,6 @@ static void get_bin(Mat &orig, Mat &out)
|
|||||||
threshold(gray, out, 128, 255, THRESH_BINARY);
|
threshold(gray, out, 128, 255, THRESH_BINARY);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
|
||||||
int find_roi(Mat &qr_straighten, Mat &roi, bool inner, string &err)
|
|
||||||
{
|
|
||||||
Mat bin;
|
|
||||||
Rect topleft_r(0, 0, qr_straighten.cols / 2, qr_straighten.rows / 2);
|
|
||||||
Mat topleft = qr_straighten(topleft_r);
|
|
||||||
get_bin(topleft, bin);
|
|
||||||
|
|
||||||
Point start;
|
|
||||||
Rect roi_rect;
|
|
||||||
auto r = find_roi_start_point(bin, start);
|
|
||||||
if (r) {
|
|
||||||
err = "failed to find roi start point";
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
r = find_roi_rect(bin, start, roi_rect, inner, err);
|
|
||||||
if (r) {
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
roi = qr_straighten(roi_rect);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int roi_process_one(const char *file, bool inner, string &err, bool warp, Mat *roi_out)
|
|
||||||
{
|
|
||||||
Mat roi;
|
|
||||||
Mat orig = imread(file, IMREAD_COLOR);
|
|
||||||
Mat qr_with_margin;
|
|
||||||
|
|
||||||
if (warp) {
|
|
||||||
ProcessState ps;
|
|
||||||
ps.orig = &orig;
|
|
||||||
preprocess(ps);
|
|
||||||
if (!detect_qr(ps, 0.02, true, err)) {
|
|
||||||
cerr << err << ":" << file << endl;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
qr_with_margin = ps.straighten;
|
|
||||||
} else {
|
|
||||||
qr_with_margin = orig;
|
|
||||||
}
|
|
||||||
if (qr_with_margin.cols <= 0 || qr_with_margin.rows <= 0) return -1;
|
|
||||||
auto r = find_roi(qr_with_margin, roi, inner, err);
|
|
||||||
if (r) return r;
|
|
||||||
if (roi_out) {
|
|
||||||
*roi_out = roi;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool is_dir(char *path)
|
|
||||||
{
|
|
||||||
struct stat st;
|
|
||||||
|
|
||||||
if (lstat(path, &st) == 0) {
|
|
||||||
if (S_ISREG(st.st_mode)) {
|
|
||||||
return false;
|
|
||||||
} else if (S_ISDIR(st.st_mode)) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
perror("Error in lstat");
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void save_roi(string orig_file, Mat &roi)
|
|
||||||
{
|
|
||||||
string outfile = orig_file + ".roi.jpg";
|
|
||||||
cout << "save: " << outfile << endl;
|
|
||||||
imwrite(outfile, roi);
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
int frame_roi_cmd(char **argv, int argc)
|
|
||||||
{
|
|
||||||
char *file = argv[0];
|
|
||||||
string err;
|
|
||||||
int ret = 0;
|
|
||||||
Mat roi;
|
|
||||||
|
|
||||||
cout << "frame roi processing: " << file << endl;
|
|
||||||
ret = roi_process_one(file, false, err, true, &roi);
|
|
||||||
if (ret) {
|
|
||||||
cerr << "failed to process: " << file << ":" << err <<endl;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
save_roi(file, roi);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
int roi_cmd(char **argv, int argc)
|
|
||||||
{
|
|
||||||
char *file = argv[0];
|
|
||||||
string err;
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
cout << "roi processing: " << file << endl;
|
|
||||||
if (is_dir(file)) {
|
|
||||||
for (auto const& dir_entry : filesystem::directory_iterator{file}) {
|
|
||||||
auto path = dir_entry.path();
|
|
||||||
Mat roi;
|
|
||||||
if (roi_process_one(path.c_str(), false, err, false, &roi) != 0) {
|
|
||||||
cerr << "failed: " << path << ":" << err << endl;
|
|
||||||
ret = 1;
|
|
||||||
}
|
|
||||||
save_roi(file, roi);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Mat roi;
|
|
||||||
ret = roi_process_one(file, false, err, false, &roi);
|
|
||||||
if (ret) {
|
|
||||||
cerr << "failed to process: " << file << ":" << err <<endl;
|
|
||||||
} else {
|
|
||||||
save_roi(file, roi);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
int roi_bench_cmd(char **argv, int argc)
|
|
||||||
{
|
|
||||||
char *file = argv[0];
|
|
||||||
int n = 0;
|
|
||||||
string err;
|
|
||||||
auto begin = chrono::system_clock::now();
|
|
||||||
for (auto const& dir_entry : filesystem::directory_iterator{file}) {
|
|
||||||
auto path = dir_entry.path();
|
|
||||||
if (roi_process_one(path.c_str(), false, err, false, NULL) == 0) {
|
|
||||||
n += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
auto end = chrono::system_clock::now();
|
|
||||||
std::chrono::duration<float> duration = end - begin;
|
|
||||||
float seconds = duration.count();
|
|
||||||
printf("qps: %.1f\n", n / seconds);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if USE_PULSAR
|
|
||||||
static vector<string> split_path(const string &path)
|
|
||||||
{
|
|
||||||
vector<string> ret;
|
|
||||||
string cur = "";
|
|
||||||
for (auto x: path) {
|
|
||||||
if (x == '/') {
|
|
||||||
if (cur.size()) {
|
|
||||||
ret.push_back(cur);
|
|
||||||
cur = "";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cur += x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (cur.size()) {
|
|
||||||
ret.push_back(cur);
|
|
||||||
cur = "";
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static string join_path(const vector<string> fs)
|
|
||||||
{
|
|
||||||
string ret;
|
|
||||||
const string sep = "/";
|
|
||||||
|
|
||||||
for (auto x: fs) {
|
|
||||||
ret += sep + x;
|
|
||||||
}
|
|
||||||
if (ret.size() == 0) ret = "/";
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static string get_output_path(const string &path)
|
|
||||||
{
|
|
||||||
auto ret = split_path(path);
|
|
||||||
ret[3] = "roi";
|
|
||||||
return join_path(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
int roi_worker_handle_image(const string &input_path,
|
|
||||||
const vector<uint8_t> &input,
|
|
||||||
string &output_path,
|
|
||||||
vector<uint8_t> &output)
|
|
||||||
{
|
|
||||||
Mat roi;
|
|
||||||
Mat orig = imdecode(input, IMREAD_COLOR);
|
|
||||||
|
|
||||||
auto r = find_roi(orig, roi, true, true);
|
|
||||||
if (r) return r;
|
|
||||||
imencode(".jpg", roi, output);
|
|
||||||
output_path = get_output_path(input_path);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
int roi_worker_handle_image_nop(const string &input_path,
|
|
||||||
const vector<uint8_t> &input,
|
|
||||||
string &output_path,
|
|
||||||
vector<uint8_t> &output)
|
|
||||||
{
|
|
||||||
output.push_back('f');
|
|
||||||
output.push_back('o');
|
|
||||||
output.push_back('o');
|
|
||||||
output_path = get_output_path(input_path);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
int roi_worker_cmd(char *topic)
|
|
||||||
{
|
|
||||||
string worker_name = "roi-worker-";
|
|
||||||
worker_name += to_string(rand());
|
|
||||||
return mq_worker(topic, "roi-worker", roi_worker_handle_image);
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
int roi_worker_nop_cmd(char *topic)
|
|
||||||
{
|
|
||||||
string worker_name = "roi-worker-";
|
|
||||||
worker_name += to_string(rand());
|
|
||||||
return mq_worker(topic, "roi-worker", roi_worker_handle_image_nop);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if ENABLE_GRPC
|
|
||||||
static
|
|
||||||
int grpc_server_cmd(char *addr)
|
|
||||||
{
|
|
||||||
return run_server(addr, roi_worker_handle_image);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static
|
|
||||||
int http_server_handle_image(const vector<uint8_t> &input,
|
|
||||||
vector<uint8_t> &output)
|
|
||||||
{
|
|
||||||
string err;
|
|
||||||
Mat roi;
|
|
||||||
Mat orig = imdecode(input, IMREAD_COLOR);
|
|
||||||
|
|
||||||
if (orig.empty()) {
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
auto r = find_roi(orig, roi, false, err);
|
|
||||||
if (r) return r;
|
|
||||||
imencode(".jpg", roi, output);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
int http_server_cmd(char **argv, int argc)
|
|
||||||
{
|
|
||||||
char *port = argv[0];
|
|
||||||
return start_http_server(atoi(port), http_server_handle_image);
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
int verify_cmd(char **args, int nargs)
|
|
||||||
{
|
|
||||||
char *std_file = args[0];
|
|
||||||
char *frame_file = args[1];
|
|
||||||
Mat std = imread(std_file);
|
|
||||||
Mat frame = imread(frame_file);
|
|
||||||
Mat roi;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
string err;
|
|
||||||
r = roi_process_one(frame_file, false, err, true, &roi);
|
|
||||||
if (r) {
|
|
||||||
printf("failed to find roi: %s\n", err.c_str());
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
double s = emblem_roi_similarity(FuzzyPixelCmp, std, roi, err);
|
|
||||||
|
|
||||||
if (err.size()) {
|
|
||||||
printf("err: %s\n", err.c_str());
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
printf("similarity: %f\n", s); return 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
static
|
||||||
void usage(const char *name, vector<string> &cmds)
|
void usage(const char *name, vector<string> &cmds)
|
||||||
{
|
{
|
||||||
@ -634,28 +135,6 @@ int roi_verify_cmd(char **argv, int argc)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
|
||||||
int side_by_side_cmd(char **argv, int argc)
|
|
||||||
{
|
|
||||||
Mat frame_roi;
|
|
||||||
string err;
|
|
||||||
cout << "side by side processing: " << argv[0] << " " << argv[1] << endl;
|
|
||||||
int r = roi_process_one(argv[0], false, err, true, &frame_roi);
|
|
||||||
if (r) {
|
|
||||||
cerr << "failed to process: " << argv[0] << ":" << err << endl;
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
Mat std_roi = imread(argv[1]);
|
|
||||||
Mat side_by_side;
|
|
||||||
auto roi_size = Size(128, 128);
|
|
||||||
resize(frame_roi, frame_roi, roi_size);
|
|
||||||
resize(std_roi, std_roi, roi_size);
|
|
||||||
hconcat(frame_roi, std_roi, side_by_side);
|
|
||||||
auto fn = string(argv[0]) + ".side_by_side.jpg";
|
|
||||||
imwrite(fn, side_by_side);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef QRTOOL_MAIN
|
#ifdef QRTOOL_MAIN
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@ -673,24 +152,6 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
add_cmd(detect, 1);
|
add_cmd(detect, 1);
|
||||||
add_cmd(angle, 1);
|
add_cmd(angle, 1);
|
||||||
add_cmd(dot, 1);
|
|
||||||
add_cmd(clarity, 1);
|
|
||||||
add_cmd(rectify, 1);
|
|
||||||
add_cmd(topleft, 1);
|
|
||||||
add_cmd(frame_roi, 1);
|
|
||||||
add_cmd(roi, 1);
|
|
||||||
add_cmd(roi_bench, 1);
|
|
||||||
#if USE_PULSAR
|
|
||||||
add_cmd(roi_worker, 1);
|
|
||||||
add_cmd(roi_worker_nop, 1);
|
|
||||||
#endif
|
|
||||||
#if ENABLE_GRPC
|
|
||||||
add_cmd(grpc_server, 1);
|
|
||||||
#endif
|
|
||||||
add_cmd(http_server, 1);
|
|
||||||
add_cmd(verify, 2);
|
|
||||||
add_cmd(roi_verify, 2);
|
|
||||||
add_cmd(side_by_side, 2);
|
|
||||||
usage(argv[0], cmds);
|
usage(argv[0], cmds);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,13 +8,14 @@ using namespace cv;
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
static
|
static
|
||||||
std::string make_resp(bool ok, string err, int angle = -1, string qrcode = "", double elapsed = 0)
|
std::string make_resp(bool ok, string err, float clarity, int angle = -1, string qrcode = "", double elapsed = 0)
|
||||||
{
|
{
|
||||||
char buf[512];
|
char buf[512];
|
||||||
snprintf(buf, sizeof(buf), R"({ "ok": %s, "err": "%s", "qrcode": "%s", "angle": %d, "elapsed": %lf })",
|
snprintf(buf, sizeof(buf), R"({ "ok": %s, "err": "%s", "qrcode": "%s", "clarity": %lf, "angle": %d, "elapsed": %lf })",
|
||||||
ok ? "true" : "false",
|
ok ? "true" : "false",
|
||||||
err.c_str(),
|
err.c_str(),
|
||||||
qrcode.c_str(),
|
qrcode.c_str(),
|
||||||
|
clarity,
|
||||||
angle,
|
angle,
|
||||||
elapsed
|
elapsed
|
||||||
);
|
);
|
||||||
@ -25,35 +26,28 @@ std::string make_resp(bool ok, string err, int angle = -1, string qrcode = "", d
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
const char *qrtool_angle(uint8_t *data,
|
const char *qrtool_angle(uint8_t *data,
|
||||||
int width, int height,
|
int width, int height,
|
||||||
uint8_t *dot_area,
|
uint8_t *mid_left_area,
|
||||||
float camera_sensitivity) {
|
float camera_sensitivity) {
|
||||||
ProcessState ps;
|
ProcessState ps;
|
||||||
ps.laplacian_thres = camera_sensitivity / 10.0;
|
ps.sobel_thres = camera_sensitivity * 3;
|
||||||
ps.sobel_thres = camera_sensitivity * 15;
|
|
||||||
auto start = std::chrono::system_clock::now();
|
auto start = std::chrono::system_clock::now();
|
||||||
static char ret[512];
|
static char ret[512];
|
||||||
printf("qrtool_angle, width: %d height %d\n", width, height);
|
|
||||||
for (int i = 0; i < 16; i++) {
|
|
||||||
printf("%d ", data[i]);
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
Mat orig(Size(width, height), CV_8UC4, data);
|
Mat orig(Size(width, height), CV_8UC4, data);
|
||||||
printf("mat: %d %d\n", orig.cols, orig.rows);
|
|
||||||
string qrcode, err;
|
string qrcode, err;
|
||||||
float angle;
|
float angle;
|
||||||
auto ok = emblem_dot_angle(ps, orig, angle, qrcode, err);
|
auto ok = emblem_dot_angle(ps, orig, angle, qrcode, err);
|
||||||
auto end = std::chrono::system_clock::now();
|
auto end = std::chrono::system_clock::now();
|
||||||
std::chrono::duration<double> elapsed = end-start;
|
std::chrono::duration<double> elapsed = end-start;
|
||||||
auto x = make_resp(ok, err, angle, qrcode, elapsed.count());
|
auto x = make_resp(ok, err, ps.clarity, angle, qrcode, elapsed.count());
|
||||||
if (dot_area) {
|
if (mid_left_area) {
|
||||||
if (!ps.dot_area.empty()) {
|
if (!ps.left_mid_area.empty()) {
|
||||||
Mat da;
|
Mat lma;
|
||||||
ps.dot_area.convertTo(da, CV_8UC4);
|
ps.left_mid_area.convertTo(lma, CV_8UC4);
|
||||||
resize(da, da, Size(32 ,32));
|
resize(lma, lma, Size(32 ,32));
|
||||||
memset(dot_area, 255, 32 * 32 * 4);
|
memset(mid_left_area, 255, 32 * 32 * 4);
|
||||||
memcpy(dot_area, da.ptr(), 32 * 32 * 4);
|
memcpy(mid_left_area, lma.ptr(), 32 * 32 * 4);
|
||||||
} else {
|
} else {
|
||||||
memset(dot_area, 55, 32 * 32 * 4);
|
memset(mid_left_area, 55, 32 * 32 * 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
snprintf(ret, 512, "%s", x.c_str());
|
snprintf(ret, 512, "%s", x.c_str());
|
||||||
|
|||||||
@ -3893,7 +3893,7 @@ var asmLibraryArg = {
|
|||||||
"y": ___cxa_begin_catch,
|
"y": ___cxa_begin_catch,
|
||||||
"wb": ___cxa_current_primary_exception,
|
"wb": ___cxa_current_primary_exception,
|
||||||
"Ja": ___cxa_decrement_exception_refcount,
|
"Ja": ___cxa_decrement_exception_refcount,
|
||||||
"F": ___cxa_end_catch,
|
"G": ___cxa_end_catch,
|
||||||
"b": ___cxa_find_matching_catch_2,
|
"b": ___cxa_find_matching_catch_2,
|
||||||
"n": ___cxa_find_matching_catch_3,
|
"n": ___cxa_find_matching_catch_3,
|
||||||
"C": ___cxa_find_matching_catch_4,
|
"C": ___cxa_find_matching_catch_4,
|
||||||
@ -3970,7 +3970,7 @@ var asmLibraryArg = {
|
|||||||
"g": invoke_vii,
|
"g": invoke_vii,
|
||||||
"l": invoke_viid,
|
"l": invoke_viid,
|
||||||
"lb": invoke_viidf,
|
"lb": invoke_viidf,
|
||||||
"G": invoke_viididii,
|
"F": invoke_viididii,
|
||||||
"bb": invoke_viidiiid,
|
"bb": invoke_viidiiid,
|
||||||
"W": invoke_viidiiiii,
|
"W": invoke_viidiiiii,
|
||||||
"Pa": invoke_viifff,
|
"Pa": invoke_viifff,
|
||||||
@ -3990,7 +3990,7 @@ var asmLibraryArg = {
|
|||||||
"pa": invoke_viiifii,
|
"pa": invoke_viiifii,
|
||||||
"k": invoke_viiii,
|
"k": invoke_viiii,
|
||||||
"M": invoke_viiiid,
|
"M": invoke_viiiid,
|
||||||
"db": invoke_viiiidd,
|
"cb": invoke_viiiidd,
|
||||||
"kb": invoke_viiiidi,
|
"kb": invoke_viiiidi,
|
||||||
"ya": invoke_viiiidid,
|
"ya": invoke_viiiidid,
|
||||||
"Ba": invoke_viiiidiidiiiiiii,
|
"Ba": invoke_viiiidiidiiiiiii,
|
||||||
@ -4025,7 +4025,7 @@ var asmLibraryArg = {
|
|||||||
"ga": invoke_viiiiiiiiiifii,
|
"ga": invoke_viiiiiiiiiifii,
|
||||||
"O": invoke_viiiiiiiiiii,
|
"O": invoke_viiiiiiiiiii,
|
||||||
"wa": invoke_viiiiiiiiiiiii,
|
"wa": invoke_viiiiiiiiiiiii,
|
||||||
"cb": invoke_viiiiiiiiiiiiii,
|
"db": invoke_viiiiiiiiiiiiii,
|
||||||
"ba": invoke_viiiiiiiiiiiiiii,
|
"ba": invoke_viiiiiiiiiiiiiii,
|
||||||
"Ta": invoke_viiiiiiiiiiiiiiii,
|
"Ta": invoke_viiiiiiiiiiiiiiii,
|
||||||
"gb": invoke_viiiiiiiiiiiiiiiiiiidi,
|
"gb": invoke_viiiiiiiiiiiiiiiiiiidi,
|
||||||
@ -4233,17 +4233,6 @@ function invoke_vii(index, a1, a2) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function invoke_i(index) {
|
|
||||||
var sp = stackSave();
|
|
||||||
try {
|
|
||||||
return getWasmTableEntry(index)();
|
|
||||||
} catch (e) {
|
|
||||||
stackRestore(sp);
|
|
||||||
if (e !== e + 0 && e !== "longjmp") throw e;
|
|
||||||
_setThrew(1, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function invoke_iifii(index, a1, a2, a3, a4) {
|
function invoke_iifii(index, a1, a2, a3, a4) {
|
||||||
var sp = stackSave();
|
var sp = stackSave();
|
||||||
try {
|
try {
|
||||||
@ -4277,6 +4266,17 @@ function invoke_viiid(index, a1, a2, a3, a4) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function invoke_i(index) {
|
||||||
|
var sp = stackSave();
|
||||||
|
try {
|
||||||
|
return getWasmTableEntry(index)();
|
||||||
|
} catch (e) {
|
||||||
|
stackRestore(sp);
|
||||||
|
if (e !== e + 0 && e !== "longjmp") throw e;
|
||||||
|
_setThrew(1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function invoke_viidf(index, a1, a2, a3, a4) {
|
function invoke_viidf(index, a1, a2, a3, a4) {
|
||||||
var sp = stackSave();
|
var sp = stackSave();
|
||||||
try {
|
try {
|
||||||
@ -4772,10 +4772,10 @@ function invoke_viiiiiiiiiddi(index, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a1
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function invoke_viiiidd(index, a1, a2, a3, a4, a5, a6) {
|
function invoke_viiiiiiiiiiiiii(index, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) {
|
||||||
var sp = stackSave();
|
var sp = stackSave();
|
||||||
try {
|
try {
|
||||||
getWasmTableEntry(index)(a1, a2, a3, a4, a5, a6);
|
getWasmTableEntry(index)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
stackRestore(sp);
|
stackRestore(sp);
|
||||||
if (e !== e + 0 && e !== "longjmp") throw e;
|
if (e !== e + 0 && e !== "longjmp") throw e;
|
||||||
@ -4783,10 +4783,10 @@ function invoke_viiiidd(index, a1, a2, a3, a4, a5, a6) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function invoke_viiiiiiiiiiiiii(index, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) {
|
function invoke_viiiidd(index, a1, a2, a3, a4, a5, a6) {
|
||||||
var sp = stackSave();
|
var sp = stackSave();
|
||||||
try {
|
try {
|
||||||
getWasmTableEntry(index)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14);
|
getWasmTableEntry(index)(a1, a2, a3, a4, a5, a6);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
stackRestore(sp);
|
stackRestore(sp);
|
||||||
if (e !== e + 0 && e !== "longjmp") throw e;
|
if (e !== e + 0 && e !== "longjmp") throw e;
|
||||||
|
|||||||
Binary file not shown.
@ -3893,7 +3893,7 @@ var asmLibraryArg = {
|
|||||||
"y": ___cxa_begin_catch,
|
"y": ___cxa_begin_catch,
|
||||||
"wb": ___cxa_current_primary_exception,
|
"wb": ___cxa_current_primary_exception,
|
||||||
"Ja": ___cxa_decrement_exception_refcount,
|
"Ja": ___cxa_decrement_exception_refcount,
|
||||||
"F": ___cxa_end_catch,
|
"G": ___cxa_end_catch,
|
||||||
"b": ___cxa_find_matching_catch_2,
|
"b": ___cxa_find_matching_catch_2,
|
||||||
"n": ___cxa_find_matching_catch_3,
|
"n": ___cxa_find_matching_catch_3,
|
||||||
"C": ___cxa_find_matching_catch_4,
|
"C": ___cxa_find_matching_catch_4,
|
||||||
@ -3970,7 +3970,7 @@ var asmLibraryArg = {
|
|||||||
"g": invoke_vii,
|
"g": invoke_vii,
|
||||||
"l": invoke_viid,
|
"l": invoke_viid,
|
||||||
"lb": invoke_viidf,
|
"lb": invoke_viidf,
|
||||||
"G": invoke_viididii,
|
"F": invoke_viididii,
|
||||||
"bb": invoke_viidiiid,
|
"bb": invoke_viidiiid,
|
||||||
"W": invoke_viidiiiii,
|
"W": invoke_viidiiiii,
|
||||||
"Pa": invoke_viifff,
|
"Pa": invoke_viifff,
|
||||||
@ -3990,7 +3990,7 @@ var asmLibraryArg = {
|
|||||||
"pa": invoke_viiifii,
|
"pa": invoke_viiifii,
|
||||||
"k": invoke_viiii,
|
"k": invoke_viiii,
|
||||||
"M": invoke_viiiid,
|
"M": invoke_viiiid,
|
||||||
"db": invoke_viiiidd,
|
"cb": invoke_viiiidd,
|
||||||
"kb": invoke_viiiidi,
|
"kb": invoke_viiiidi,
|
||||||
"ya": invoke_viiiidid,
|
"ya": invoke_viiiidid,
|
||||||
"Ba": invoke_viiiidiidiiiiiii,
|
"Ba": invoke_viiiidiidiiiiiii,
|
||||||
@ -4025,7 +4025,7 @@ var asmLibraryArg = {
|
|||||||
"ga": invoke_viiiiiiiiiifii,
|
"ga": invoke_viiiiiiiiiifii,
|
||||||
"O": invoke_viiiiiiiiiii,
|
"O": invoke_viiiiiiiiiii,
|
||||||
"wa": invoke_viiiiiiiiiiiii,
|
"wa": invoke_viiiiiiiiiiiii,
|
||||||
"cb": invoke_viiiiiiiiiiiiii,
|
"db": invoke_viiiiiiiiiiiiii,
|
||||||
"ba": invoke_viiiiiiiiiiiiiii,
|
"ba": invoke_viiiiiiiiiiiiiii,
|
||||||
"Ta": invoke_viiiiiiiiiiiiiiii,
|
"Ta": invoke_viiiiiiiiiiiiiiii,
|
||||||
"gb": invoke_viiiiiiiiiiiiiiiiiiidi,
|
"gb": invoke_viiiiiiiiiiiiiiiiiiidi,
|
||||||
@ -4233,17 +4233,6 @@ function invoke_vii(index, a1, a2) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function invoke_i(index) {
|
|
||||||
var sp = stackSave();
|
|
||||||
try {
|
|
||||||
return getWasmTableEntry(index)();
|
|
||||||
} catch (e) {
|
|
||||||
stackRestore(sp);
|
|
||||||
if (e !== e + 0 && e !== "longjmp") throw e;
|
|
||||||
_setThrew(1, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function invoke_iifii(index, a1, a2, a3, a4) {
|
function invoke_iifii(index, a1, a2, a3, a4) {
|
||||||
var sp = stackSave();
|
var sp = stackSave();
|
||||||
try {
|
try {
|
||||||
@ -4277,6 +4266,17 @@ function invoke_viiid(index, a1, a2, a3, a4) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function invoke_i(index) {
|
||||||
|
var sp = stackSave();
|
||||||
|
try {
|
||||||
|
return getWasmTableEntry(index)();
|
||||||
|
} catch (e) {
|
||||||
|
stackRestore(sp);
|
||||||
|
if (e !== e + 0 && e !== "longjmp") throw e;
|
||||||
|
_setThrew(1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function invoke_viidf(index, a1, a2, a3, a4) {
|
function invoke_viidf(index, a1, a2, a3, a4) {
|
||||||
var sp = stackSave();
|
var sp = stackSave();
|
||||||
try {
|
try {
|
||||||
@ -4772,10 +4772,10 @@ function invoke_viiiiiiiiiddi(index, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a1
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function invoke_viiiidd(index, a1, a2, a3, a4, a5, a6) {
|
function invoke_viiiiiiiiiiiiii(index, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) {
|
||||||
var sp = stackSave();
|
var sp = stackSave();
|
||||||
try {
|
try {
|
||||||
getWasmTableEntry(index)(a1, a2, a3, a4, a5, a6);
|
getWasmTableEntry(index)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
stackRestore(sp);
|
stackRestore(sp);
|
||||||
if (e !== e + 0 && e !== "longjmp") throw e;
|
if (e !== e + 0 && e !== "longjmp") throw e;
|
||||||
@ -4783,10 +4783,10 @@ function invoke_viiiidd(index, a1, a2, a3, a4, a5, a6) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function invoke_viiiiiiiiiiiiii(index, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) {
|
function invoke_viiiidd(index, a1, a2, a3, a4, a5, a6) {
|
||||||
var sp = stackSave();
|
var sp = stackSave();
|
||||||
try {
|
try {
|
||||||
getWasmTableEntry(index)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14);
|
getWasmTableEntry(index)(a1, a2, a3, a4, a5, a6);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
stackRestore(sp);
|
stackRestore(sp);
|
||||||
if (e !== e + 0 && e !== "longjmp") throw e;
|
if (e !== e + 0 && e !== "longjmp") throw e;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user