alg: Delete angle.cpp

This commit is contained in:
Fam Zheng 2025-03-02 10:53:32 +00:00
parent 690f500ba6
commit 9e344b9920

View File

@ -1,211 +0,0 @@
#include <algorithm>
#include "libqr.h"
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
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<Point> &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<Point> &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<float> 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<Vec3f> 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<Point> 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<float> 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;
}