diff --git a/alg/angle.cpp b/alg/angle.cpp deleted file mode 100644 index 92464ff..0000000 --- a/alg/angle.cpp +++ /dev/null @@ -1,211 +0,0 @@ -#include -#include "libqr.h" - -static void clear_connected(Mat &bin, Point p) -{ - vector q; - q.push_back(p); - while (q.size()) { - auto p = q[q.size() - 1]; - q.pop_back(); - bin.at(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(ny, nx)) { - q.push_back(Point(nx, ny)); - } - } - } - } -} - -static -vector find_points(Mat bin) -{ - vector ret; - for (int x = 0; x < bin.cols; x++) { - for (int y = 0; y < bin.rows; y++) { - auto p = bin.at(y, x); - if (!p) continue; - auto point = Point(x, y); - ret.push_back(point); - clear_connected(bin, point); - } - } - return ret; -} - -static -bool in_center(Mat &bin, Point &p) -{ - int margin = bin.rows * 2 / 10; - - return p.x > margin && p.x < bin.cols - margin && p.y > margin && p.y <= bin.rows - margin; -} - -static -float distance(Point &p, Point &q) -{ - auto xdiff = p.x - q.x; - auto ydiff = p.y - q.y; - return xdiff * xdiff + ydiff * ydiff; -} - -static -int find_closest(Point &p, vector &points, bool left, bool top) -{ - int ret = -1; - for (int ii = 0; ii < points.size(); ii++) { - auto i = points[ii]; - if (i.x == p.x && i.y == p.y) continue; - if (left && i.x > p.x) continue; - if (top && i.y > p.y) continue; - if (!left && i.x <= p.x) continue; - if (!top && i.y < p.y) continue; - if (ret < 0 || distance(p, points[ret]) > distance(p, i)) { - ret = ii; - } - } - return ret; -} - -static -float find_angle(Point &p, vector &points) -{ - // Find 4 dots in 4 quadrant (if any) - // Then find 2 closest on y axis - // Then calculate angle between those two - - auto topleft = find_closest(p, points, true, true); - auto bottomright = find_closest(p, points, false, false); - - if (topleft < 0 || bottomright < 0) - return -1; - auto a = points[topleft]; - auto b = points[bottomright]; - printf("point %d %d top left %d %d, bottom right %d %d\n", p.x, p.y, a.x, a.y, b.x, b.y); - if (a.y == b.y) return 0; - auto ret = atan((b.x - a.x) / (b.y - a.y)) * 180.0 / CV_PI; - if (ret < 0) ret += 90; - if (ret > 45) ret = 90 - ret; - return ret; -} - -static -void angle_stat(vector angles, float &median, float &variance) -{ - std::sort(angles.begin(), angles.end()); - float sum = 0; - for (auto x: angles) { - sum += x; - } - auto mid = angles.size() / 2; - median = angles[mid]; - auto avg = sum / angles.size(); - variance = 0; - for (auto x: angles) { - auto diff = x - avg; - variance += diff * diff; - } -} - -float hough_lines_angle(Mat &img, string &err) -{ - show(img); - vector lines; - HoughLines(img, lines, 1, CV_PI / 180, 6, 0, 0); - for (auto x: lines) { - printf("line: %.1f %.1f %.1f\n", x[0], x[1] * 180.0 / CV_PI, x[2]); - } - if (!lines.size()) { - err = "cannot find lines in image"; - return -1; - } - - int total_weight = 0; - for (int i = 0; i < lines.size() && i < 5; i++) { - total_weight += lines[i][2]; - } - int acc = 0; - float ret = 0; - for (int i = 0; i < lines.size(); i++) { - acc += lines[i][2]; - if (acc >= total_weight / 2) { - ret = lines[i][1] * 180.0 / CV_PI; - break; - } - } - while (ret < 0) { - ret += 90; - } - while (ret > 90) { - ret -= 90; - } - if (ret > 45) { - ret = 90 - ret; - } - printf("angle: %f\n", ret); - return ret; -} - -float emblem_detect_angle(Mat &gray, string &err) -{ - Mat bin; - const int min_points = 30; - vector points; - auto kernel = getStructuringElement(MORPH_ELLIPSE, Size(3, 3)); - - adaptiveThreshold(gray, bin, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY_INV, 11, 2); - while (true) { - // In this loop we erode a "full" image in order to get enough detached components - 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(bin, bin, kernel); - } - - while (true) { - // In this loop we further erode a "lean" image in order to get clarity until it's too much - Mat eroded; - erode(bin, eroded, kernel); - auto tmp = find_points(eroded.clone()); - if (tmp.size() < min_points) { - printf("too much\n"); - break; - } - bin = eroded.clone(); - } - - return hough_lines_angle(bin, err); - - vector angles; - for (auto p: points) { - if (!in_center(bin, p)) { - continue; - } - auto angle = find_angle(p, points); - if (angle >= 0) { - printf("found angle %f\n", angle); - angles.push_back(angle); - } - } - if (!angles.size()) { - err = "cannot find point to calculate angle"; - return -1; - } - float med, var; - angle_stat(angles, med, var); - printf("med: %f, var: %f\n", med, var); - return med; -}