-
Notifications
You must be signed in to change notification settings - Fork 8
/
UserInterface.cpp
378 lines (284 loc) · 12 KB
/
UserInterface.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
/*
* File: UserInterface.cpp
* Author: Jan Dufek
*/
#include "UserInterface.hpp"
#define CAMSHIFT
// Program settings
Settings * UserInterface::settings;
// Original point of click
Point UserInterface::origin;
Size UserInterface::video_size;
UserInterface::UserInterface(Settings& s, Size sz) {
UserInterface::settings = &s;
UserInterface::video_size = sz;
// Show main window including slide bars
create_main_window();
#ifdef CAMSHIFT
// Histogram window
namedWindow("Histogram", 0);
#endif
// Set mouse handler on main window to choose object of interest
setMouseCallback(UserInterface::settings->MAIN_WINDOW, onMouse, 0);
// Set main window to full screen
setWindowProperty(settings->MAIN_WINDOW, CV_WND_PROP_FULLSCREEN, CV_WINDOW_FULLSCREEN);
}
UserInterface::UserInterface(const UserInterface& orig) {
}
UserInterface::~UserInterface() {
}
/**
* Trackbar handler. Called when track bar is clicked on.
*
*/
void UserInterface::on_trackbar(int, void*) {
// Gaussian kernel size must be positive and odd. Or, it can be zero’s and
// then it is computed from sigma.
if (UserInterface::settings->blur_kernel_size % 2 == 0) {
UserInterface::settings->blur_kernel_size++;
}
// Erode size cannot be 0
if (UserInterface::settings->erode_size == 0) {
UserInterface::settings->erode_size++;
}
// Dilate size cannot be 0
if (UserInterface::settings->dilate_size == 0) {
UserInterface::settings->dilate_size++;
}
}
/**
* Shows the main window and creates track bars.
*
*/
void UserInterface::create_main_window() {
// Show new window
namedWindow(UserInterface::settings->MAIN_WINDOW, CV_GUI_NORMAL);
#ifndef CAMSHIFT
// Hue 1 trackbars
createTrackbar("H 1 Min", MAIN_WINDOW, &hue_1_min, 180, on_trackbar);
createTrackbar("H 1 Max", MAIN_WINDOW, &hue_1_max, 180, on_trackbar);
// Hue 2 trackbars
createTrackbar("H 2 Min", MAIN_WINDOW, &hue_2_min, 180, on_trackbar);
createTrackbar("H 2 Max", MAIN_WINDOW, &hue_2_max, 180, on_trackbar);
#endif
// Saturation trackbars
createTrackbar("S Min", UserInterface::settings->MAIN_WINDOW, &UserInterface::settings->saturation_min, 255, on_trackbar);
createTrackbar("S Max", UserInterface::settings->MAIN_WINDOW, &UserInterface::settings->saturation_max, 255, on_trackbar);
// Value trackbars
createTrackbar("V Min", UserInterface::settings->MAIN_WINDOW, &UserInterface::settings->value_min, 255, on_trackbar);
createTrackbar("V Max", UserInterface::settings->MAIN_WINDOW, &UserInterface::settings->value_max, 255, on_trackbar);
// Gaussian blur trackbar
createTrackbar("Blur", UserInterface::settings->MAIN_WINDOW, &UserInterface::settings->blur_kernel_size, min(UserInterface::video_size.height, UserInterface::video_size.width), on_trackbar);
// Target reached radius trackbar
createTrackbar("Radius", UserInterface::settings->MAIN_WINDOW, &UserInterface::settings->target_radius, min(UserInterface::video_size.height, UserInterface::video_size.width), on_trackbar);
// Proportional controller trackbar
createTrackbar("Proportion", UserInterface::settings->MAIN_WINDOW, &UserInterface::UserInterface::settings->proportional, 100, on_trackbar);
// Camera angle trackbar
createTrackbar("Angle", UserInterface::UserInterface::settings->MAIN_WINDOW, &UserInterface::UserInterface::settings->camera_angle_degrees, 90, on_trackbar);
#ifndef CAMSHIFT
// Erode size trackbar
createTrackbar("Erode", MAIN_WINDOW, &erode_size, min(UserInterface::video_size.height, UserInterface::video_size.width), on_trackbar);
// Dilate size trackbar
createTrackbar("Dilate", MAIN_WINDOW, &dilate_size, min(UserInterface::video_size.height, UserInterface::video_size.width), on_trackbar);
#endif
}
/**
* Mouse handler.
*
*/
void UserInterface::onMouse(int event, int x, int y, int flags, void*) {
// Select object mode
if (select_object) {
// Get selected rectangle
selection.x = MIN(x, UserInterface::origin.x);
selection.y = MIN(y, UserInterface::origin.y);
selection.width = abs(x - UserInterface::origin.x);
selection.height = abs(y - UserInterface::origin.y);
// Get intersection with the original image
selection &= Rect(0, 0, UserInterface::video_size.width, UserInterface::video_size.height); // TODO check if works
}
// Check mouse button
switch (event) {
// Right drag is reserved for moving over the image
// Left click context menu is disabled
// Scrool is reserved for zoom
// Right drag to select EMILY
case EVENT_RBUTTONDOWN:
// Save current point as click origin
UserInterface::origin = Point(x, y);
// Initialize rectangle
selection = Rect(x, y, 0, 0);
// Start selection
select_object = true;
break;
case EVENT_RBUTTONUP:
// End selection
select_object = false;
// If the selection has been made, start tracking
if (selection.width > 0 && selection.height > 0) {
object_selected = -1;
}
break;
// Left double click to choose target
case EVENT_LBUTTONDBLCLK:
// Get location of the target
target_location = Point(x, y);
target_reached = false;
//cout << int_to_string(target_location.x) + " " + int_to_string(target_location.y) << endl;
break;
#ifdef ANALYSIS
case EVENT_MOUSEMOVE:
// Get mouse location
mouse_location = Point(x, y);
// Print mouse location
//cout << int_to_string(mouse_location.x) + " " + int_to_string(mouse_location.y) << endl;
break;
#endif
}
}
/**
* Draws position of the object as crosshairs with the center in the object's
* centroid.
*
* @param x x coordinate
* @param y y coordinate
* @param radius radius of crosshairs
* @param frame frame to which draw into
*/
void UserInterface::draw_position(int x, int y, double radius, Mat &frame) {
#ifndef CAMSHIFT
// Circle
circle(frame, Point(x, y), radius, UserInterface::settings->LOCATION_COLOR, UserInterface::settings->LOCATION_THICKNESS);
#endif
// Lines
if (y - radius > 0) {
line(frame, Point(x, y), Point(x, y - radius), UserInterface::settings->LOCATION_COLOR, UserInterface::settings->LOCATION_THICKNESS);
} else {
line(frame, Point(x, y), Point(x, 0), UserInterface::settings->LOCATION_COLOR, UserInterface::settings->LOCATION_THICKNESS);
}
if (y + radius < UserInterface::video_size.height) {
line(frame, Point(x, y), Point(x, y + radius), UserInterface::settings->LOCATION_COLOR, UserInterface::settings->LOCATION_THICKNESS);
} else {
line(frame, Point(x, y), Point(x, UserInterface::video_size.height), UserInterface::settings->LOCATION_COLOR, UserInterface::settings->LOCATION_THICKNESS);
}
if (x - radius > 0) {
line(frame, Point(x, y), Point(x - radius, y), UserInterface::settings->LOCATION_COLOR, UserInterface::settings->LOCATION_THICKNESS);
} else {
line(frame, Point(x, y), Point(0, y), UserInterface::settings->LOCATION_COLOR, UserInterface::settings->LOCATION_THICKNESS);
}
if (x + radius < UserInterface::video_size.width) {
line(frame, Point(x, y), Point(x + radius, y), UserInterface::settings->LOCATION_COLOR, UserInterface::settings->LOCATION_THICKNESS);
} else {
line(frame, Point(x, y), Point(UserInterface::video_size.width, y), UserInterface::settings->LOCATION_COLOR, UserInterface::settings->LOCATION_THICKNESS);
}
// Text coordinates
putText(frame, "[" + int_to_string(x) + "," + int_to_string(y) + "]", Point(x, y + radius + 20), 1, 1, UserInterface::settings->LOCATION_COLOR, 1, 8);
}
/**
* Draws axis of given rotated rectangle. Axis is an principal axis of symmetry.
*
* @param rectangle rotated rectangle for which to draw principal axis
*/
void UserInterface::draw_principal_axis(RotatedRect rectangle, Mat& frame) {
// Get EMILY pose as the principal symmetry axis of bounding rectangle
// Get points of bounding rectangle
Point2f rectangle_points[4];
rectangle.points(rectangle_points);
// Initialize variables to look for the rectangle shortest side
double shortest_axis = DBL_MAX;
int shortest_axis_index;
// For each side
for (int j = 0; j < 4; j++) {
// Line length
double line_length = norm(rectangle_points[j] - rectangle_points[(j + 1) % 4]);
if (line_length < shortest_axis) {
shortest_axis = line_length;
shortest_axis_index = j;
}
// Draw line of the bounding rectangle
//line( frame, rectangle_points[j], rectangle_points[(j + 1) % 4], color, 1, 8 );
}
// Get midpoints of the shortest sides
Point shortest_axis_midpoint_1 = (rectangle_points[shortest_axis_index] + rectangle_points[(shortest_axis_index + 1) % 4]) * 0.5;
Point shortest_axis_midpoint_2 = (rectangle_points[(shortest_axis_index + 2) % 4] + rectangle_points[(shortest_axis_index + 3) % 4]) * 0.5;
// Save EMILY pose
emily_pose_point_1 = shortest_axis_midpoint_1;
emily_pose_point_2 = shortest_axis_midpoint_2;
// Draw line representing principal axis of symmetry
line(frame, shortest_axis_midpoint_1, shortest_axis_midpoint_2, UserInterface::settings->POSE_LINE_COLOR, UserInterface::settings->POSE_LINE_THICKNESS, 8);
}
/**
* Draws current target location.
*
* @param frame
* @param target_location
*/
void UserInterface::draw_target(Mat& frame, Point target_location) {
if (target_location.x != 0 && target_location.y != 0) {
circle(frame, target_location, settings->TARGET_RADIUS - 1, settings->TARGET_COLOR, 1, 8, 0);
line(frame, Point(target_location.x - (settings->TARGET_RADIUS / 2), target_location.y + (settings->TARGET_RADIUS / 2)), Point(target_location.x + (settings->TARGET_RADIUS / 2), target_location.y - (settings->TARGET_RADIUS / 2)), settings->TARGET_COLOR, 1, 8, 0);
line(frame, Point(target_location.x - (settings->TARGET_RADIUS / 2), target_location.y - (settings->TARGET_RADIUS / 2)), Point(target_location.x + (settings->TARGET_RADIUS / 2), target_location.y + (settings->TARGET_RADIUS / 2)), settings->TARGET_COLOR, 1, 8, 0);
// Draw target acceptance radius
circle(frame, target_location, settings->target_radius, settings->TARGET_COLOR, 1, 8, 0);
}
}
/**
* Prints current status to the GUI.
*
* @param frame
* @param status
* @param time_to_target
*/
void UserInterface::print_status(Mat& frame, int status, double time_to_target) {
String stringStatus;
switch (status) {
case 0:
stringStatus = "Initialization";
break;
case 1:
stringStatus = "Select EMILY and target.";
break;
case 2:
stringStatus = "Target set. Getting orientation.";
break;
case 3:
stringStatus = "Target set. Going to target.";
break;
case 4:
// Covert time to target to string
ostringstream stringStream;
stringStream << time_to_target;
std::string timeToTargetString = stringStream.str();
stringStatus = "Target reached in " + timeToTargetString + " s";
break;
}
// Print status
putText(frame, stringStatus, Point(50, 50), FONT_HERSHEY_SIMPLEX, 1, Scalar(0, 0, 255), 2);
}
/**
* Convert integer to string.
*
* @param number integer to be converted to string
*
*/
string UserInterface::int_to_string(int number) {
stringstream stringStream;
stringStream << number;
return stringStream.str();
}
/**
* Show main window.
*
* @param mat
*/
void UserInterface::show_main(Mat& mat) {
imshow(UserInterface::settings->MAIN_WINDOW, mat);
}
/**
* Show histogram window.
*
* @param mat
*/
void UserInterface::show_histogram(Mat& mat) {
imshow(UserInterface::settings->HISTOGRAM_WINDOW, mat);
}