utility.h 6.92 KB
Newer Older
Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
1
using namespace cv;
2
using namespace std;
3
namespace fs = std::filesystem;
4

Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*************************************************************************************************/
/*************************************** OpenCV FUNCTIONS ****************************************/
/*************************************************************************************************/

/**
 * @brief Detects a given shape in an image, using a the OpenCV algorithm GeneralizedHoughGuil.
 *
 * @param[in] alg the algorithm instance;
 * @param[in] templateShape the shape to detect;
 * @param[in] posThresh the position votes threshold;
 * @param[out] positivePositions vector representing the position assigned to each found rectangle for positive angles;
 * @param[out] positiveVotes vector representing the vote assigned to each found rectangle for positive angles;
 * @param[out] negativePositions vector representing the position assigned to each found rectangle for negative angles;
 * @param[out] negativeVotes vector representing the vote assigned to each found rectangle for negative angles;
 * @param[in] processingArea the image to be processed.
 */
Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
21
void detectShape(Ptr<GeneralizedHoughGuil> alg, Mat templateShape, int posThresh, vector<Vec4f> &positivePositions, Mat &positiveVotes, vector<Vec4f> &negativePositions, Mat &negativeVotes, Mat processingArea) {
22

Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
23
24
25
26
27
28
29
30
31
	alg -> setPosThresh(posThresh);
	alg -> setTemplate(templateShape);

	int oldSizePositive = 0;
	int i = 0;
	int maxVote = 0;

	// Process shapes with positive angles
	alg -> setMinAngle(0);
32
	alg -> setMaxAngle(3);
Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
33
34
35
36
37
38
39
40
41
42
43
44
	while (true) {
		alg -> detect(processingArea, positivePositions, positiveVotes);
		int currentSize = positivePositions.size();
		if (currentSize == 1) {
			// We detected the most interesting shape
			break;
		} else if (currentSize == 0 && oldSizePositive > 0) {
			// It is not possible to detect only one shape with the current parameters
			alg -> setPosThresh(posThresh+i-1); // Decrease position value
			alg -> detect(processingArea, positivePositions, positiveVotes); // Detect all available shapes
			break;
		} else if (currentSize == 0 && oldSizePositive == 0) {
45
			// Impossible to find with these parameters
Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
			break;
		}
		oldSizePositive = currentSize;
		// Find maximum vote
		for (int j = 0; j < positiveVotes.cols / 3; j++) {
			if (positiveVotes.at<int>(3*j) > maxVote)
				maxVote = positiveVotes.at<int>(3*j);
		}

		if (currentSize > 10) {
			i += 5; // To speed up computation when there are too many matches
		} else if (maxVote - (posThresh + i) > 100) {
			i += 100; // To speed up computation when there are few super high matches
		} else {
			i++;
		}
		alg -> setPosThresh(posThresh+i);
	}

	int oldSizeNegative = 0;
	// Reset incremental position value
	i = 0;
	maxVote = 0;
	// Process shapes with negative angles
70
	alg -> setMinAngle(357);
Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
	alg -> setMaxAngle(360);
	while (true) {
		alg -> detect(processingArea, negativePositions, negativeVotes);
		int currentSize = negativePositions.size();
		if (currentSize == 1) {
			// We detected the most interesting shape
			break;
		} else if (currentSize == 0 && oldSizeNegative > 0) {
			// It is not possible to detect only one shape with the current parameters
			alg -> setPosThresh(posThresh+i-1); // Decrease position value
			alg -> detect(processingArea, negativePositions, negativeVotes); // Detect all available shapes
			break;
		} else if (currentSize == 0 && oldSizeNegative == 0) {
			// Impossible to found with these parameters
			break;
		}
		oldSizeNegative = currentSize;

		// Find maximum vote
		for (int j = 0; j < positiveVotes.cols / 3; j++) {
			if (positiveVotes.at<int>(3*j) > maxVote)
				maxVote = positiveVotes.at<int>(3*j);
		}

		if (currentSize > 10) {
			i += 5; // To speed up computation when there are too many matches
		} else if (maxVote - (posThresh + i) > 100) {
			i += 100; // To speed up computation when there are few super high matches
		} else {
			i++;
		}
		alg -> setPosThresh(posThresh+i);
	}
}

Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
106
107
108
109
110
111
112
113
114
115
116
117
118
119

/**
 * @brief Draw rectangles on an image.
 *
 * @param frame Frame on which the rectangles will be drawn;
 * @param positions The position of the rectangle;
 * @param color The color of the rectangle;
 * @param width The width of the rectangle;
 * @param height The height of the rectangle;
 * @param offsetX X offset on the position of the rectangle;
 * @param offsetY Y offset on the position of the rectangle;
 * @param processingScale Scaling factor, useful for downsizing.
 * @return RotatedRect Object representing the drawn rectangle.
 */
120
RotatedRect drawShapes(Mat frame, Vec4f &positions, Scalar color, int width, int height, int offsetX, int offsetY, float processingScale) {
Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
121
122
123
124

	RotatedRect rr;
	Point2f rrpts[4];

125
126
127
	Point2f pos(positions[0]+offsetX, positions[1]+offsetY);
	float scale = positions[2];
	float angle = positions[3];
Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
128

129
130
131
	rr.center = pos * processingScale;
	rr.size = Size2f(width * scale * processingScale, height * scale * processingScale);
	rr.angle = angle;
Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
132

133
	rr.points(rrpts);
Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
134

135
136
137
138
	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);
Nadir Dalla Pozza's avatar
Update.    
Nadir Dalla Pozza committed
139
140

	return rr;
Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
141
142
}

143

Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
144
145
146
147
148
149
150
151
152
153
154
/**
 * @brief Function to deinterlace the current image.
 *
 * @param[in] frame image to be processed;
 * @param[out] odd_frame odd plane;
 * @param[out] even_frame even plane.
 */
void separateFrame(cv::Mat frame, cv::Mat &odd_frame, cv::Mat &even_frame) {

	int i_odd_frame = 0;
	int i_even_frame = 0;
155
156
157
158

	for (int i = 0; i < frame.rows; i++) {
		for (int j = 0; j < frame.cols; j++) {
			if (i % 2 == 0) {
Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
159
160
161
				even_frame.at<cv::Vec3b>( i_even_frame, j )[0] = frame.at<cv::Vec3b>(i, j)[0];
				even_frame.at<cv::Vec3b>( i_even_frame, j )[1] = frame.at<cv::Vec3b>(i, j)[1];
				even_frame.at<cv::Vec3b>( i_even_frame, j )[2] = frame.at<cv::Vec3b>(i, j)[2];
162
			} else {
Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
163
164
165
				odd_frame.at<cv::Vec3b>( i_odd_frame, j )[0] = frame.at<cv::Vec3b>(i, j)[0];
				odd_frame.at<cv::Vec3b>( i_odd_frame, j )[1] = frame.at<cv::Vec3b>(i, j)[1];
				odd_frame.at<cv::Vec3b>( i_odd_frame, j )[2] = frame.at<cv::Vec3b>(i, j)[2];
166
167
168
169
			}
		}

		if (i % 2 == 0) {
Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
170
			i_even_frame++;
171
		} else {
Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
172
			i_odd_frame++;
173
174
175
176
177
178
179
		}
	}

	return;

}

Nadir Dalla Pozza's avatar
Nadir Dalla Pozza committed
180
181
182
183
184
185
186
187

/**
 * @brief Compute the number of different pixels between two frames.
 *
 * @param prevFrame the first frame;
 * @param currentFrame the second frame.
 * @return cv::Mat A black and white frame, where black pixels represent a difference, while white pixels represent an equality.
 */
188
189
190
191
192
193
194
195
196
197
198
199
200
201
cv::Mat difference(cv::Mat &prevFrame, cv::Mat &currentFrame) {
	cv::Mat diff = currentFrame.clone();
	for (int i = 0; i < currentFrame.rows; i++) {
		for (int j = 0; j < currentFrame.cols; j++) {
			if (prevFrame.at<cv::Vec3b>(i, j)[0] != currentFrame.at<cv::Vec3b>(i, j)[0] || prevFrame.at<cv::Vec3b>(i, j)[1] != currentFrame.at<cv::Vec3b>(i, j)[1] || prevFrame.at<cv::Vec3b>(i, j)[2] != currentFrame.at<cv::Vec3b>(i, j)[2]) {
				// Different pixels
				diff.at<cv::Vec3b>(i, j)[0] = 0;
			} else {
				// Identical pixels
				diff.at<cv::Vec3b>(i, j)[0] = 255;
			}
		}
	}
	return diff;
202
}