utility.cpp 5.58 KB
Newer Older
Matteo's avatar
Matteo committed
1
#include "utility.hpp"
Matteo's avatar
Matteo committed
2

3
4
5
#include <filesystem>
#include <fstream>
#include <nlohmann/json.hpp>
Matteo's avatar
update  
Matteo committed
6
7
8

using namespace cv;
using namespace std;
Matteo's avatar
Matteo committed
9
namespace fs = std::filesystem;
Matteo's avatar
update  
Matteo committed
10

11
12
using json = nlohmann::json;

Matteo's avatar
Matteo committed
13
14
15
16
void utility::detect_shape(Ptr<GeneralizedHoughGuil> alg, int pos_thresh, vector<Vec4f>& positive_positions,
                           Mat& positive_votes, vector<Vec4f>& negative_positions, Mat& negative_votes,
                           Mat processing_area) {
    alg->setPosThresh(pos_thresh);
17

Matteo's avatar
Matteo committed
18
19
20
    int num_prev_matches = 0;
    int threshold_increment = 0;
    int max_match_score = 0;
Matteo's avatar
Matteo committed
21
22
23
24
25

    // Process shapes with positive angles
    alg->setMinAngle(0);
    alg->setMaxAngle(3);
    while (true) {
Matteo's avatar
Matteo committed
26
27
28
        alg->detect(processing_area, positive_positions, positive_votes);
        int current_matches = positive_positions.size();
        if (current_matches == 1 || (current_matches == 0 && num_prev_matches == 0)) {
Matteo's avatar
Matteo committed
29
            // We detected the most interesting shape
Matteo's avatar
Matteo committed
30
            // Impossible to find with these parameters
Matteo's avatar
Matteo committed
31
            break;
Matteo's avatar
Matteo committed
32
        } else if (current_matches == 0 && num_prev_matches > 0) {
Matteo's avatar
Matteo committed
33
34
            // It is not possible to detect only one shape with the current
            // parameters
Matteo's avatar
Matteo committed
35
36
37
            alg->setPosThresh(pos_thresh + threshold_increment - 1);  // Decrease position value
            alg->detect(processing_area, positive_positions,
                        positive_votes);  // Detect all available shapes
Matteo's avatar
Matteo committed
38
39
            break;
        }
Matteo's avatar
Matteo committed
40
        num_prev_matches = current_matches;
Matteo's avatar
Matteo committed
41
        // Find maximum vote
Matteo's avatar
Matteo committed
42
43
        for (int j = 0; j < positive_votes.cols / 3; j++) {
            if (positive_votes.at<int>(3 * j) > max_match_score) max_match_score = positive_votes.at<int>(3 * j);
Matteo's avatar
Matteo committed
44
45
        }

Matteo's avatar
Matteo committed
46
47
48
49
50
        if (current_matches > 10) {
            threshold_increment += 5;  // To speed up computation when there are too many matches
        } else if (max_match_score - (pos_thresh + threshold_increment) > 100) {
            threshold_increment += 100;  // To speed up computation when there are few super high
                                         // matches
Matteo's avatar
Matteo committed
51
        } else {
Matteo's avatar
Matteo committed
52
            threshold_increment++;
Matteo's avatar
Matteo committed
53
        }
Matteo's avatar
Matteo committed
54
        alg->setPosThresh(pos_thresh + threshold_increment);
Matteo's avatar
Matteo committed
55
56
57
    }

    // Reset incremental position value
Matteo's avatar
Matteo committed
58
59
60
    threshold_increment = 0;
    num_prev_matches = 0;
    max_match_score = 0;
Matteo's avatar
Matteo committed
61
62
63
64
    // Process shapes with negative angles
    alg->setMinAngle(357);
    alg->setMaxAngle(360);
    while (true) {
Matteo's avatar
Matteo committed
65
66
67
        alg->detect(processing_area, negative_positions, negative_votes);
        int current_matches = negative_positions.size();
        if (current_matches == 1 || (current_matches == 0 && num_prev_matches == 0)) {
Matteo's avatar
Matteo committed
68
            // We detected the most interesting shape
Matteo's avatar
Matteo committed
69
            // Impossible to found with these parameters
Matteo's avatar
Matteo committed
70
            break;
Matteo's avatar
Matteo committed
71
        } else if (current_matches == 0 && num_prev_matches > 0) {
Matteo's avatar
Matteo committed
72
73
            // It is not possible to detect only one shape with the current
            // parameters
Matteo's avatar
Matteo committed
74
75
76
            alg->setPosThresh(pos_thresh + threshold_increment - 1);  // Decrease position value
            alg->detect(processing_area, negative_positions,
                        negative_votes);  // Detect all available shapes
Matteo's avatar
Matteo committed
77
78
            break;
        }
Matteo's avatar
Matteo committed
79
        num_prev_matches = current_matches;
Matteo's avatar
Matteo committed
80
81

        // Find maximum vote
Matteo's avatar
Matteo committed
82
83
        for (int j = 0; j < positive_votes.cols / 3; j++) {
            if (positive_votes.at<int>(3 * j) > max_match_score) max_match_score = positive_votes.at<int>(3 * j);
Matteo's avatar
Matteo committed
84
85
        }

Matteo's avatar
Matteo committed
86
87
88
89
90
        if (current_matches > 10) {
            threshold_increment += 5;  // To speed up computation when there are too many matches
        } else if (max_match_score - (pos_thresh + threshold_increment) > 100) {
            threshold_increment += 100;  // To speed up computation when there are few super high
                                         // matches
Matteo's avatar
Matteo committed
91
        } else {
Matteo's avatar
Matteo committed
92
            threshold_increment++;
Matteo's avatar
Matteo committed
93
        }
Matteo's avatar
Matteo committed
94
        alg->setPosThresh(pos_thresh + threshold_increment);
Matteo's avatar
Matteo committed
95
    }
Matteo's avatar
update  
Matteo committed
96
97
}

Matteo's avatar
Matteo committed
98
RotatedRect utility::drawShapes(Mat frame, const Vec4f& positions, Scalar color, int width, int height, int offsetX,
Matteo's avatar
Matteo committed
99
                                int offsetY, float processingScale) {
Matteo's avatar
update  
Matteo committed
100
101
102
    RotatedRect rr;
    Point2f rrpts[4];

Matteo's avatar
Matteo committed
103
    Point2f pos(positions[0] + offsetX, positions[1] + offsetY);
Matteo's avatar
update  
Matteo committed
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
    float scale = positions[2];
    float angle = positions[3];

    rr.center = pos * processingScale;
    rr.size = Size2f(width * scale * processingScale, height * scale * processingScale);
    rr.angle = angle;

    rr.points(rrpts);

    line(frame, rrpts[0], rrpts[1], color, 2);
    line(frame, rrpts[1], rrpts[2], color, 2);
    line(frame, rrpts[2], rrpts[3], color, 2);
    line(frame, rrpts[3], rrpts[0], color, 2);

    return rr;
}

Matteo's avatar
Matteo committed
121
122
123
124
125
126
127
128
129
Threshold::Threshold(float percentual, int angle, int scale, int pos) {
    if (percentual < 0 || percentual > 100) throw std::invalid_argument("Percentual must be between 0 and 100");

    this->percentual = percentual;
    this->angle = angle;
    this->scale = scale;
    this->pos = pos;
}

130
SceneObject::SceneObject(int minDist, Threshold threshold) {
Matteo's avatar
Matteo committed
131
132
    this->minDist = minDist;
    this->threshold = threshold;
133
134
}

Matteo's avatar
Matteo committed
135
SceneObject SceneObject::from_file(fs::path path, ROI obj) {
Matteo's avatar
Matteo committed
136
137
138
139
    ifstream iConfig(path);
    json j;
    iConfig >> j;

Matteo's avatar
Matteo committed
140
    if (obj == ROI::TAPE) {
Matteo's avatar
Matteo committed
141
        return SceneObject(j["MinDist"],
Matteo's avatar
Matteo committed
142
                           Threshold(j["TapeThresholdPercentual"], j["AngleThresh"], j["ScaleThresh"], j["PosThresh"]));
Matteo's avatar
Matteo committed
143
    } else {
Matteo's avatar
Matteo committed
144
145
        return SceneObject(j["MinDistCapstan"], Threshold(j["CapstanThresholdPercentual"], j["AngleThreshCapstan"],
                                                          j["ScaleThreshCapstan"], j["PosThreshCapstan"]));
Matteo's avatar
Matteo committed
146
    }
Matteo's avatar
update  
Matteo committed
147
}