Anubis - Bachelor thesis project

interface.py
Go to the documentation of this file.
1 # Anubis is a program to control industrial cameras and train and use artificial neural networks
2 # Copyright (C) 2021 Lukaszczyk Jakub
3 #
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or
7 # any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program. If not, see <https://www.gnu.org/licenses/>.
16
17
18
19 from PyQt5 import QtCore, QtGui, QtWidgets
20 import threading
21 import time
22 import win32api
23 import os
24 from queue import Queue
25 import webbrowser
26
27 from prediction_graph import Prediction_graph
28 from global_camera import cam
29 from global_queue import active_frame_queue
30 from computer_vision import Computer_vision
31 from config_level import Config_level
32
33
34 class Ui_MainWindow(QtCore.QObject):
35 """!@brief Main class for user interface
36 @details This file implements Ui_MainWindow class which defines the application's
37 graphical user interface. Methods setupUi and retranslateUi are generated from
38 QtDesigner using pyuic5 tool. When modifying the GUI these methods should be
39 carefully edited with regards to calls at their ends which are used to bind
40 methods to the widgets and initialize other variables.
41 Methods in the class are mainly used to check some conditions and run methods
42 of other connected classes like Camera and Computer_vision.
43 """
44 def __init__(self):
45 """!@brief Initialize the class and all its variables
46 """
47
48 super(Ui_MainWindow,self).__init__()
49
50
51 self.feat_refresh_timer = QtCore.QTimer(self)
52 self.feat_refresh_timer.setInterval(4000)
53 self.feat_refresh_timer.timeout.connect(self.update_parameters)
54 self.feat_refresh_timer.timeout.connect(self.start_refresh_parameters)
55 self.feat_refresh_timer.start()
56
57
58 self.image_pixmap = None
59
60 self.w_preview = 0
61
62 self.h_preview = 0
63
64
65 self.model_loaded = False
66
67
68 self.move_x_prev = 0
69
70 self.move_y_prev = 0
71
72 self.process_perc = [0]
73
74
75 self.parameter_values = {}
76
77
78 self.update_completed_flag = threading.Event()
79 self.update_completed_flag.set()
80
81
82 self.update_flag = threading.Event()
83
84
85 self.preview_zoom = 1
86
87 self.preview_fit = True
88
89
90 self.top_items = {}
91
92 self.children_items = {}
93
94
95 self.feat_widgets = {}
96
97 self.feat_labels = {}
98
99 self.feat_queue = Queue()
100
101
102 self.detected = []
103
104 self.connected = False
105
106
107 self.training_flag = threading.Event()
108
109 self.param_flag = threading.Event()
110
111
112 self.process_flag = threading.Event()
113
114 self.process_prog_flag = threading.Event()
115
116
117 self.callback_train_signal = QtWidgets.QLineEdit()
118 self.callback_train_signal.textChanged.connect(self.update_training)
119
120
121 self.callback_process_signal = QtWidgets.QLineEdit()
122 self.callback_process_signal.textChanged.connect(self.update_processing)
123
124
125 self.resize_signal = QtWidgets.QLineEdit()
126 self.resize_signal.textChanged.connect(self.update_img)
127
128
129 self.parameters_signal = QtWidgets.QLineEdit()
130 self.parameters_signal.textChanged.connect(self.show_parameters)
131
132
133 self.progress_flag = threading.Event()
134
135
136 self.train_vals = {'progress': 0,
137 'loss': 0,
138 'acc': 0,
139 'val_loss': 0,
140 'val_acc': 0,
141 'max_epoch': 0,
142 'epoch': 0}
143
144
145 self.prediction_flag = threading.Event()
146
147
148 self.interupt_flag = threading.Event()
149
150
151 self.recording = False
152
153 self.preview_live = False
154
155
156 self.icon_offline = QtGui.QPixmap("./icons/icon_offline.png")
157
158 self.icon_standby = QtGui.QPixmap("./icons/icon_standby.png")
159
160 self.icon_busy = QtGui.QPixmap("./icons/icon_busy.png")
161
162
163 self.fps = 0.0
164
165 self.received = 0
166
167
168 self.status_timer = QtCore.QTimer()
169
170
171
172 def setupUi(self, MainWindow):
173 """!@brief Create GUI widgets
174 @details Excluding section marked as added manually, the whole
175 method is generated by pyuic5 tool and should not be modified otherwise
176 because the changes are hard to track outside added manually section.
177 In this method all widgets, tabs, buttons etc. are created but not
178 named yet.
179 """
180
181 MainWindow.setObjectName("MainWindow")
182 MainWindow.resize(1005, 610)
183 self.centralwidget = QtWidgets.QWidget(MainWindow)
184 self.centralwidget.setObjectName("centralwidget")
185
186 #Definition of basic layout
187 #----------------------------------------------------------------
188 self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
189 self.gridLayout.setObjectName("gridLayout")
190
191 self.preview_and_control = QtWidgets.QWidget(self.centralwidget)
192 self.preview_and_control.setObjectName("preview_and_control")
193
194 self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.preview_and_control)
195 self.verticalLayout_2.setObjectName("verticalLayout_2")
196
197 #Window with camera preview
198 #-------------------------------------------------------------------
199 self.preview_area = QtWidgets.QScrollArea(self.preview_and_control)
200 #disables scrollbars in preview window
201 #self.preview_area.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
202 #self.preview_area.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
203 self.preview_area.installEventFilter(self)
204
205 self.camera_preview = QtWidgets.QLabel(self.preview_area)
206 self.camera_preview.setAutoFillBackground(False)
207 self.camera_preview.setText("")
208 self.camera_preview.setSizePolicy(QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Ignored)
209 self.camera_preview.setPixmap(QtGui.QPixmap("default_preview.png"))
210 self.camera_preview.setScaledContents(False)
211 self.camera_preview.setIndent(-1)
212 self.camera_preview.setObjectName("camera_preview")
213 self.preview_area.setWidget(self.camera_preview)
214 self.verticalLayout_2.addWidget(self.preview_area)
215
216 #Definition of buttons to control camera (bottom right)
217 #-------------------------------------------------------------------
218 self.widget_controls = QtWidgets.QWidget(self.preview_and_control)
219 self.widget_controls.setObjectName("widget_controls")
220
221 self.gridLayout_4 = QtWidgets.QGridLayout(self.widget_controls)
222 self.gridLayout_4.setObjectName("gridLayout_4")
223
224 self.btn_zoom_in = QtWidgets.QPushButton(self.widget_controls)
225 self.btn_zoom_in.setObjectName("btn_zoom_in")
226 self.gridLayout_4.addWidget(self.btn_zoom_in, 0, 2, 1, 1)
227
228 self.btn_zoom_out = QtWidgets.QPushButton(self.widget_controls)
229 self.btn_zoom_out.setObjectName("btn_zoom_out")
230 self.gridLayout_4.addWidget(self.btn_zoom_out, 0, 3, 1, 1)
231
232 self.btn_zoom_100 = QtWidgets.QPushButton(self.widget_controls)
233 self.btn_zoom_100.setObjectName("btn_zoom_100")
234 self.gridLayout_4.addWidget(self.btn_zoom_100, 1, 3, 1, 1)
235
236 self.btn_zoom_fit = QtWidgets.QPushButton(self.widget_controls)
237 self.btn_zoom_fit.setObjectName("btn_zoom_fit")
238 self.gridLayout_4.addWidget(self.btn_zoom_fit, 1, 2, 1, 1)
239
240 self.btn_single_frame = QtWidgets.QPushButton(self.widget_controls)
241 self.btn_single_frame.setObjectName("btn_single_frame")
242 self.gridLayout_4.addWidget(self.btn_single_frame, 1, 0, 1, 1)
243
244 self.btn_start_preview = QtWidgets.QPushButton(self.widget_controls)
245 self.btn_start_preview.setObjectName("btn_start_preview")
246
247 self.gridLayout_4.addWidget(self.btn_start_preview, 0, 0, 1, 1)
248
249 self.btn_start_recording = QtWidgets.QPushButton(self.widget_controls)
250 self.btn_start_recording.setObjectName("btn_start_recording")
251
252 self.gridLayout_4.addWidget(self.btn_start_recording, 0, 1, 1, 1)
253
254 self.verticalLayout_2.addWidget(self.widget_controls)
255 self.gridLayout.addWidget(self.preview_and_control, 0, 2, 1, 1)
256
257 #Definition of all the tabs on the left side of the UI
258 #--------------------------------------------------------------------
259 self.tabs = QtWidgets.QTabWidget(self.centralwidget)
260 self.tabs.setAccessibleName("")
261 self.tabs.setAccessibleDescription("")
262 self.tabs.setObjectName("tabs")
263
264 #Tab - Connect camera
265 self.tab_connect = QtWidgets.QWidget()
266 self.tab_connect.setObjectName("tab_connect")
267 self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.tab_connect)
268 self.verticalLayout_4.setObjectName("verticalLayout_4")
269 self.widget_4 = QtWidgets.QWidget(self.tab_connect)
270 self.widget_4.setObjectName("widget_4")
271 self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.widget_4)
272 self.horizontalLayout_3.setObjectName("horizontalLayout_3")
273 self.btn_connect_camera = QtWidgets.QPushButton(self.widget_4)
274 self.btn_connect_camera.setObjectName("btn_connect_camera")
275 self.horizontalLayout_3.addWidget(self.btn_connect_camera)
276 self.btn_refresh_cameras = QtWidgets.QPushButton(self.widget_4)
277 self.btn_refresh_cameras.setObjectName("btn_refresh_cameras")
278 self.horizontalLayout_3.addWidget(self.btn_refresh_cameras)
279 self.btn_disconnect_camera = QtWidgets.QPushButton(self.widget_4)
280 self.btn_disconnect_camera.setObjectName("btn_disconnect_camera")
281 self.horizontalLayout_3.addWidget(self.btn_disconnect_camera)
282 self.verticalLayout_4.addWidget(self.widget_4)
283 self.list_detected_cameras = QtWidgets.QListWidget(self.tab_connect)
284 self.list_detected_cameras.setObjectName("list_detected_cameras")
285
286
287 #Connect refresh camera to the UI
288
289 self.verticalLayout_4.addWidget(self.list_detected_cameras)
290
291 self.frame_cti = QtWidgets.QFrame(self.tab_connect)
292 self.frame_cti.setFrameShape(QtWidgets.QFrame.StyledPanel)
293 self.frame_cti.setFrameShadow(QtWidgets.QFrame.Raised)
294 self.frame_cti.setObjectName("frame_cti")
295 self.gridLayout_7 = QtWidgets.QGridLayout(self.frame_cti)
296 self.gridLayout_7.setObjectName("gridLayout_7")
297 self.btn_remove_cti = QtWidgets.QPushButton(self.frame_cti)
298 self.btn_remove_cti.setObjectName("btn_remove_cti")
299 self.gridLayout_7.addWidget(self.btn_remove_cti, 0, 3, 1, 1)
300 self.btn_add_cti = QtWidgets.QPushButton(self.frame_cti)
301 self.btn_add_cti.setObjectName("btn_add_cti")
302 self.gridLayout_7.addWidget(self.btn_add_cti, 0, 2, 1, 1)
303 self.tip_add_cti = QtWidgets.QLabel(self.frame_cti)
304 self.tip_add_cti.setWordWrap(True)
305 self.tip_add_cti.setObjectName("tip_add_cti")
306 self.gridLayout_7.addWidget(self.tip_add_cti, 0, 0, 2, 1)
307 self.combo_remove_cti = QtWidgets.QComboBox(self.frame_cti)
308 self.combo_remove_cti.setObjectName("combo_remove_cti")
309 self.gridLayout_7.addWidget(self.combo_remove_cti, 1, 2, 1, 2)
310 self.verticalLayout_4.addWidget(self.frame_cti)
311
312 self.tabs.addTab(self.tab_connect, "")
313
314 #Tab - Configure camera
315 #read present parameters on tab change and when read parameters button (To be added) is pressed
316
317
318 self.tab_config = QtWidgets.QWidget()
319 self.tab_config.setObjectName("tab_config")
320 self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.tab_config)
321 self.verticalLayout_3.setObjectName("verticalLayout_3")
322
323 self.frame_config_level = QtWidgets.QFrame(self.tab_config)
324 self.frame_config_level.setFrameShape(QtWidgets.QFrame.StyledPanel)
325 self.frame_config_level.setFrameShadow(QtWidgets.QFrame.Raised)
326 self.frame_config_level.setObjectName("frame_config_level")
327 self.horizontalLayout_5 = QtWidgets.QHBoxLayout(self.frame_config_level)
328 self.horizontalLayout_5.setObjectName("horizontalLayout_5")
329 self.label_config_level = QtWidgets.QLabel(self.frame_config_level)
330 self.label_config_level.setObjectName("label_config_level")
331 self.horizontalLayout_5.addWidget(self.label_config_level)
332 self.combo_config_level = QtWidgets.QComboBox(self.frame_config_level)
333 self.combo_config_level.setObjectName("combo_config_level")
334 self.combo_config_level.addItem("")
335 self.combo_config_level.addItem("")
336 self.combo_config_level.addItem("")
337
338 self.horizontalLayout_5.addWidget(self.combo_config_level)
339 self.verticalLayout_3.addWidget(self.frame_config_level)
340
341
342 self.tree_features = QtWidgets.QTreeWidget(self.tab_config)
343 self.tree_features.setObjectName("tree_features")
344 self.tree_features.setColumnWidth(0,250)
345 self.verticalLayout_3.addWidget(self.tree_features)
346
347
348 self.widget_3 = QtWidgets.QWidget(self.tab_config)
349 self.widget_3.setObjectName("widget_3")
350 self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.widget_3)
351 self.horizontalLayout_2.setObjectName("horizontalLayout_2")
352
353 self.btn_save_config = QtWidgets.QPushButton(self.widget_3)
354 self.btn_save_config.setObjectName("btn_save_config")
355
356 self.horizontalLayout_2.addWidget(self.btn_save_config)
357
358 self.btn_load_config = QtWidgets.QPushButton(self.widget_3)
359 self.btn_load_config.setObjectName("btn_load_config")
360 self.horizontalLayout_2.addWidget(self.btn_load_config)
361
362 self.verticalLayout_3.addWidget(self.widget_3)
363 self.tabs.addTab(self.tab_config, "")
364
365 #Tab - Configure recording
366 self.tab_recording_config = QtWidgets.QWidget()
367 self.tab_recording_config.setObjectName("tab_recording_config")
368 self.verticalLayout = QtWidgets.QVBoxLayout(self.tab_recording_config)
369 self.verticalLayout.setObjectName("verticalLayout")
370
371 self.widget_sequence_name = QtWidgets.QWidget(self.tab_recording_config)
372 self.widget_sequence_name.setObjectName("widget_sequence_name")
373
374 self.formLayout_4 = QtWidgets.QFormLayout(self.widget_sequence_name)
375 self.formLayout_4.setObjectName("formLayout_4")
376
377 self.label_file_name_recording = QtWidgets.QLabel(self.widget_sequence_name)
378 self.label_file_name_recording.setObjectName("label_file_name_recording")
379 self.formLayout_4.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.label_file_name_recording)
380
381 self.line_edit_sequence_name = QtWidgets.QLineEdit(self.widget_sequence_name)
382 self.line_edit_sequence_name.setObjectName("line_edit_sequence_name")
383 self.formLayout_4.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.line_edit_sequence_name)
384
385 self.verticalLayout.addWidget(self.widget_sequence_name)
386
387 self.label_sequence_name = QtWidgets.QLabel(self.tab_recording_config)
388 self.label_sequence_name.setObjectName("label_sequence_name")
389 self.verticalLayout.addWidget(self.label_sequence_name)
390
391 self.widget_sequence_save = QtWidgets.QWidget(self.tab_recording_config)
392 self.widget_sequence_save.setObjectName("widget_sequence_save")
393 self.formLayout_3 = QtWidgets.QFormLayout(self.widget_sequence_save)
394 self.formLayout_3.setObjectName("formLayout_3")
395
396 self.file_manager_save_location = QtWidgets.QPushButton(self.widget_sequence_save)
397 self.file_manager_save_location.setObjectName("file_manager_save_location")
398
399 self.formLayout_3.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.file_manager_save_location)
400
401 self.line_edit_save_location = QtWidgets.QLineEdit(self.widget_sequence_save)
402 self.line_edit_save_location.setObjectName("line_edit_save_location")
403 self.formLayout_3.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.line_edit_save_location)
404
405 self.verticalLayout.addWidget(self.widget_sequence_save)
406
407 self.widget_duration = QtWidgets.QWidget(self.tab_recording_config)
408 self.widget_duration.setObjectName("widget_duration")
409 self.formLayout_2 = QtWidgets.QFormLayout(self.widget_duration)
410 self.formLayout_2.setObjectName("formLayout_2")
411
412 self.label_sequence_duration = QtWidgets.QLabel(self.widget_duration)
413 self.label_sequence_duration.setObjectName("label_sequence_duration")
414 self.formLayout_2.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.label_sequence_duration)
415
416 self.line_edit_sequence_duration = QtWidgets.QLineEdit(self.widget_duration)
417 self.line_edit_sequence_duration.setObjectName("line_edit_sequence_duration")
418 #accept only numbers
419
420 self.formLayout_2.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.line_edit_sequence_duration)
421
422 self.verticalLayout.addWidget(self.widget_duration)
423
424 self.label_sequence_duration_tip = QtWidgets.QLabel(self.tab_recording_config)
425 self.label_sequence_duration_tip.setObjectName("label_sequence_duration_tip")
426 self.verticalLayout.addWidget(self.label_sequence_duration_tip)
427
428 spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
429 self.verticalLayout.addItem(spacerItem1)
430
431 self.btn_save_sequence_settings = QtWidgets.QPushButton(self.tab_recording_config)
432 self.btn_save_sequence_settings.setObjectName("btn_save_sequence_settings")
433 self.verticalLayout.addWidget(self.btn_save_sequence_settings)
434
435 self.btn_reset_sequence_settings = QtWidgets.QPushButton(self.tab_recording_config)
436 self.btn_reset_sequence_settings.setObjectName("btn_reset_sequence_settings")
437
438 self.verticalLayout.addWidget(self.btn_reset_sequence_settings)
439
440 self.tabs.addTab(self.tab_recording_config, "")
441
442 #Tab - Keras/Tensorflow/Learning,Classification
443 self.tab_tensorflow = QtWidgets.QWidget()
444 self.tab_tensorflow.setObjectName("tab_tensorflow")
445
446 self.gridLayout_3 = QtWidgets.QGridLayout(self.tab_tensorflow)
447 self.gridLayout_3.setObjectName("gridLayout_3")
448
449 self.btn_save_model = QtWidgets.QPushButton(self.tab_tensorflow)
450 self.btn_save_model.setObjectName("btn_save_model")
451
452 self.gridLayout_3.addWidget(self.btn_save_model, 0, 1, 1, 1)
453
454 self.line_edit_model_name = QtWidgets.QLineEdit(self.tab_tensorflow)
455 self.line_edit_model_name.setObjectName("line_edit_model_name")
456 self.line_edit_model_name.setEnabled(False)
457 self.gridLayout_3.addWidget(self.line_edit_model_name, 1, 0, 1, 2)
458
459 self.btn_load_model = QtWidgets.QPushButton(self.tab_tensorflow)
460 self.btn_load_model.setObjectName("btn_load_model")
461
462 self.gridLayout_3.addWidget(self.btn_load_model, 0, 0, 1, 1)
463
464 self.tensorflow_tabs = QtWidgets.QTabWidget(self.tab_tensorflow)
465 self.tensorflow_tabs.setObjectName("tensorflow_tabs")
466
467 self.tab_classify = QtWidgets.QWidget()
468 self.tab_classify.setObjectName("tab_classify")
469 self.gridLayout_5 = QtWidgets.QGridLayout(self.tab_classify)
470 self.gridLayout_5.setObjectName("gridLayout_5")
471
472 self.predictions = Prediction_graph()
473
474 self.gridLayout_5.addWidget(self.predictions, 0, 0, 1, 1)
475
476 self.tensorflow_tabs.addTab(self.tab_classify, "")
477
478 self.tab_train = QtWidgets.QWidget()
479 self.tab_train.setObjectName("tab_train")
480
481 self.gridLayout_9 = QtWidgets.QGridLayout(self.tab_train)
482 self.gridLayout_9.setObjectName("gridLayout_9")
483
484 spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
485 self.gridLayout_9.addItem(spacerItem1, 2, 0, 1, 1)
486
487 self.frame_train_stats = QtWidgets.QFrame(self.tab_train)
488 self.frame_train_stats.setFrameShape(QtWidgets.QFrame.StyledPanel)
489 self.frame_train_stats.setFrameShadow(QtWidgets.QFrame.Raised)
490 self.frame_train_stats.setObjectName("frame_train_stats")
491
492 self.gridLayout_8 = QtWidgets.QGridLayout(self.frame_train_stats)
493 self.gridLayout_8.setObjectName("gridLayout_8")
494
495 self.label_val_acc = QtWidgets.QLabel(self.frame_train_stats)
496 self.label_val_acc.setObjectName("label_val_acc")
497 self.gridLayout_8.addWidget(self.label_val_acc, 6, 3, 1, 1)
498
499 self.line_edit_acc = QtWidgets.QLineEdit(self.frame_train_stats)
500 self.line_edit_acc.setEnabled(False)
501 self.line_edit_acc.setObjectName("line_edit_acc")
502 self.gridLayout_8.addWidget(self.line_edit_acc, 6, 2, 1, 1)
503
504 self.label_acc = QtWidgets.QLabel(self.frame_train_stats)
505 self.label_acc.setObjectName("label_acc")
506 self.gridLayout_8.addWidget(self.label_acc, 6, 0, 1, 1)
507
508 self.label_val_loss = QtWidgets.QLabel(self.frame_train_stats)
509 self.label_val_loss.setObjectName("label_val_loss")
510 self.gridLayout_8.addWidget(self.label_val_loss, 2, 3, 1, 1)
511
512 self.line_edit_val_acc = QtWidgets.QLineEdit(self.frame_train_stats)
513 self.line_edit_val_acc.setEnabled(False)
514 self.line_edit_val_acc.setObjectName("line_edit_val_acc")
515 self.gridLayout_8.addWidget(self.line_edit_val_acc, 6, 4, 1, 1)
516
517 self.line_edit_val_loss = QtWidgets.QLineEdit(self.frame_train_stats)
518 self.line_edit_val_loss.setEnabled(False)
519 self.line_edit_val_loss.setObjectName("line_edit_val_loss")
520 self.gridLayout_8.addWidget(self.line_edit_val_loss, 2, 4, 1, 1)
521
522 self.label_epoch = QtWidgets.QLabel(self.frame_train_stats)
523 self.label_epoch.setObjectName("label_epoch")
524 self.gridLayout_8.addWidget(self.label_epoch, 1, 0, 1, 1)
525
526 self.label_active_epoch = QtWidgets.QLabel(self.frame_train_stats)
527 self.label_active_epoch.setObjectName("label_active_epoch")
528 self.gridLayout_8.addWidget(self.label_active_epoch, 1, 2, 1, 1)
529
530 self.line_edit_loss = QtWidgets.QLineEdit(self.frame_train_stats)
531 self.line_edit_loss.setEnabled(False)
532 self.line_edit_loss.setObjectName("line_edit_loss")
533 self.gridLayout_8.addWidget(self.line_edit_loss, 2, 2, 1, 1)
534
535 self.label_loss = QtWidgets.QLabel(self.frame_train_stats)
536 self.label_loss.setObjectName("label_loss")
537 self.gridLayout_8.addWidget(self.label_loss, 2, 0, 1, 1)
538
539 self.btn_train_cancel = QtWidgets.QPushButton(self.frame_train_stats)
540 self.btn_train_cancel.setObjectName("btn_train_cancel")
541 self.gridLayout_8.addWidget(self.btn_train_cancel, 0, 0, 1, 1)
542
543 self.progress_bar_train = QtWidgets.QProgressBar(self.frame_train_stats)
544 self.progress_bar_train.setProperty("value", 0)
545 self.progress_bar_train.setObjectName("progress_bar_train")
546 self.gridLayout_8.addWidget(self.progress_bar_train, 0, 2, 1, 3)
547
548 self.gridLayout_9.addWidget(self.frame_train_stats, 3, 0, 1, 1)
549
550 self.frame_train_preprocess = QtWidgets.QFrame(self.tab_train)
551 self.frame_train_preprocess.setFrameShape(QtWidgets.QFrame.StyledPanel)
552 self.frame_train_preprocess.setFrameShadow(QtWidgets.QFrame.Raised)
553 self.frame_train_preprocess.setObjectName("frame_train_preprocess")
554
555 self.gridLayout_6 = QtWidgets.QGridLayout(self.frame_train_preprocess)
556 self.gridLayout_6.setObjectName("gridLayout_6")
557 self.label_img_resize = QtWidgets.QLabel(self.frame_train_preprocess)
558 self.label_img_resize.setObjectName("label_img_resize")
559 self.gridLayout_6.addWidget(self.label_img_resize, 1, 0, 1, 1)
560
561 self.btn_load_dataset = QtWidgets.QPushButton(self.frame_train_preprocess)
562 self.btn_load_dataset.setObjectName("btn_load_dataset")
563 self.gridLayout_6.addWidget(self.btn_load_dataset, 0, 0, 1, 1)
564
565 self.label_val_split = QtWidgets.QLabel(self.frame_train_preprocess)
566 self.label_val_split.setObjectName("label_val_split")
567 self.gridLayout_6.addWidget(self.label_val_split, 4, 0, 1, 1)
568
569 self.spin_box_val_split = QtWidgets.QDoubleSpinBox(self.frame_train_preprocess)
570 self.spin_box_val_split.setMaximum(100.0)
571 self.spin_box_val_split.setProperty("value", 20.0)
572 self.spin_box_val_split.setObjectName("spin_box_val_split")
573 self.gridLayout_6.addWidget(self.spin_box_val_split, 4, 1, 1, 1)
574
575 self.spin_box_epochs = QtWidgets.QSpinBox(self.frame_train_preprocess)
576 self.spin_box_epochs.setMaximum(1024)
577 self.spin_box_epochs.setProperty("value", 5)
578 self.spin_box_epochs.setObjectName("spin_box_epochs")
579 self.gridLayout_6.addWidget(self.spin_box_epochs, 5, 1, 1, 1)
580
581 self.label_train_epochs = QtWidgets.QLabel(self.frame_train_preprocess)
582 self.label_train_epochs.setObjectName("label_train_epochs")
583 self.gridLayout_6.addWidget(self.label_train_epochs, 5, 0, 1, 1)
584
585 self.btn_preprocess = QtWidgets.QPushButton(self.frame_train_preprocess)
586 self.btn_preprocess.setObjectName("btn_preprocess")
587 self.gridLayout_6.addWidget(self.btn_preprocess, 6, 0, 1, 1)
588
589 self.progress_bar_preprocess = QtWidgets.QProgressBar(self.frame_train_preprocess)
590 self.progress_bar_preprocess.setProperty("value", 0)
591 self.progress_bar_preprocess.setObjectName("progress_bar_preprocess")
592 self.gridLayout_6.addWidget(self.progress_bar_preprocess, 6, 1, 1, 2)
593
594 self.label_res_width = QtWidgets.QLabel(self.frame_train_preprocess)
595 self.label_res_width.setObjectName("label_res_width")
596 self.gridLayout_6.addWidget(self.label_res_width, 2, 0, 1, 1, QtCore.Qt.AlignRight)
597
598 self.label_res_height = QtWidgets.QLabel(self.frame_train_preprocess)
599 self.label_res_height.setObjectName("label_res_height")
600 self.gridLayout_6.addWidget(self.label_res_height, 3, 0, 1, 1, QtCore.Qt.AlignRight)
601
602 self.line_edit_res_width = QtWidgets.QLineEdit(self.frame_train_preprocess)
603 self.line_edit_res_width.setEnabled(False)
604 self.line_edit_res_width.setInputMethodHints(QtCore.Qt.ImhDigitsOnly)
605 self.line_edit_res_width.setObjectName("line_edit_res_width")
606 self.gridLayout_6.addWidget(self.line_edit_res_width, 2, 1, 1, 1)
607
608 self.line_edit_res_height = QtWidgets.QLineEdit(self.frame_train_preprocess)
609 self.line_edit_res_height.setEnabled(False)
610 self.line_edit_res_height.setInputMethodHints(QtCore.Qt.ImhDigitsOnly)
611 self.line_edit_res_height.setObjectName("line_edit_res_height")
612 self.gridLayout_6.addWidget(self.line_edit_res_height, 3, 1, 1, 1)
613
614 spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
615 self.gridLayout_6.addItem(spacerItem2, 2, 2, 1, 1)
616 self.line_edit_dataset_path = QtWidgets.QLineEdit(self.frame_train_preprocess)
617 self.line_edit_dataset_path.setObjectName("line_edit_dataset_path")
618 self.gridLayout_6.addWidget(self.line_edit_dataset_path, 0, 1, 1, 2)
619
620 self.gridLayout_9.addWidget(self.frame_train_preprocess, 1, 0, 1, 1)
621 self.tensorflow_tabs.addTab(self.tab_train, "")
622
623 self.gridLayout_3.addWidget(self.tensorflow_tabs, 2, 0, 1, 2)
624 self.tabs.addTab(self.tab_tensorflow, "")
625
626
627 self.gridLayout.addWidget(self.tabs, 0, 0, 2, 1)
628 #methods to call on tab change
629 self.tabs.currentChanged.connect(self.tab_changed)
630 #Menubar buttons
631 #-------------------------------------------------------------------
632 MainWindow.setCentralWidget(self.centralwidget)
633
634 self.menubar = QtWidgets.QMenuBar(MainWindow)
635 self.menubar.setGeometry(QtCore.QRect(0, 0, 1208, 26))
636 self.menubar.setObjectName("menubar")
637 self.menuFile = QtWidgets.QMenu(self.menubar)
638 self.menuFile.setObjectName("menuFile")
639 self.menuHelp = QtWidgets.QMenu(self.menubar)
640 self.menuHelp.setObjectName("menuHelp")
641 MainWindow.setMenuBar(self.menubar)
642
643 #Define statusbar
644 #------------------------------------------------
645 self.statusbar = QtWidgets.QStatusBar(MainWindow)
646 self.statusbar.setObjectName("statusbar")
647
648 #added manually
649 self.status_label = QtWidgets.QLabel()
650 self.status_label.setObjectName("status_label")
651 self.statusbar.addWidget(self.status_label,stretch=40)
652
653 self.camera_icon = QtWidgets.QLabel()
654 self.camera_icon.setObjectName("camera_icon")
655 self.camera_icon.setScaledContents(True)
656 self.statusbar.addPermanentWidget(self.camera_icon)
657
658 self.camera_status = QtWidgets.QLabel()
659 self.camera_status.setObjectName("camera_status")
660 self.statusbar.addPermanentWidget(self.camera_status,stretch=30)
661
662 self.fps_status = QtWidgets.QLabel()
663 self.fps_status.setObjectName("fps_status")
664 self.statusbar.addPermanentWidget(self.fps_status,stretch=10)
665
666 self.receive_status = QtWidgets.QLabel()
667 self.receive_status.setObjectName("receive_status")
668 self.statusbar.addPermanentWidget(self.receive_status,stretch=20)
669
670 MainWindow.setStatusBar(self.statusbar)
671
672 #Adding individual items to menus in menubar
673 #-------------------------------------------------------------
674 self.actionAdd_Remove_cti_file = QtWidgets.QAction(MainWindow)
675 self.actionAdd_Remove_cti_file.setObjectName("actionAdd_Remove_cti_file")
676
677 self.actionOpen_Help = QtWidgets.QAction(MainWindow)
678 self.actionOpen_Help.setObjectName("actionOpen_Help")
679
680 self.actionRemove_cti_file = QtWidgets.QAction(MainWindow)
681 self.actionRemove_cti_file.setObjectName("actionRemove_cti_file")
682
683 self.action_save_frame = QtWidgets.QAction(MainWindow)
684 self.action_save_frame.setObjectName("action_save_frame")
685
686 self.action_save_settings = QtWidgets.QAction(MainWindow)
687 self.action_save_settings.setObjectName("action_save_settings")
688
689 self.actionAbout_Anubis = QtWidgets.QAction(MainWindow)
690 self.actionAbout_Anubis.setObjectName("actionAbout_Anubis")
691
692 self.actionGit_Repository = QtWidgets.QAction(MainWindow)
693 self.actionGit_Repository.setObjectName("actionGit_Repository")
694
695 self.actionSave_camera_config = QtWidgets.QAction(MainWindow)
696 self.actionSave_camera_config.setObjectName("actionSave_camera_config")
697
698 self.actionLoad_camera_config = QtWidgets.QAction(MainWindow)
699 self.actionLoad_camera_config.setObjectName("actionLoad_camera_config")
700
701 self.menuFile.addAction(self.actionSave_camera_config)
702 self.menuFile.addAction(self.actionLoad_camera_config)
703 self.menuFile.addAction(self.actionAdd_Remove_cti_file)
704 self.menuFile.addAction(self.actionRemove_cti_file)
705
706 self.menuFile.addSeparator()
707
708 self.menuFile.addAction(self.action_save_settings)
709 self.menuHelp.addAction(self.actionOpen_Help)
710
711 self.menuHelp.addSeparator()
712
713 self.menuHelp.addAction(self.actionAbout_Anubis)
714 self.menuHelp.addAction(self.actionGit_Repository)
715
716 self.menubar.addAction(self.menuFile.menuAction())
717 self.menubar.addAction(self.menuHelp.menuAction())
718 #----------------------------------------------------------------
719
720 #--------------------------------------------------------------
721
722 self.setup_validators()
723 self.connect_actions()
724 self.retranslateUi(MainWindow)
725 self.read_config()
726 self.tabs.setCurrentIndex(0)
727 QtCore.QMetaObject.connectSlotsByName(MainWindow)
728
729
730 self.vision = Computer_vision(self.predictions)
731
732 def retranslateUi(self, MainWindow):
733 """!@brief Sets names of widgets.
734 @details Widgets are created in setupUi method, this method sets text
735 of the buttons, tabs and default texts for all of these widgets.
736 """
737 _translate = QtCore.QCoreApplication.translate
738 MainWindow.setWindowTitle(_translate("MainWindow", "Anubis"))
739 self.btn_zoom_100.setText(_translate("MainWindow", "Zoom to 100%"))
740 self.btn_zoom_fit.setText(_translate("MainWindow", "Fit to window"))
741 self.btn_start_recording.setText(_translate("MainWindow", "Start/Stop recording"))
742 self.btn_start_preview.setText(_translate("MainWindow", "Start/Stop preview"))
743 self.btn_single_frame.setText(_translate("MainWindow", "Single frame"))
744 self.btn_zoom_in.setText(_translate("MainWindow", "Zoom In"))
745 self.btn_zoom_out.setText(_translate("MainWindow", "Zoom Out"))
746 self.btn_connect_camera.setText(_translate("MainWindow", "Connect"))
747 self.btn_refresh_cameras.setText(_translate("MainWindow", "Refresh"))
748 self.btn_disconnect_camera.setText(_translate("MainWindow", "Disconnect"))
749 self.tip_add_cti.setText(_translate("MainWindow", "Tip: If you can\'t detect your camera try adding new .cti file from your camera vendor"))
750 self.tabs.setTabText(self.tabs.indexOf(self.tab_connect), _translate("MainWindow", "Connect Camera"))
751 self.btn_add_cti.setText(_translate("MainWindow", "Add a new .cti file"))
752 self.btn_remove_cti.setText(_translate("MainWindow", "Remove selected .cti"))
753 self.label_config_level.setText(_translate("MainWindow", "Configuration level"))
754 self.combo_config_level.setItemText(0, _translate("MainWindow", "Beginner"))
755 self.combo_config_level.setItemText(1, _translate("MainWindow", "Expert"))
756 self.combo_config_level.setItemText(2, _translate("MainWindow", "Guru"))
757 self.tree_features.headerItem().setText(0, _translate("MainWindow", "Feature"))
758 self.tree_features.headerItem().setText(1, _translate("MainWindow", "Value"))
759 self.btn_save_config.setText(_translate("MainWindow", "Save Configuration"))
760 self.btn_load_config.setText(_translate("MainWindow", "Load Configuration"))
761 self.tabs.setTabText(self.tabs.indexOf(self.tab_config), _translate("MainWindow", "Configure Camera"))
762 self.label_file_name_recording.setText(_translate("MainWindow", "File name"))
763 self.label_sequence_name.setText(_translate("MainWindow", "Tip: Use %n for sequence number, %d for date and %t for time stamp "))
764 self.file_manager_save_location.setText(_translate("MainWindow", "Save Location"))
765 self.label_sequence_duration.setText(_translate("MainWindow", "Sequence duration [s]"))
766 self.label_sequence_duration_tip.setText(_translate("MainWindow", "Tip: Leave empty for manual control using Start/Stop recording buttons"))
767 self.btn_save_sequence_settings.setText(_translate("MainWindow", "Save settings"))
768 self.btn_reset_sequence_settings.setText(_translate("MainWindow", "Default settings"))
769 self.tabs.setTabText(self.tabs.indexOf(self.tab_recording_config), _translate("MainWindow", "Configure Recording"))
770 self.tabs.setTabText(self.tabs.indexOf(self.tab_tensorflow), _translate("MainWindow", "Tensorflow"))
771 self.btn_save_model.setText(_translate("MainWindow", "Save model"))
772 self.line_edit_model_name.setText(_translate("MainWindow", "Select a model to load"))
773 self.btn_load_model.setText(_translate("MainWindow", "Load model"))
774 self.tensorflow_tabs.setTabText(self.tensorflow_tabs.indexOf(self.tab_classify), _translate("MainWindow", "Classify"))
775 self.tensorflow_tabs.setTabText(self.tensorflow_tabs.indexOf(self.tab_classify), _translate("MainWindow", "Classify"))
776 self.label_val_acc.setText(_translate("MainWindow", "Validation Accuracy"))
777 self.label_acc.setText(_translate("MainWindow", "Accuracy"))
778 self.label_val_loss.setText(_translate("MainWindow", "Validation Loss"))
779 self.label_epoch.setText(_translate("MainWindow", "Epoch: "))
780 self.label_active_epoch.setText(_translate("MainWindow", "0/0"))
781 self.label_loss.setText(_translate("MainWindow", "Loss"))
782 self.btn_train_cancel.setText(_translate("MainWindow", "Train"))
783 self.label_img_resize.setText(_translate("MainWindow", "Resize dimensions"))
784 self.btn_load_dataset.setText(_translate("MainWindow", "Select Dataset"))
785 self.label_val_split.setText(_translate("MainWindow", "Data for a validation [%]"))
786 self.label_train_epochs.setText(_translate("MainWindow", "Train epochs"))
787 self.btn_preprocess.setText(_translate("MainWindow", "Load Data"))
788 self.label_res_width.setText(_translate("MainWindow", "Width"))
789 self.label_res_height.setText(_translate("MainWindow", "Height"))
790 self.tensorflow_tabs.setTabText(self.tensorflow_tabs.indexOf(self.tab_train), _translate("MainWindow", "Train"))
791 self.tabs.setTabText(self.tabs.indexOf(self.tab_tensorflow), _translate("MainWindow", "Tensorflow"))
792 self.menuFile.setTitle(_translate("MainWindow", "File"))
793 self.menuHelp.setTitle(_translate("MainWindow", "Help"))
794 self.actionAdd_Remove_cti_file.setText(_translate("MainWindow", "Add .cti file"))
795 self.actionOpen_Help.setText(_translate("MainWindow", "Open Help"))
796 self.actionRemove_cti_file.setText(_translate("MainWindow", "Remove .cti file"))
797 self.action_save_frame.setText(_translate("MainWindow", "Save frame"))
798 self.action_save_settings.setText(_translate("MainWindow", "Save app state"))
799 self.action_save_settings.setToolTip(_translate("MainWindow", "Save modifications made to application settings"))
800 self.actionAbout_Anubis.setText(_translate("MainWindow", "About Anubis"))
801 self.actionGit_Repository.setText(_translate("MainWindow", "Git Repository"))
802 self.actionSave_camera_config.setText(_translate("MainWindow", "Save camera config"))
803 self.actionLoad_camera_config.setText(_translate("MainWindow", "Load camera config"))
804
805 #added manually
806 self.camera_status.setText("Camera: Not connected")
807 self.receive_status.setText("Received frames: 0")
808 self.fps_status.setText("FPS: 0")
809 self.camera_icon.setPixmap(self.icon_offline)
810
811 #Start of custom methods (not generated by QtDesigner)
812 def connect_actions(self):
813 """!@brief Connect method calls to appropriate widgets
814 @details All static widgets are connected to some method either in this
815 class or call method of another object. In this method all such bindings
816 done excluding dynamically created widgets like camera's features
817 """
818
819 self.btn_zoom_out.clicked.connect(lambda: self.set_zoom(-1))
820 self.btn_zoom_fit.clicked.connect(lambda: self.set_zoom(0))
821 self.btn_zoom_in.clicked.connect(lambda: self.set_zoom(1))
822 self.btn_zoom_100.clicked.connect(lambda: self.set_zoom(100))
823 self.btn_single_frame.clicked.connect(self.single_frame)
824 self.btn_start_preview.clicked.connect(self.preview)
825 self.btn_start_recording.clicked.connect(self.record)
826 self.btn_refresh_cameras.clicked.connect(self.refresh_cameras)
827 self.btn_add_cti.clicked.connect(self.add_cti)
828 self.btn_remove_cti.clicked.connect(self.remove_cti)
829
830 self.btn_connect_camera.clicked.connect(
831 lambda: self.connect_camera(self.list_detected_cameras.currentRow()))
832
833 self.list_detected_cameras.itemDoubleClicked.connect(
834 lambda: self.connect_camera(self.list_detected_cameras.currentRow()))
835 #možná lambda s indexem itemu
836
837 self.btn_disconnect_camera.clicked.connect(self.disconnect_camera)
838 self.combo_config_level.currentIndexChanged.connect(self.load_parameters)
839 self.btn_save_config.clicked.connect(self.save_cam_config)
840 self.btn_load_config.clicked.connect(self.load_cam_config)
841 self.file_manager_save_location.clicked.connect(lambda: self.get_directory(self.line_edit_save_location))
842
843
844
845 self.btn_save_sequence_settings.clicked.connect(self.save_seq_settings)
846 self.btn_reset_sequence_settings.clicked.connect(self.reset_seq_settings)
847 self.btn_save_model.clicked.connect(self.save_model)
848 self.btn_load_model.clicked.connect(self.load_model)
849 self.btn_load_dataset.clicked.connect(self.choose_dataset)
850 self.btn_preprocess.clicked.connect(self.preprocess_dataset)
851 self.btn_train_cancel.clicked.connect(self.train_model)
852
853 self.action_save_settings.triggered.connect(self.save_cti_config)
854 self.actionRemove_cti_file.triggered.connect(self.remove_cti)
855 self.actionAdd_Remove_cti_file.triggered.connect(self.add_cti)
856 self.actionSave_camera_config.triggered.connect(self.save_cam_config)
857 self.actionLoad_camera_config.triggered.connect(self.load_cam_config)
858 self.actionOpen_Help.triggered.connect(lambda:
859 webbrowser.open(
860 os.path.dirname(os.path.realpath(__file__)) +
861 "/Help//index.html",
862 new=2))
863 self.actionGit_Repository.triggered.connect(lambda:
864 webbrowser.open("https://github.com/xlukas10/anubis",new=2))
865 self.actionAbout_Anubis.triggered.connect(self.about)
866
867 def setup_validators(self):
868 """!@brief create input constrains for various widgets
869 @details if a text widget needs certain input type, the validators are
870 set up here. For example setting prohibited characters of the file saved.
871 """
872 self.line_edit_sequence_duration.setValidator(QtGui.QDoubleValidator(0,16777216,5))
873 expression = QtCore.QRegExp("^[^\\\\/:*?\"<>|]*$")
874 self.line_edit_sequence_name.setValidator(QtGui.QRegExpValidator(expression))
875
876 def eventFilter(self, obj, event):
877 """!@brief Implements dragging inside preview area
878 @details whin user cliks and drags inside of a preview area, this
879 method is called and do the scrolling based on the distance dragged in
880 each direction.
881 """
882 if (obj == self.preview_area):
883 if(event.type() == QtCore.QEvent.MouseMove ):
884
885 if self.move_x_prev == 0:
886 self.move_x_prev = event.pos().x()
887 if self.move_y_prev == 0:
888 self.move_y_prev = event.pos().y()
889
890 dist_x = self.move_x_prev - event.pos().x()
891 dist_y = self.move_y_prev - event.pos().y()
892 self.preview_area.verticalScrollBar().setValue(
893 self.preview_area.verticalScrollBar().value() + dist_y)
894 self.preview_area.horizontalScrollBar().setValue(
895 self.preview_area.horizontalScrollBar().value() + dist_x)
896 #self.preview_area.scrollContentsBy(dist_x,dist_y)
897 self.move_x_prev = event.pos().x()
898 self.move_y_prev = event.pos().y()
899
900 elif event.type() == QtCore.QEvent.MouseButtonRelease:
901 self.last_time_move = 0
902 return QtWidgets.QWidget.eventFilter(self, obj, event)
903
904 #-----------Common methods--------------------
905 def tab_changed(self):
906 """!@brief Called when tab changes
907 @details Used to do actions when entering specific tab.
908 """
909 index = self.tabs.currentIndex()
910
911 if index == 0:
912 pass
913 if index == 1:#Camera configuration tab
914 #Request parameters from camera and show them in gui
915 self.load_parameters()
916
917 def set_status_msg(self, message, timeout=0):
918 """!@brief Shows message in status bar
919 @details Method is called when other methods need to send the user
920 some confrimation or status update.
921 @param[in] message Contains text to be displayed in the status bar
922 @param[in] timeout For how long should the message be displayed [ms]. Defaults to infinity.
923 """
924 self.status_timer.stop()
925 self.status_label.setText(message)
926 #When time out is reached, connected method
927 #(self.clear_status) is called.
928 if(timeout > 0):
929 self.status_timer.start(timeout)
930
931 def clear_status(self):
932 """!@brief Empties self.status_label in self.statusbar.
933 @details Method is called after active message times out.
934 """
935 self.status_label.setText("")
936
937 def get_directory(self, line_output = None):
938 #set_record_path
939 """!@brief Opens file dialog for user to set path to save frames.
940 @details Method is called by Save Location button. Path is written to
941 the label next to the button and can be further modified.
942 """
943 #Open file dialog for choosing a folder
944 name = QtWidgets.QFileDialog.getExistingDirectory(self.centralwidget,
945 "Select Folder",
946 )
947
948 #Set label text to chosen folder path
949 if(line_output):
950 line_output.setText(name)
951 return name
952
953 def read_config(self):
954 """!@brief Loads configuration from config.ini file
955 @details This method is called on startup and loads all modifications
956 user made to applications default state.
957 """
958
959 cti_files = False
960 loaded_cti = None
961
962 with open("config.ini", 'r') as config:
963 for line in config:
964 #reading configuration for recording
965 line = line.rstrip('\n')
966 if(line.startswith("filename=")):
967 self.line_edit_sequence_name.setText(line.replace("filename=", "", 1))
968 elif(line.startswith("save_location=")):
969 self.line_edit_save_location.setText(line.replace("save_location=", "", 1))
970 elif(line.startswith("sequence_duration=")):
971 self.line_edit_sequence_duration.setText(line.replace("sequence_duration=", "", 1))
972 elif(line.startswith("CTI_FILES_PATHS")):
973 cti_files = True
974 elif(cti_files == True):
975 loaded_cti = cam.add_gentl_producer(line)
976
977 #if no cti path is present in the config adding files will be skipped
978 try:
979 self.combo_remove_cti.addItems(loaded_cti)
980 except:
981 pass
982
983 #Set status update
984 self.set_status_msg("Configuration loaded",1500)
985
986 def save_cti_config(self):
987 """!@brief Saves all currently loaded GenTL producers to the config
988 file.
989 @details When the program starts, the saved producers are loaded
990 from the config file. Save method overwrites any previous configuration.
991 """
992 paths = cam.get_gentl_producers()
993 config = []
994
995
996 with open("config.ini", 'r') as file:
997 for line in file:
998 config.append(line)
999
1000 with open("config.ini", 'w') as file:
1001 for line in config:
1002 #reading configuration for recording
1003 if(line.startswith("CTI_FILES_PATHS")):
1004 file.write(line)
1005 break
1006 else:
1007 file.write(line)
1008
1009 if isinstance(paths, str):
1010 file.write(paths + '\n')
1011 else:
1012 if(paths):
1013 for path in paths:
1014 file.write(path + '\n')
1015
1016 self.set_status_msg("Configuration saved")
1017
1018 def about(self):
1019 """!@brief Shows simple about dialog
1020 @details About dialog contains informations about version, author etc.
1021 """
1022 QtWidgets.QMessageBox.about(self.centralwidget, "About",
1023 "<p>Author: Jakub Lukaszczyk</p>" +
1024 "<p>Version: 1.0</p>" +
1025 "<p>Original release: 2021</p>" +
1026 "<p>Gui created using Qt</p>")
1027
1028 #-------------Connect camera tab--------------------
1029 def add_cti(self):
1030 """!@brief Used to load a new GenTL producer file.
1031 @details User can select a new file using file dialog.
1032 """
1033 path = QtWidgets.QFileDialog.getOpenFileName(self.centralwidget,
1034 "Load GenTL producer",
1035 filter="CTI files (*.cti)")
1036
1037 #If user changes his/her mind and closes the file dialog, don't
1038 #add empty producer
1039 if(path[0]):
1040 cti_files = cam.add_gentl_producer(path[0])
1041 try:
1042 self.combo_remove_cti.clear()
1043 self.combo_remove_cti.addItems(cti_files)
1044 except:
1045 pass
1046
1047 self.set_status_msg("File added")
1048
1049 def remove_cti(self):
1050 """!@brief Used to remove selected GenTL producer file.
1051 @details User can select file from combo box.
1052 """
1053
1054 cti_files, removed = cam.remove_gentl_producer(self.combo_remove_cti.currentText())
1055 if(removed):
1056 self.set_status_msg("File removed")
1057 self.combo_remove_cti.clear()
1058 self.combo_remove_cti.addItems(cti_files)
1059
1060 def refresh_cameras(self):
1061 """!@brief Calls function to detect connected cameras and prints them
1062 as items in a list.
1063 @details If no cameras are present nothing will happen. If cameras are
1064 detected, all previous item are cleared and cameras detected in this call
1065 are printed.
1066 """
1067 #set status message
1068 self.set_status_msg("Searching for cameras", 1500)
1069
1070 #clear the list so the cameras won't appear twice or more
1071 self.list_detected_cameras.clear()
1072
1073 #Get a list of cameras and inser each one to the interface as an
1074 #entry in the list.
1075 self.detected = cam.get_camera_list()
1076 for device in self.detected:
1077 output = device['model']
1078 #in the future maybe add icon based on interface type
1079 self.list_detected_cameras.addItem(output)
1080
1081 def connect_camera(self, index):
1082 """!@brief Connect to selected camera
1083 @details This method is called either by double clicking camera in a
1084 list or by pressing connect button
1085 @param[in] index index of selected camera in the list
1086 """
1087 #Something must be selected
1088 if index != -1:
1089
1090 #If some camera is connected, disconnect it first
1091 if self.connected:
1092 self.disconnect_camera()
1093
1094 #set green background to the selected camera
1095 self.list_detected_cameras.item(index).setBackground(QtGui.QColor('#70BF4E'))
1096
1097 #Print status message
1098 self.set_status_msg("Connecting camera")
1099
1100 #Connect camera
1101 cam.select_camera(self.detected[index]['id_'])
1102
1103
1104 self.set_status_msg("Camera connected")
1105
1106 #Set up the status bar
1107 self.camera_icon.setPixmap(self.icon_standby)
1108 self.camera_status.setText("Camera: "+self.detected[index]['model'])
1109 self.connected = True
1110
1111 def disconnect_camera(self):
1112 """!@brief Disconnect current camera
1113 @details Method disconnects camera and sets all statusbar items to
1114 their default state.
1115 """
1116 #Disconnect only if already connected
1117 if self.connected:
1118 #Get default states
1119 self.connected = False
1120 self.received = 0
1121 self.fps = 0.0
1122 self.camera_icon.setPixmap(self.icon_offline)
1123 self.camera_status.setText("Camera: Not connected")
1124
1125 self.receive_status.setText("Received frames: " + str(self.received))
1126 self.fps_status.setText("FPS: " + str(self.fps))
1127 self.set_status_msg("Disconnecting camera")
1128
1129 self.preview_live = False
1130 self.recording = False
1131 #Disconnect camera
1132 cam.disconnect_camera()
1133
1134
1135 self.set_status_msg("Camera disconnected")
1136
1137 #Imidiately search for new cameras
1138 self.refresh_cameras()
1139
1140 #-------------Camera control buttons and image-----------------
1141 def record(self):
1142 """!@brief Starts and stops recording
1143 @details Is called by start/stop button. Recording is always started
1144 manually. Recording ends with another button click or after time set
1145 in self.line_edit_sequence_duration passes. Save location and name is
1146 determined by the text in self.line_edit_save_location and
1147 self.line_edit_sequence_name.
1148 """
1149 if self.connected:
1150 if(not self.recording):
1151 #Change status icon and print status message
1152 self.camera_icon.setPixmap(self.icon_busy)
1153 self.set_status_msg("Starting recording")
1154
1155
1156 self.recording = True
1157
1158 #Start new recording with defined name and save path
1159 cam.start_recording(self.line_edit_save_location.text(),
1160 self.line_edit_sequence_name.text(),
1161 'nothing')
1162
1163
1164 #If automatic sequence duration is set, create thread that will
1165 #automatically terminate the recording
1166 if(float(self.line_edit_sequence_duration.text()) > 0):
1167 self.interupt_flag.clear()
1168 self.seq_duration_thread = threading.Thread(target=self.seq_duration_wait)
1169 self.seq_duration_thread.start()
1170
1171 #Start live preview in a new thread
1172 self.show_preview_thread = threading.Thread(target=self.show_preview)
1173 self.show_preview_thread.start()
1174 self.set_status_msg("Recording",0)
1175 else:
1176 #Set status message and standby icon
1177 self.camera_icon.setPixmap(self.icon_standby)
1178 self.set_status_msg("Stopping recording")
1179
1180 #Tell automatic sequence duration thread to end
1181 self.interupt_flag.set()
1182
1183 #End recording
1184 cam.stop_recording()
1185 self.recording = False
1186 self.preview_live = False
1187 self.set_status_msg("Recording stopped", 3500)
1188
1189 def seq_duration_wait(self):
1190 """!@brief Automatic recording interrupt.
1191 @details Let camera record for defined time and if the recording is not
1192 manually terminated stop the recording.
1193 """
1194 #wait for the first frame to be received
1195 while active_frame_queue.empty():
1196 time.sleep(0.001)
1197
1198 #print status message
1199 self.set_status_msg("Recording for "+self.line_edit_sequence_duration.text()+"s started")
1200
1201 #wait either for manual recording stop or wait for defined time
1202 self.interupt_flag.wait(float(self.line_edit_sequence_duration.text()))
1203
1204 #If the recording is still running (not terminated manually), stop
1205 #the recording.
1206 if(self.recording):
1207 self.record()
1208
1209 def preview(self):
1210 """!@brief Starts live preview
1211 @details Unlike recording method, this method does not save frames to a
1212 drive. Preview picture is rendered in separate thread.
1213 """
1214 #continue only if camera is connected
1215 if self.connected:
1216 if(not self.preview_live):
1217 #Set status message and icon
1218 self.camera_icon.setPixmap(self.icon_busy)
1219 self.set_status_msg("Starting preview",1500)
1220
1221
1222 self.preview_live = True
1223
1224 #Start camera frame acquisition (not recording)
1225 cam.start_acquisition()
1226
1227
1228 #Create and run thread to draw frames to gui
1229 self.show_preview_thread = threading.Thread(target=self.show_preview)
1230 self.show_preview_thread.start()
1231 else:
1232 #Reset status icon and print message
1233 self.camera_icon.setPixmap(self.icon_standby)
1234 self.set_status_msg("Stopping preview",1500)
1235
1236 #Stop receiving frames
1237 cam.stop_acquisition()
1238
1239 self.preview_live = False
1240
1241 def set_zoom(self, flag):
1242 """!@brief Set the zoom amount of the image previewed
1243 @details This method only sets the zooming variable, actual resizing
1244 is done in other methods.
1245 @param[in] flag Is used to define type of zoom.
1246 1 - zoom in
1247 -1 - zoom out
1248 0 - zoom fit
1249 100- zoom reset
1250 """
1251 #flag 1 zoom in, -1 zoom out, 0 zoom fit, 100 zoom reset
1252 if(flag == -1 and self.preview_zoom > 0.1):
1253 self.preview_fit = False
1254 self.preview_zoom -= 0.1
1255 elif(flag == 1):
1256 self.preview_fit = False
1257 self.preview_zoom += 0.1
1258 elif(flag == 0):
1259 self.preview_fit = True
1260 elif(flag == 100):
1261 self.preview_fit = False
1262 self.preview_zoom = 1
1263
1264 def single_frame(self):
1265 """!@brief Acquire and draw a single frame.
1266 @details Unlike the live preview, this method runs in the main thread
1267 and therefore can modify frontend variables. The method may block whole
1268 application but its execution should be fast enough to not make a
1269 difference.
1270 """
1271 #Method runs only if camera is connected
1272 if self.connected and not(self.preview_live or self.recording):
1273 #Set status icon and message
1274 self.set_status_msg("Receiving single frame",1500)
1275 self.camera_icon.setPixmap(self.icon_busy)
1276
1277 #Get image
1278 image, pixel_format = cam.get_single_frame()
1279
1280 #Try to run prediction
1281 self.predict(image)
1282
1283 #Set up a new value of received frames in the statusbar
1284 self.received = self.received + 1
1285 self.receive_status.setText("Received frames: " + str(self.received))
1286
1287 #Convert image to proper format fo PyQt
1288 h, w, ch = image.shape
1289 bytes_per_line = ch * w
1290 image = QtGui.QImage(image.data, w, h, bytes_per_line, self._get_QImage_format(pixel_format))
1291
1292
1293 #get size of preview window
1294 w_preview = self.preview_area.size().width()
1295 h_preview = self.preview_area.size().height()
1296
1297 image_scaled = image.scaled(w_preview,
1298 h_preview,
1299 QtCore.Qt.KeepAspectRatio)
1300
1301 #Set image to gui
1302 self.camera_preview.resize(w_preview,
1303 h_preview)
1304 self.camera_preview.setPixmap(QtGui.QPixmap.fromImage(image_scaled))
1305 self.camera_preview.show()
1306
1307 #Reset status icon
1308 self.camera_icon.setPixmap(self.icon_standby)
1309
1310 def show_preview(self):
1311 """!@brief Draws image from camera in real time.
1312 @details Acquires images from camera and draws them in real time at
1313 the same rate as is display refresh_rate. If the frames come too fast,
1314 only one at the most recent one is drawn and the rest is dumped. During
1315 this method an attempt to classify the image is called using predict method.
1316 """
1317 #Determine refresh rate of used display. This way the method will not
1318 #run too slowly or redundantly fast.
1319 device = win32api.EnumDisplayDevices()
1320 refresh_rate = win32api.EnumDisplaySettings(device.DeviceName, -1).DisplayFrequency
1321
1322 #Auxiliary variables for fps calculation
1323 frames = 0
1324 cycles = 0
1325
1326 color_format = QtGui.QImage.Format_Invalid
1327 str_color = None
1328 time_fps = time.monotonic_ns()
1329 #runs as long as the camera is recording or preview is active
1330 while self.recording or self.preview_live:
1331 cycles = cycles + 1
1332
1333 #Draw only if thre is at least 1 frame to draw
1334 if not active_frame_queue.qsize() == 0:
1335 image = active_frame_queue.get_nowait()
1336 self.received = self.received + 1
1337
1338 frames += 1
1339
1340 #Dump all remaining frames (If frames are received faster than
1341 #refresh_rate).
1342 while not active_frame_queue.qsize() == 0:
1343 frames += 1
1344 self.received = self.received + 1
1345 active_frame_queue.get_nowait()
1346
1347 #Try to run a prediction
1348 self.predict(image[0])
1349
1350 #Set up a new value of received frames in the statusbar
1351 self.receive_status.setText("Received frames: " + str(self.received))
1352
1353 #Change to time dependency instead of cycle#More cycles -> more exact fps calculation (value is more stable in gui)
1354
1355 if cycles > 30:
1356 time_now = time.monotonic_ns()
1357 time_passed = time_now - time_fps
1358 time_fps = time_now
1359 #[frames*Hz/c] -> [frames/s]
1360 self.fps = round(frames/(time_passed/1_000_000_000),1)
1361 self.fps_status.setText("FPS: " + str(self.fps))
1362
1363 cycles = 0
1364 frames = 0
1365
1366 #Convert image to proper format for PyQt
1367 h, w, ch = image[0].shape
1368 bytes_per_line = ch * w
1369
1370
1371 if(str_color != image[1]):
1372 str_color = image[1]
1373 color_format = self._get_QImage_format(str_color)
1374
1375 if(color_format == QtGui.QImage.Format_Invalid):
1376 self.set_status_msg("Used image format is not supported")
1377
1378
1379 image = QtGui.QImage(image[0].data, w, h, bytes_per_line, color_format)
1380 #TODO Get color format dynamically
1381
1382 #get size of preview window if zoom fit is selected
1383 if(self.preview_fit == True):
1384 self.w_preview = self.preview_area.size().width()
1385 self.h_preview = self.preview_area.size().height()
1386 image_scaled = image.scaled(self.w_preview,
1387 self.h_preview,
1388 QtCore.Qt.KeepAspectRatio)
1389 else:#else use zoom percentage
1390 self.w_preview = w*self.preview_zoom
1391 self.h_preview = w*self.preview_zoom
1392 image_scaled = image.scaled(self.w_preview,
1393 self.w_preview,
1394 QtCore.Qt.KeepAspectRatio)
1395
1396 self.image_pixmap = QtGui.QPixmap.fromImage(image_scaled)
1397 self.preview_callback()
1398 #Set image to gui
1399 #Wait for next display frame
1400 time.sleep(1/refresh_rate)
1401
1402 #When recording stops, change fps to 0
1403 self.fps = 0.0
1404 self.fps_status.setText("FPS: " + str(self.fps))
1405
1406 def preview_callback(self):
1407 """!@brief Auxiliary method used to transfer thread state change into
1408 the main thread.
1409 """
1410 if(self.resize_signal.text() != "A"):
1411 self.resize_signal.setText("A")
1412 else:
1413 self.resize_signal.setText("B")
1414
1415 def update_img(self):
1416 """!@brief update image in the live preview window.
1417 @details This method must run in the main thread as it modifies frontend
1418 data of the gui.
1419 """
1420 #Resize preview label if preview window size changed
1421 if(self.w_preview != self.camera_preview.size().width() or
1422 self.h_preview != self.camera_preview.size().height()):
1423 self.camera_preview.resize(self.w_preview,
1424 self.h_preview)
1425
1426 #set a new image to the preview area
1427 self.camera_preview.setPixmap(self.image_pixmap)
1428 self.camera_preview.show()
1429
1430 def _get_QImage_format(self, format_string):
1431 """!@brief The image format provided by camera object (according to
1432 GenICam standard) is transoformed to one of the color formats supported
1433 by PyQt.
1434 @param[in] format_string text containing color format defined by GenICam
1435 or another standard.
1436 """
1437 image_format = None
1438
1439 if(format_string == 'Format_Mono'):
1440 image_format = QtGui.QImage.Format_Mono
1441 elif(format_string == 'Format_MonoLSB'):
1442 image_format = QtGui.QImage.Format_MonoLSB
1443 elif(format_string == 'Format_Indexed8'):
1444 image_format = QtGui.QImage.Format_Indexed8
1445 elif(format_string == 'Format_RGB32'):
1446 image_format = QtGui.QImage.Format_RGB32
1447 elif(format_string == 'Format_ARGB32'):
1448 image_format = QtGui.QImage.Format_ARGB32
1449 elif(format_string == 'Format_ARGB32_Premultiplied'):
1450 image_format = QtGui.QImage.Format_ARGB32_Premultiplied
1451 elif(format_string == 'Format_RGB16'):
1452 image_format = QtGui.QImage.Format_RGB16
1453 elif(format_string == 'Format_ARGB8565_Premultiplied'):
1454 image_format = QtGui.QImage.Format_ARGB8565_Premultiplied
1455 elif(format_string == 'Format_RGB666'):
1456 image_format = QtGui.QImage.Format_RGB666
1457 elif(format_string == 'Format_ARGB6666_Premultiplied'):
1458 image_format = QtGui.QImage.Format_ARGB6666_Premultiplied
1459 elif(format_string == 'Format_RGB555'):
1460 image_format = QtGui.QImage.Format_RGB555
1461 elif(format_string == 'Format_ARGB8555_Premultiplied'):
1462 image_format = QtGui.QImage.Format_ARGB8555_Premultiplied
1463 elif(format_string == 'Format_RGB888' or format_string == 'RGB8'):
1464 image_format = QtGui.QImage.Format_RGB888
1465 elif(format_string == 'Format_RGB444'):
1466 image_format = QtGui.QImage.Format_RGB444
1467 elif(format_string == 'Format_ARGB4444_Premultiplied'):
1468 image_format = QtGui.QImage.Format_ARGB4444_Premultiplied
1469 elif(format_string == 'Format_RGBX8888'):
1470 image_format = QtGui.QImage.Format_RGBX8888
1471 elif(format_string == 'Format_RGBA8888' or format_string == 'RGBa8'):
1472 image_format = QtGui.QImage.Format_RGBA8888
1473 elif(format_string == 'Format_RGBA8888_Premultiplied'):
1474 image_format = QtGui.QImage.Format_RGBA8888_Premultiplied
1475 elif(format_string == 'Format_BGR30'):
1476 image_format = QtGui.QImage.Format_BGR30
1477 elif(format_string == 'Format_A2BGR30_Premultiplied'):
1478 image_format = QtGui.QImage.Format_A2BGR30_Premultiplied
1479 elif(format_string == 'Format_RGB30'):
1480 image_format = QtGui.QImage.Format_RGB30
1481 elif(format_string == 'Format_A2RGB30_Premultiplied'):
1482 image_format = QtGui.QImage.Format_A2RGB30_Premultiplied
1483 elif(format_string == 'Format_Alpha8'):
1484 image_format = QtGui.QImage.Format_Alpha8
1485 elif(format_string == 'Format_Grayscale8' or format_string == 'Mono8'):
1486 image_format = QtGui.QImage.Format_Grayscale8
1487 elif(format_string == 'Format_Grayscale16' or format_string == 'Mono16'):
1488 image_format = QtGui.QImage.Format_Grayscale16
1489 elif(format_string == 'Format_RGBX64'):
1490 image_format = QtGui.QImage.Format_RGBX64
1491 elif(format_string == 'Format_RGBA64'):
1492 image_format = QtGui.QImage.Format_RGBA64
1493 elif(format_string == 'Format_RGBA64_Premultiplied'):
1494 image_format = QtGui.QImage.Format_RGBA64_Premultiplied
1495 elif(format_string == 'Format_BGR888' or format_string == 'BGR8'):
1496 image_format = QtGui.QImage.Format_BGR888
1497 else:
1498 image_format = QtGui.QImage.Format_Invalid
1499
1500 return image_format
1501
1502 '''
1503 SFNC OPTIONS not yet implemented
1504 Mono1p
1505 Mono2p, Mono4p, Mono8s, Mono10, Mono10p, Mono12, Mono12p, Mono14,
1506 , R8, G8, B8, , RGB8_Planar, , RGB10, RGB10_Planar,
1507 RGB10p32, RGB12, RGB12_Planar, RGB16, RGB16_Planar, RGB565p, BGR10,
1508 BGR12, BGR16, BGR565p, , BGRa8, YUV422_8, YCbCr411_8, YCbCr422_8,
1509 YCbCr601_422_8, YCbCr709_422_8, YCbCr8, BayerBG8, BayerGB8, BayerGR8,
1510 BayerRG8, BayerBG10, BayerGB10, BayerGR10, BayerRG10, BayerBG12,
1511 BayerGB12, BayerGR12, BayerRG12, BayerBG16, BayerGB16, BayerGR16,
1512 BayerRG16, Coord3D_A8, Coord3D_B8, Coord3D_C8, Coord3D_ABC8,
1513 Coord3D_ABC8_Planar, Coord3D_A16, Coord3D_B16, Coord3D_C16,
1514 Coord3D_ABC16, Coord3D_ABC16_Planar, Coord3D_A32f, Coord3D_B32f,
1515 Coord3D_C32f, Coord3D_ABC32f, Coord3D_ABC32f_Planar, Confidence1,
1516 Confidence1p, Confidence8, Confidence16, Confidence32f, Raw8, Raw16,
1517 Device-specific
1518 - GigE Vision Specific:
1519 Mono12Packed, BayerGR10Packed, BayerRG10Packed, BayerGB10Packed,
1520 BayerBG10Packed, BayerGR12Packed, BayerRG12Packed, BayerGB12Packed,
1521 BayerBG12Packed, RGB10V1Packed, RGB12V1Packed,
1522 - Deprecated:
1523 will not be implemented for now as they are not used in genicam anymore
1524 '''
1525 '''
1526 SFNC OPTIONS - all
1527 Mono1p
1528 Mono2p, Mono4p, Mono8, Mono8s, Mono10, Mono10p, Mono12, Mono12p, Mono14,
1529 Mono16, R8, G8, B8, RGB8, RGB8_Planar, RGBa8, RGB10, RGB10_Planar,
1530 RGB10p32, RGB12, RGB12_Planar, RGB16, RGB16_Planar, RGB565p, BGR10,
1531 BGR12, BGR16, BGR565p, BGR8, BGRa8, YUV422_8, YCbCr411_8, YCbCr422_8,
1532 YCbCr601_422_8, YCbCr709_422_8, YCbCr8, BayerBG8, BayerGB8, BayerGR8,
1533 BayerRG8, BayerBG10, BayerGB10, BayerGR10, BayerRG10, BayerBG12,
1534 BayerGB12, BayerGR12, BayerRG12, BayerBG16, BayerGB16, BayerGR16,
1535 BayerRG16, Coord3D_A8, Coord3D_B8, Coord3D_C8, Coord3D_ABC8,
1536 Coord3D_ABC8_Planar, Coord3D_A16, Coord3D_B16, Coord3D_C16,
1537 Coord3D_ABC16, Coord3D_ABC16_Planar, Coord3D_A32f, Coord3D_B32f,
1538 Coord3D_C32f, Coord3D_ABC32f, Coord3D_ABC32f_Planar, Confidence1,
1539 Confidence1p, Confidence8, Confidence16, Confidence32f, Raw8, Raw16,
1540 Device-specific
1541 - GigE Vision Specific:
1542 Mono12Packed, BayerGR10Packed, BayerRG10Packed, BayerGB10Packed,
1543 BayerBG10Packed, BayerGR12Packed, BayerRG12Packed, BayerGB12Packed,
1544 BayerBG12Packed, RGB10V1Packed, RGB12V1Packed,
1545 - Deprecated:
1546 Mono8Signed (Deprecated, use Mono8s)
1547 RGB8Packed (Deprecated, use RGB8) ,BGR8Packed (Deprecated, use BGR8),
1548 RGBA8Packed (Deprecated, use RGBa8), BGRA8Packed (Deprecated, use BGRa8),
1549 RGB10Packed (Deprecated, use RGB10), BGR10Packed (Deprecated, use BGR10),
1550 RGB12Packed (Deprecated, use RGB12), BGR12Packed (Deprecated, use BGR12),
1551 RGB16Packed (Deprecated, use RGB16), BGR16Packed (Deprecated, use BGR16),
1552 RGB10V2Packed (Deprecated, use RGB10p32), BGR10V2Packed (Deprecated, use BGR10p32),
1553 RGB565Packed (Deprecated, use RGB565p), BGR565Packed (Deprecated, use BGR565p),
1554 YUV411Packed (Deprecated, use YUV411_8_UYYVYY), YUV422Packed (Deprecated, use YUV422_8_UYVY),
1555 YUV444Packed (Deprecated, use YUV8_UYV), YUYVPacked (Deprecated, use YUV422_8),
1556 RGB8Planar (Deprecated, use RGB8_Planar), RGB10Planar (Deprecated, use RGB10_Planar),
1557 RGB12Planar (Deprecated, use RGB12_Planar), RGB16Planar (Deprecated, use RGB16_Planar),
1558 '''
1559
1560 #-----------Tensorflow tab----------------------------
1561 def load_model(self):
1562 """!@brief When user wants to load a tensorflow model, this method will
1563 open a file dialog and makes sure the path provided actually contains
1564 a tensorflow model.
1565 """
1566 #Open file dialog for choosing a folder
1567 name = self.get_directory(self.line_edit_model_name)
1568
1569 dim = self.vision.load_model(name)
1570 #Set label text to chosen folder path
1571 if(dim):
1572 self.line_edit_res_width.setText(str(dim[0]))
1573 self.line_edit_res_height.setText(str(dim[1]))
1574 self.set_status_msg("Model loaded")
1575 self.model_loaded = True
1576 else:
1577 self.set_status_msg("Failed to load model")
1578 self.line_edit_model_name.setText("Select a model to load")
1579
1580 def save_model(self):
1581 """!@brief If tensorflow model is loaded, the file dialog is opened
1582 for user to choose save location.
1583 """
1584 #Open file dialog for choosing a folder
1585 if(not self.model_loaded):
1586 return
1587
1588 name = QtWidgets.QFileDialog.getSaveFileName(self.centralwidget,
1589 "Save Model",
1590 filter="Keras model folder (*.model)",
1591 )
1592 #Set label text to chosen folder path
1593 if(name[0]):
1594 saved = self.vision.save_model(name[0])
1595 if(saved):
1596 self.set_status_msg("Model saved")
1597 else:
1598 self.set_status_msg("Failed to save model")
1599
1600 def choose_dataset(self):
1601 """!@brief Get dataset path and reenable preprocess button.
1602 """
1603 self.get_directory(self.line_edit_dataset_path)
1604 self.btn_preprocess.setEnabled(True)
1605
1606 def preprocess_dataset(self):
1607 """!@brief Is called after user chooses dataset and clicks the load button.
1608 @details This method will proceed only if some path to the dataset has
1609 been provided. From the names of the folders the category names are derived.
1610 The data are then processed and modified to be suitable as inputs to
1611 the loaded neural network. Preprocessing runs in its own thread and
1612 provides callback to the GUI.
1613 """
1614 if(self.line_edit_dataset_path.text() and self.model_loaded):
1615 try:
1616 self.btn_preprocess.setEnabled(False)
1617 path = self.line_edit_dataset_path.text()
1618 files = os.scandir(path)
1619 categories = []
1620
1621 for file in files:
1622 if file.is_dir():
1623 categories.append(file.name)
1624
1625 self.process_flag.clear()
1626
1627 self.preprocess_thread = threading.Thread(
1628 target=self.vision.process_dataset,
1629 kwargs={'path': path,
1630 'process_perc': self.process_perc,
1631 'categories': categories,
1632 'process_flag': self.process_flag,
1633 'callback_flag': self.process_prog_flag})
1634 self.callback_preprocess_thread = threading.Thread(target=self.preprocess_callback)
1635
1636
1637 self.callback_preprocess_thread.start()
1638 self.preprocess_thread.start()
1639 except:
1640 self.process_prog_flag.clear()
1641 self.process_flag.clear()
1642
1643 def preprocess_callback(self):
1644 """!@brief Auxiliary method used to transfer thread state changes into
1645 the main thread.
1646 """
1647 while(not self.process_flag.is_set()):
1648 self.process_prog_flag.wait(2)
1649 if(not self.process_prog_flag.is_set()):
1650 continue
1651 self.process_prog_flag.clear()
1652 if(self.callback_process_signal.text() != "A"):
1653 self.callback_process_signal.setText("A")
1654 else:
1655 self.callback_process_signal.setText("B")
1656
1657 self.set_status_msg("Dataset preprocess completed")
1658
1659 def update_processing(self):
1660 """!@brief While the dataset is being processed this method shows the
1661 progress to the user. Method must run in the main thread
1662 """
1663 self.progress_bar_preprocess.setValue(int(self.process_perc[0]))
1664
1665 def train_model(self):
1666 """!@brief When the train button is pressed, this methods makes sure the
1667 training will start correctly.
1668 @details The method starts the training only if it is not already in
1669 progress. The training is started in its own thread and all progress
1670 variables are passed into the training method. At the same time, another
1671 thread is created for controling the progress status updates and callbacks.
1672 """
1673 if(not self.training_flag.is_set()):
1674 self.training_flag.set()
1675
1676 split = self.spin_box_val_split.value()/100
1677
1678 self.train_thread = threading.Thread(target=self.vision.train, kwargs={
1679 'epochs': self.spin_box_epochs.value(),
1680 'train_vals': self.train_vals,
1681 'split': split,
1682 'progress_flag': self.progress_flag,
1683 'training_flag': self.training_flag})
1684
1685 self.callback_train_thread = threading.Thread(target=self.training_callback)
1686
1687 self.callback_train_thread.start()
1688 self.train_thread.start()
1689 else:
1690 #stop training prematurely
1691 #self.training_flag.clear()
1692 pass
1693
1694 def training_callback(self):
1695 """!@brief Auxiliary method used to transfer thread state changes into
1696 the main thread.
1697 """
1698 while(self.training_flag.is_set()):
1699 self.progress_flag.wait(2)
1700 if(not self.progress_flag.is_set()):
1701 continue
1702 self.progress_flag.clear()
1703 if(self.callback_train_signal.text() != "A"):
1704 self.callback_train_signal.setText("A")
1705 else:
1706 self.callback_train_signal.setText("B")
1707 self.set_status_msg("Training ended")
1708
1709 def update_training(self):
1710 """!@brief Updates training progress in the GUI.
1711 @details Is called as a result of training_callback change. All variables
1712 are set up in other threads and this method reads them and update the
1713 GUI in the main application thread.
1714 """
1715
1716 self.progress_bar_train.setValue(self.train_vals['progress'])
1717 self.line_edit_loss.setText(str(self.train_vals['loss']))
1718 self.line_edit_acc.setText(str(self.train_vals['acc']))
1719 self.line_edit_val_loss.setText(str(self.train_vals['val_loss']))
1720 self.line_edit_val_acc.setText(str(self.train_vals['val_acc']))
1721 self.label_active_epoch.setText(str(self.train_vals['epoch']) + '/' + str(self.train_vals['max_epoch']))
1722
1723 def predict(self,frame):
1724 """!@brief Starts a thread used to classify images from live camera feed
1725 @details This method should only be called when the last prediction
1726 ended. That means not every frame will be classified if the computer
1727 can't keep up in the real time.
1728 @param[in] frame Picture to be classified. The format is OpenCV image.
1729 """
1730 #Tensorflow index is 3, if the gui changes, this may need to chage as well
1731 if(self.tabs.currentIndex() == 3 and
1732 self.tensorflow_tabs.currentIndex() == 0):
1733 if(not self.prediction_flag.is_set() and self.model_loaded == True):
1734 self.prediction_flag.set()
1735
1736 self.prediction_thread = threading.Thread(
1737 target=self.vision.classify, kwargs={'frame': frame, 'prediction_flag': self.prediction_flag})
1738 self.prediction_thread.start()
1739
1740 #------------Camera config tab--------------------------
1741 def show_parameters(self):
1742 """!@brief Loads all camera's features and creates dynamic widgets for
1743 every feature.
1744 @details This method is called when user first enters parameters tab or
1745 when the configuration level changes. All the widgets are created dynamically
1746 and based on the type of the feature, proper widget type is selected. Also
1747 these widgets have method to change their value associated with them
1748 when created.
1749 """
1750 num = 0
1751
1752 categories = []
1753 self.top_items = {}
1754 self.children_items = {}
1755
1756 self.tree_features.clear()
1757
1758 for name in self.feat_widgets:
1759 self.feat_widgets[name].deleteLater()
1760
1761 for name in self.feat_labels:
1762 self.feat_labels[name].deleteLater()
1763
1764 self.feat_widgets.clear()
1765 self.feat_labels.clear()
1766
1767 while not self.feat_queue.empty():
1768 try:
1769 param = self.feat_queue.get()
1770 param['attr_cat'] = param['attr_cat'].lstrip('/')
1771 ctgs = param['attr_cat'].split('/')
1772 for i, ctg in enumerate(ctgs):
1773 if(not(ctg in categories)):
1774 if(i == 0):
1775 self.top_items[ctg] = QtWidgets.QTreeWidgetItem([ctg])
1776 self.tree_features.addTopLevelItem(self.top_items[ctg])
1777 else:
1778 self.top_items[ctg] = QtWidgets.QTreeWidgetItem([ctg])
1779 self.top_items[ctgs[i-1]].addChild(self.top_items[ctg])
1780 categories.append(ctg)
1781 #Create a new label with name of the feature
1782
1783 self.feat_labels[param["name"]] = QtWidgets.QLabel(self.tab_config)
1784 self.feat_labels[param["name"]].setObjectName(param["name"])
1785 self.feat_labels[param["name"]].setText(param["attr_name"])
1786 #If the feature has a tooltip, set it.
1787 try:
1788 self.feat_labels[param["name"]].setToolTip(param["attr_tooltip"])
1789 except:
1790 pass
1791
1792 #Place the label on the num line of the layout
1793 #self.parameters_layout.setWidget(num, QtWidgets.QFormLayout.LabelRole, self.feat_labels[param["name"]])
1794
1795 #If the feature does not have a value, set it to 0
1796 if param["attr_value"] == None:
1797 param["attr_value"] = 0
1798
1799 #Based on the feature type, right widget is chosen to hold the
1800 #feature's value
1801
1802 if param["attr_type"] == "IntFeature":
1803 #For int feature a Line edit field is created, but only
1804 #integers can be written in.
1805 self.feat_widgets[param["name"]] = QtWidgets.QSpinBox(self.tab_config)
1806 if(param["attr_range"]):
1807 self.feat_widgets[param["name"]].setRange(
1808 param["attr_range"][0],
1809 param["attr_range"][1])
1810
1811 #Set text to the current value of the feature
1812 self.feat_widgets[param["name"]].setValue(param["attr_value"])
1813
1814 #Call feature change for this feature when enter is pressed in this field.
1815 #Text is the value that will be set to the feature.
1816 self.feat_widgets[param["name"]].valueChanged.connect(lambda new_val,param=param: cam.set_parameter(param["name"],new_val))
1817 elif param["attr_type"] == "FloatFeature":
1818 #For float feature a Line edit field is created, but only
1819 #real numbers can be written in.
1820 self.feat_widgets[param["name"]] = QtWidgets.QDoubleSpinBox(self.tab_config)
1821 if(param["attr_range"]):
1822 self.feat_widgets[param["name"]].setRange(
1823 param["attr_range"][0],
1824 param["attr_range"][1])
1825
1826 #Set text to the current value of the feature
1827 self.feat_widgets[param["name"]].setValue(param["attr_value"])
1828
1829 #Call feature change for this feature when enter is pressed in this field.
1830 #Text is the value that will be set to the feature.
1831 self.feat_widgets[param["name"]].valueChanged.connect(lambda new_val,param=param: cam.set_parameter(param["name"],new_val))
1832 elif param["attr_type"] == "StringFeature":
1833 #For string feature a Line edit field is created.
1834 self.feat_widgets[param["name"]] = QtWidgets.QLineEdit(self.tab_config)
1835
1836 #Set text to the current value of the feature
1837 self.feat_widgets[param["name"]].setText(param["attr_value"])
1838
1839 #Call feature change for this feature when enter is pressed in this field.
1840 #Text is the value that will be set to the feature.
1841 self.feat_widgets[param["name"]].returnPressed.connect(lambda new_val,param=param: cam.set_parameter(param["name"],new_val))
1842 elif param["attr_type"] == "BoolFeature":
1843 #For bool feature a checkbox is created.
1844 self.feat_widgets[param["name"]] = QtWidgets.QCheckBox(self.tab_config)
1845
1846 #If value is true the checkbox is ticked otherwise remains empty
1847 self.feat_widgets[param["name"]].setChecked(param["attr_value"])
1848
1849 #When state of the checkbox change, the feature is sent to
1850 #the camera and changed to the new state
1851 self.feat_widgets[param["name"]].stateChanged.connect(lambda new_val,param=param: cam.set_parameter(param["name"],new_val))
1852 elif param["attr_type"] == "EnumFeature":
1853 #For enum feature a combo box is created.
1854 self.feat_widgets[param["name"]] = QtWidgets.QComboBox(self.tab_config)
1855
1856 #All available enum states are added as options to the
1857 #combo box.
1858 for enum in param["attr_enums"]:
1859 self.feat_widgets[param["name"]].addItem(str(enum))
1860
1861 #Search the options and find the index of the active value
1862 index = self.feat_widgets[param["name"]].findText(str(param["attr_value"]), QtCore.Qt.MatchFixedString)
1863
1864 #Set found index to be the active one
1865 if index >= 0:
1866 self.feat_widgets[param["name"]].setCurrentIndex(index)
1867
1868 #When different option is selected change the given enum in
1869 #the camera
1870 self.feat_widgets[param["name"]].activated.connect(lambda new_val,param=param: cam.set_parameter(param["name"],new_val+1))
1871 elif param["attr_type"] == "CommandFeature":
1872 #If the feature type is not recognized, create a label with
1873 #the text error
1874 self.feat_widgets[param["name"]] = QtWidgets.QPushButton(self.tab_config)
1875 self.feat_widgets[param["name"]].setText("Execute command")
1876 self.feat_widgets[param["name"]].clicked.connect(lambda val,param=param: cam.execute_command(param["name"]))
1877 else:
1878 #If the feature type is not recognized, create a label with
1879 #the text error
1880 self.feat_widgets[param["name"]] = QtWidgets.QLabel(self.tab_config)
1881 self.feat_widgets[param["name"]].setText("Unknown feature type")
1882
1883 self.feat_widgets[param["name"]].setEnabled(param["attr_enabled"])
1884
1885 #Add newly created widget to the layout on the num line
1886 new_item = QtWidgets.QTreeWidgetItem(self.top_items[ctgs[-1]] ,['', ''])
1887 #add new item to the last subcategory of its category tree
1888 self.tree_features.setItemWidget(new_item, 0,self.feat_labels[param["name"]])
1889 self.tree_features.setItemWidget(new_item, 1,self.feat_widgets[param["name"]])
1890 #new_item = QtWidgets.QTreeWidgetItem(self.top_items[param['attr_cat']] ,[self.feat_labels[param["name"]], self.feat_widgets[param["name"]]])
1891 self.children_items[param["name"]] = new_item
1892 #self.parameters_layout.setWidget(num, QtWidgets.QFormLayout.FieldRole, self.feat_widgets[param["name"]])
1893 num += 1
1894 except:
1895 pass
1896 #we'll get here when queue is empty
1897 self.param_flag.clear()
1898
1899 def start_refresh_parameters(self):
1900 """!@brief Called automatically when feat_refresh_timer runs out
1901 @details used to start a thread to refresh parameters values. Not
1902 called by user but automatically.
1903 """
1904 #called every 4 seconds
1905 if (self.feat_widgets and self.connected and self.tabs.currentIndex() == 1 and
1906 not(self.preview_live or self.recording) and
1907 not self.param_flag.is_set() and self.update_completed_flag.is_set()):
1908
1909 self.update_completed_flag.clear()
1910
1911 self.update_thread = threading.Thread(target=self.get_new_val_parameters)
1912 self.update_thread.start()
1913
1914 def get_new_val_parameters(self):
1915 """!@brief Check for new parameter value
1916 @details after camera features are loaded, this method periodically
1917 calls for the most recent value of each parameter.
1918 """
1919 if(not self.feat_widgets):
1920 self.update_completed_flag.set()
1921 return
1922
1923 params = Queue()
1924 tries = 0
1925 while(tries <= 10):
1926 if(cam.get_parameters(params,
1927 threading.Event(),
1928 self.combo_config_level.currentIndex()+1)):
1929 break
1930 else:
1931 tries += 1
1932
1933 if(tries >= 10):
1934 self.update_completed_flag.set()
1935 return
1936
1937 while(not params.empty()):
1938 parameter = params.get()
1939 if(not(self.preview_live or self.recording) and
1940 self.tabs.currentIndex() == 1):
1941 self.parameter_values[parameter["name"]] = parameter["attr_value"]
1942 else:
1943 self.update_completed_flag.set()
1944 return
1945 self.update_flag.set()
1946
1947 def update_parameters(self):
1948 """!@brief Writes new values of the parameters to the GUI.
1949 @details After get_new_val_parameters finishes, the update_flag is set
1950 and this method can transfer the new values of the parameters to the GUI.
1951 Like start_refresh_parameters, this method is bound to the timer.
1952 """
1953 if (self.connected and not self.param_flag.is_set() and
1954 self.tabs.currentIndex() == 1 and
1955 self.update_flag.is_set() and not(self.preview_live or self.recording)):
1956
1957 self.update_flag.clear()
1958
1959 for parameter in self.feat_widgets:
1960 try:
1961 value = self.parameter_values[parameter]
1962 widget = self.feat_widgets[parameter]
1963 if(value == None):
1964 continue
1965
1966 if(type(widget) == QtWidgets.QLineEdit):
1967 widget.setText(str(value))
1968 elif(type(widget) == QtWidgets.QComboBox):
1969 index = widget.findText(str(value), QtCore.Qt.MatchFixedString)
1970 #Set found index to be the active one
1971 if index >= 0:
1972 widget.setCurrentIndex(index)
1973 elif(type(widget) == QtWidgets.QDoubleSpinBox or
1974 type(widget) == QtWidgets.QSpinBox):
1975 widget.setValue(value)
1976 elif(type(widget) == QtWidgets.QCheckBox):
1977 widget.setChecked(value)
1978 except:
1979 pass
1980 self.update_completed_flag.set()
1981
1982 def load_parameters(self):
1983 """!@brief Fills layout with feature name and value pairs
1984 @details Based on the feature type a new label, text area, checkbox or
1985 combo box is created. In this version all available parameters are shown.
1986 """
1987
1988 #Start filling features in only with connected camera
1989 if self.connected and not self.param_flag.is_set():
1990 #Status message
1991
1992 self.set_status_msg("Reading features")
1993
1994 #empty feature queue
1995 self.get_params_thread = threading.Thread(
1996 target=cam.get_parameters,
1997 kwargs={'feature_queue': self.feat_queue,
1998 'flag': self.param_flag,
1999 'visibility': Config_level(self.combo_config_level.currentIndex()+1)})
2000 self.param_callback_thread = threading.Thread(target=self.callback_parameters)
2001
2002
2003 self.param_callback_thread.start()
2004 self.get_params_thread.start()
2005
2006 def save_cam_config(self):
2007 """!@brief Opens file dialog for user to select where to save camera
2008 configuration.
2009 @details Called by Save configuration button. Configuration is saved
2010 as an .xml file and its contents are dependent on module used in Camera
2011 class to save the config.
2012 """
2013
2014 if(self.connected):
2015 #Open file dialog for choosing a save location and name
2016 name = QtWidgets.QFileDialog.getSaveFileName(self.centralwidget,
2017 "Save Configuration",
2018 filter="XML files (*.xml)",
2019 directory="config.xml")
2020
2021 #Save camera config to path specified in name (0 index)
2022 cam.save_config(name[0])
2023
2024 def load_cam_config(self):
2025 """!@brief Allows a user to choose saved xml configuration and load it
2026 into the camera
2027 @details Allowes only xml file in the file dialog and after loading prints
2028 a status message
2029 """
2030 if self.connected:
2031 if(not self.recording and not self.preview_live):
2032 name = QtWidgets.QFileDialog.getOpenFileName(self.centralwidget,
2033 "Load Configuration",
2034 filter="XML files (*.xml)")
2035
2036 #Set label text to chosen folder path
2037 if(name[0]):
2038 tries = 0
2039 while(tries <= 10):
2040 if(cam.load_config(name[0])):
2041 self.set_status_msg("Configuration loaded")
2042 return
2043 else:
2044 tries += 1
2045 self.set_status_msg("Loading failed", 2500)
2046 else:
2047 self.set_status_msg("Stop recording and preview before loading config")
2048
2049 def callback_parameters(self):
2050 """!@brief Auxiliary method used to transfer thread state change into
2051 the main thread.
2052 """
2053 self.param_flag.wait()
2054
2055 if(self.parameters_signal.text() != "A"):
2056 self.parameters_signal.setText("A")
2057 else:
2058 self.parameters_signal.setText("B")
2059
2060 #--------------Recording config tab-----------------------------
2061 def reset_seq_settings(self):
2062 """!@brief Restores default recording settings
2063 @details Settings are saved to config.ini file. Defaults are hard-coded
2064 in this method.
2065 """
2066 file_contents = []
2067
2068 #Open config file and load its contents
2069 with open("config.ini", 'r') as config:
2070 file_contents = config.readlines()
2071
2072 end_of_rec_conf = None
2073 #Find end of Recording config part of the file
2074 #if no delimiter is found a new one is added
2075 try:
2076 end_of_rec_conf = file_contents.index("CTI_FILES_PATHS\n")
2077 except(ValueError):
2078 file_contents.append("CTI_FILES_PATHS\n")
2079 end_of_rec_conf = -1
2080
2081 with open("config.ini", 'w') as config:
2082 #Write default states to the file
2083 config.write("RECORDING\n")
2084 config.write("filename=img(%n)\n")
2085 config.write("save_location=Recording\n")
2086 #maybe set to the documents folder
2087 config.write("sequence_duration=0\n")
2088
2089 #When at the end of recording config part, just copy the rest of
2090 #the initial file.
2091 if(end_of_rec_conf):
2092 for line in file_contents[end_of_rec_conf:]:
2093 config.write(line)
2094
2095 #Fill the Recording tab with updated values
2096 self.read_config()
2097
2098 #Print status msg
2099 self.set_status_msg("Configuration restored",2500)
2100
2101 def save_seq_settings(self):
2102 """!@brief Saves recording settings
2103 @details Settings are saved to config.ini file. Parameters saved are:
2104 file name, save, location and sequence duration.
2105 """
2106 file_contents = []
2107
2108 #Open config file and load its contents
2109 with open("config.ini", 'r') as config:
2110 file_contents = config.readlines()
2111
2112 #Open config file for writing
2113 with open("config.ini", 'w') as config:
2114
2115 for line in file_contents:
2116 #Reading configuration for recording
2117 if(line.startswith("filename=")):
2118 config.write("filename=" + self.line_edit_sequence_name.text() + "\n")
2119 elif(line.startswith("save_location=")):
2120 config.write("save_location=" + self.line_edit_save_location.text() + "\n")
2121 elif(line.startswith("sequence_duration=")):
2122 config.write("sequence_duration=" + self.line_edit_sequence_duration.text() + "\n")
2123 else:
2124 #All content not concerning recording is written back without change
2125 config.write(line)
2126 self.set_status_msg("Configuration saved")
2127
2128
2129
interface.Ui_MainWindow.widget_3
widget_3
Definition: interface.py:348
interface.Ui_MainWindow.recording
recording
State of recording.
Definition: interface.py:151
interface.Ui_MainWindow.retranslateUi
def retranslateUi(self, MainWindow)
Sets names of widgets.
Definition: interface.py:732
interface.Ui_MainWindow.update_training
def update_training(self)
Updates training progress in the GUI.
Definition: interface.py:1709
interface.Ui_MainWindow.label_active_epoch
label_active_epoch
Definition: interface.py:526
interface.Ui_MainWindow.param_flag
param_flag
Flag is not set while the application is getting parameters from the cam object.
Definition: interface.py:109
interface.Ui_MainWindow.icon_standby
icon_standby
Holds image of standby state of a camera.
Definition: interface.py:158
interface.Ui_MainWindow.label_val_split
label_val_split
Definition: interface.py:565
interface.Ui_MainWindow
Main class for user interface.
Definition: interface.py:34
interface.Ui_MainWindow.save_seq_settings
def save_seq_settings(self)
Saves recording settings.
Definition: interface.py:2101
interface.Ui_MainWindow.progress_bar_train
progress_bar_train
Definition: interface.py:543
interface.Ui_MainWindow.callback_train_thread
callback_train_thread
Definition: interface.py:1685
interface.Ui_MainWindow.btn_start_preview
btn_start_preview
Definition: interface.py:244
interface.Ui_MainWindow.train_vals
train_vals
dictionary holding variables used in a callback while training
Definition: interface.py:136
interface.Ui_MainWindow.clear_status
def clear_status(self)
Empties self.status_label in self.statusbar.
Definition: interface.py:931
interface.Ui_MainWindow.vision
vision
Definition: interface.py:730
interface.Ui_MainWindow.btn_zoom_100
btn_zoom_100
Definition: interface.py:232
interface.Ui_MainWindow.preview_fit
preview_fit
Resizing image to preview area size instead of using zoom.
Definition: interface.py:87
interface.Ui_MainWindow.spin_box_epochs
spin_box_epochs
Definition: interface.py:575
interface.Ui_MainWindow.actionAbout_Anubis
actionAbout_Anubis
Definition: interface.py:689
interface.Ui_MainWindow.tab_changed
def tab_changed(self)
Called when tab changes.
Definition: interface.py:905
interface.Ui_MainWindow.preprocess_dataset
def preprocess_dataset(self)
Is called after user chooses dataset and clicks the load button.
Definition: interface.py:1606
interface.Ui_MainWindow.verticalLayout_2
verticalLayout_2
Definition: interface.py:194
interface.Ui_MainWindow.formLayout_2
formLayout_2
Definition: interface.py:409
interface.Ui_MainWindow.btn_start_recording
btn_start_recording
Definition: interface.py:249
interface.Ui_MainWindow.save_cam_config
def save_cam_config(self)
Opens file dialog for user to select where to save camera configuration.
Definition: interface.py:2006
interface.Ui_MainWindow.update_thread
update_thread
Definition: interface.py:1911
interface.Ui_MainWindow.seq_duration_wait
def seq_duration_wait(self)
Automatic recording interrupt.
Definition: interface.py:1189
interface.Ui_MainWindow.update_completed_flag
update_completed_flag
Flag used when running various parameter refreshing methods.
Definition: interface.py:78
interface.Ui_MainWindow.btn_connect_camera
btn_connect_camera
Definition: interface.py:273
interface.Ui_MainWindow.btn_refresh_cameras
btn_refresh_cameras
Definition: interface.py:276
interface.Ui_MainWindow.resize_signal
resize_signal
Widget used to transfer GUI changes from thread into the main thread while updating preview.
Definition: interface.py:125
interface.Ui_MainWindow.last_time_move
last_time_move
Definition: interface.py:901
interface.Ui_MainWindow.remove_cti
def remove_cti(self)
Used to remove selected GenTL producer file.
Definition: interface.py:1049
interface.Ui_MainWindow.move_y_prev
move_y_prev
Last value of the dragging in the preview area - y axis.
Definition: interface.py:70
interface.Ui_MainWindow.label_res_height
label_res_height
Definition: interface.py:598
interface.Ui_MainWindow.predict
def predict(self, frame)
Starts a thread used to classify images from live camera feed.
Definition: interface.py:1723
interface.Ui_MainWindow.show_preview
def show_preview(self)
Draws image from camera in real time.
Definition: interface.py:1310
interface.Ui_MainWindow.label_acc
label_acc
Definition: interface.py:504
interface.Ui_MainWindow.line_edit_res_width
line_edit_res_width
Definition: interface.py:602
interface.Ui_MainWindow.add_cti
def add_cti(self)
Used to load a new GenTL producer file.
Definition: interface.py:1029
interface.Ui_MainWindow.show_parameters
def show_parameters(self)
Loads all camera's features and creates dynamic widgets for every feature.
Definition: interface.py:1741
interface.Ui_MainWindow.w_preview
w_preview
Width of the preview area.
Definition: interface.py:60
interface.Ui_MainWindow.btn_zoom_fit
btn_zoom_fit
Definition: interface.py:236
interface.Ui_MainWindow.receive_status
receive_status
Definition: interface.py:666
interface.Ui_MainWindow.line_edit_dataset_path
line_edit_dataset_path
Definition: interface.py:616
interface.Ui_MainWindow.preview_live
preview_live
State of live preview.
Definition: interface.py:153
interface.Ui_MainWindow.detected
detected
List of detected cameras.
Definition: interface.py:102
interface.Ui_MainWindow.about
def about(self)
Shows simple about dialog.
Definition: interface.py:1018
interface.Ui_MainWindow.tab_train
tab_train
Definition: interface.py:478
interface.Ui_MainWindow.widget_4
widget_4
Definition: interface.py:269
interface.Ui_MainWindow.process_perc
process_perc
Progress percentage of dataset loading/preprocessing.
Definition: interface.py:72
interface.Ui_MainWindow.gridLayout
gridLayout
Definition: interface.py:188
interface.Ui_MainWindow.train_model
def train_model(self)
When the train button is pressed, this methods makes sure the training will start correctly.
Definition: interface.py:1665
interface.Ui_MainWindow.menuFile
menuFile
Definition: interface.py:637
interface.Ui_MainWindow.label_val_acc
label_val_acc
Definition: interface.py:495
interface.Ui_MainWindow.received
received
Total sum of received frames for active camera session.
Definition: interface.py:165
interface.Ui_MainWindow.disconnect_camera
def disconnect_camera(self)
Disconnect current camera.
Definition: interface.py:1111
interface.Ui_MainWindow.verticalLayout_4
verticalLayout_4
Definition: interface.py:267
interface.Ui_MainWindow.training_callback
def training_callback(self)
Auxiliary method used to transfer thread state changes into the main thread.
Definition: interface.py:1694
interface.Ui_MainWindow.read_config
def read_config(self)
Loads configuration from config.ini file.
Definition: interface.py:953
interface.Ui_MainWindow.actionRemove_cti_file
actionRemove_cti_file
Definition: interface.py:680
interface.Ui_MainWindow.line_edit_res_height
line_edit_res_height
Definition: interface.py:608
interface.Ui_MainWindow.file_manager_save_location
file_manager_save_location
Definition: interface.py:396
interface.Ui_MainWindow.formLayout_3
formLayout_3
Definition: interface.py:393
interface.Ui_MainWindow.setup_validators
def setup_validators(self)
create input constrains for various widgets
Definition: interface.py:867
interface.Ui_MainWindow.menubar
menubar
Definition: interface.py:634
interface.Ui_MainWindow.update_processing
def update_processing(self)
While the dataset is being processed this method shows the progress to the user.
Definition: interface.py:1659
interface.Ui_MainWindow.line_edit_acc
line_edit_acc
Definition: interface.py:499
interface.Ui_MainWindow.tip_add_cti
tip_add_cti
Definition: interface.py:303
interface.Ui_MainWindow.frame_cti
frame_cti
Definition: interface.py:291
interface.Ui_MainWindow.tabs
tabs
Definition: interface.py:259
interface.Ui_MainWindow.label_val_loss
label_val_loss
Definition: interface.py:508
interface.Ui_MainWindow.save_model
def save_model(self)
If tensorflow model is loaded, the file dialog is opened for user to choose save location.
Definition: interface.py:1580
interface.Ui_MainWindow.widget_sequence_name
widget_sequence_name
Definition: interface.py:371
interface.Ui_MainWindow.btn_remove_cti
btn_remove_cti
Definition: interface.py:297
interface.Ui_MainWindow.h_preview
h_preview
Height of the preview area.
Definition: interface.py:62
interface.Ui_MainWindow.move_x_prev
move_x_prev
Last value of the dragging in the preview area - x axis.
Definition: interface.py:68
interface.Ui_MainWindow.btn_save_config
btn_save_config
Definition: interface.py:353
interface.Ui_MainWindow.line_edit_save_location
line_edit_save_location
Definition: interface.py:401
interface.Ui_MainWindow.btn_preprocess
btn_preprocess
Definition: interface.py:585
interface.Ui_MainWindow.btn_reset_sequence_settings
btn_reset_sequence_settings
Definition: interface.py:435
interface.Ui_MainWindow.tree_features
tree_features
Definition: interface.py:342
interface.Ui_MainWindow.param_callback_thread
param_callback_thread
Definition: interface.py:2000
interface.Ui_MainWindow.model_loaded
model_loaded
Is tensorflow model loaded.
Definition: interface.py:65
interface.Ui_MainWindow.actionGit_Repository
actionGit_Repository
Definition: interface.py:692
interface.Ui_MainWindow.seq_duration_thread
seq_duration_thread
Definition: interface.py:1168
interface.Ui_MainWindow.verticalLayout_3
verticalLayout_3
Definition: interface.py:320
interface.Ui_MainWindow.update_parameters
def update_parameters(self)
Writes new values of the parameters to the GUI.
Definition: interface.py:1947
interface.Ui_MainWindow.camera_icon
camera_icon
Definition: interface.py:653
interface.Ui_MainWindow.gridLayout_3
gridLayout_3
Definition: interface.py:446
interface.Ui_MainWindow.list_detected_cameras
list_detected_cameras
Definition: interface.py:283
interface.Ui_MainWindow.line_edit_sequence_name
line_edit_sequence_name
Definition: interface.py:381
interface.Ui_MainWindow.btn_train_cancel
btn_train_cancel
Definition: interface.py:539
interface.Ui_MainWindow._get_QImage_format
def _get_QImage_format(self, format_string)
The image format provided by camera object (according to GenICam standard) is transoformed to one of ...
Definition: interface.py:1430
interface.Ui_MainWindow.label_loss
label_loss
Definition: interface.py:535
interface.Ui_MainWindow.progress_bar_preprocess
progress_bar_preprocess
Definition: interface.py:589
config_level.Config_level
This class defines configuration levels that are defined by the GenICam standard.
Definition: config_level.py:19
interface.Ui_MainWindow.tensorflow_tabs
tensorflow_tabs
Definition: interface.py:464
interface.Ui_MainWindow.fps
fps
Current frames per second received from the camera.
Definition: interface.py:163
computer_vision.Computer_vision
brief Implements Tensorflow communication
Definition: computer_vision.py:24
interface.Ui_MainWindow.image_pixmap
image_pixmap
Holds current frame displayed in the GUI.
Definition: interface.py:58
interface.Ui_MainWindow.label_train_epochs
label_train_epochs
Definition: interface.py:581
interface.Ui_MainWindow.line_edit_val_acc
line_edit_val_acc
Definition: interface.py:512
interface.Ui_MainWindow.tab_connect
tab_connect
Definition: interface.py:265
interface.Ui_MainWindow.statusbar
statusbar
Definition: interface.py:645
interface.Ui_MainWindow.label_img_resize
label_img_resize
Definition: interface.py:557
interface.Ui_MainWindow.update_flag
update_flag
Flag used when running various parameter refreshing methods.
Definition: interface.py:82
interface.Ui_MainWindow.frame_config_level
frame_config_level
Definition: interface.py:323
interface.Ui_MainWindow.top_items
top_items
Holds parameter category paths for tree widget.
Definition: interface.py:90
interface.Ui_MainWindow.horizontalLayout_2
horizontalLayout_2
Definition: interface.py:350
interface.Ui_MainWindow.preview_callback
def preview_callback(self)
Auxiliary method used to transfer thread state change into the main thread.
Definition: interface.py:1406
interface.Ui_MainWindow.process_prog_flag
process_prog_flag
Signal used to tell the main thread to update dataset progress.
Definition: interface.py:114
interface.Ui_MainWindow.feat_labels
feat_labels
Contains all dynamically created labels of parameters.
Definition: interface.py:97
interface.Ui_MainWindow.gridLayout_8
gridLayout_8
Definition: interface.py:492
interface.Ui_MainWindow.feat_refresh_timer
feat_refresh_timer
Automatic feature refresh timer.
Definition: interface.py:51
interface.Ui_MainWindow.action_save_settings
action_save_settings
Definition: interface.py:686
interface.Ui_MainWindow.start_refresh_parameters
def start_refresh_parameters(self)
Called automatically when feat_refresh_timer runs out.
Definition: interface.py:1899
interface.Ui_MainWindow.connect_actions
def connect_actions(self)
Connect method calls to appropriate widgets.
Definition: interface.py:812
interface.Ui_MainWindow.choose_dataset
def choose_dataset(self)
Get dataset path and reenable preprocess button.
Definition: interface.py:1600
interface.Ui_MainWindow.centralwidget
centralwidget
Definition: interface.py:183
interface.Ui_MainWindow.combo_remove_cti
combo_remove_cti
Definition: interface.py:307
interface.Ui_MainWindow.action_save_frame
action_save_frame
Definition: interface.py:683
interface.Ui_MainWindow.callback_process_signal
callback_process_signal
Widget used to transfer GUI changes from thread into the main thread while processing dataset.
Definition: interface.py:121
interface.Ui_MainWindow.parameter_values
parameter_values
Used to store values of parameters when automatically refreshing them.
Definition: interface.py:75
interface.Ui_MainWindow.tab_config
tab_config
Definition: interface.py:318
interface.Ui_MainWindow.parameters_signal
parameters_signal
Widget used to transfer GUI changes from thread into the main thread while showing parameters.
Definition: interface.py:129
interface.Ui_MainWindow.callback_preprocess_thread
callback_preprocess_thread
Definition: interface.py:1634
interface.Ui_MainWindow.tab_tensorflow
tab_tensorflow
Definition: interface.py:443
interface.Ui_MainWindow.callback_train_signal
callback_train_signal
Widget used to transfer GUI changes from thread into the main thread while training.
Definition: interface.py:117
interface.Ui_MainWindow.label_config_level
label_config_level
Definition: interface.py:329
interface.Ui_MainWindow.btn_disconnect_camera
btn_disconnect_camera
Definition: interface.py:279
interface.Ui_MainWindow.gridLayout_6
gridLayout_6
Definition: interface.py:555
interface.Ui_MainWindow.btn_single_frame
btn_single_frame
Definition: interface.py:240
interface.Ui_MainWindow.frame_train_preprocess
frame_train_preprocess
Definition: interface.py:550
interface.Ui_MainWindow.training_flag
training_flag
Is true while the tensorflow training is running.
Definition: interface.py:107
interface.Ui_MainWindow.callback_parameters
def callback_parameters(self)
Auxiliary method used to transfer thread state change into the main thread.
Definition: interface.py:2049
interface.Ui_MainWindow.label_epoch
label_epoch
Definition: interface.py:522
interface.Ui_MainWindow.load_cam_config
def load_cam_config(self)
Allows a user to choose saved xml configuration and load it into the camera.
Definition: interface.py:2024
interface.Ui_MainWindow.preview_and_control
preview_and_control
Definition: interface.py:191
interface.Ui_MainWindow.prediction_flag
prediction_flag
Signals that prediction was completed and a new one can be made.
Definition: interface.py:145
interface.Ui_MainWindow.horizontalLayout_3
horizontalLayout_3
Definition: interface.py:271
interface.Ui_MainWindow.btn_save_model
btn_save_model
Definition: interface.py:449
interface.Ui_MainWindow.btn_load_config
btn_load_config
Definition: interface.py:358
interface.Ui_MainWindow.combo_config_level
combo_config_level
Definition: interface.py:332
interface.Ui_MainWindow.widget_controls
widget_controls
Definition: interface.py:218
interface.Ui_MainWindow.camera_preview
camera_preview
Definition: interface.py:205
interface.Ui_MainWindow.train_thread
train_thread
Definition: interface.py:1678
interface.Ui_MainWindow.status_timer
status_timer
Timer used to show a status messages for specific time window.
Definition: interface.py:168
interface.Ui_MainWindow.btn_load_model
btn_load_model
Definition: interface.py:459
interface.Ui_MainWindow.menuHelp
menuHelp
Definition: interface.py:639
interface.Ui_MainWindow.widget_duration
widget_duration
Definition: interface.py:407
interface.Ui_MainWindow.horizontalLayout_5
horizontalLayout_5
Definition: interface.py:327
interface.Ui_MainWindow.get_directory
def get_directory(self, line_output=None)
Opens file dialog for user to set path to save frames.
Definition: interface.py:937
interface.Ui_MainWindow.line_edit_sequence_duration
line_edit_sequence_duration
Definition: interface.py:416
interface.Ui_MainWindow.btn_zoom_out
btn_zoom_out
Definition: interface.py:228
interface.Ui_MainWindow.fps_status
fps_status
Definition: interface.py:662
interface.Ui_MainWindow.btn_zoom_in
btn_zoom_in
Definition: interface.py:224
interface.Ui_MainWindow.update_img
def update_img(self)
update image in the live preview window.
Definition: interface.py:1415
interface.Ui_MainWindow.prediction_thread
prediction_thread
Definition: interface.py:1736
interface.Ui_MainWindow.record
def record(self)
Starts and stops recording.
Definition: interface.py:1141
interface.Ui_MainWindow.formLayout_4
formLayout_4
Definition: interface.py:374
interface.Ui_MainWindow.reset_seq_settings
def reset_seq_settings(self)
Restores default recording settings.
Definition: interface.py:2061
interface.Ui_MainWindow.label_sequence_duration
label_sequence_duration
Definition: interface.py:412
interface.Ui_MainWindow.preview
def preview(self)
Starts live preview.
Definition: interface.py:1209
interface.Ui_MainWindow.refresh_cameras
def refresh_cameras(self)
Calls function to detect connected cameras and prints them as items in a list.
Definition: interface.py:1060
interface.Ui_MainWindow.actionOpen_Help
actionOpen_Help
Definition: interface.py:677
interface.Ui_MainWindow.set_status_msg
def set_status_msg(self, message, timeout=0)
Shows message in status bar.
Definition: interface.py:917
interface.Ui_MainWindow.spin_box_val_split
spin_box_val_split
Definition: interface.py:569
interface.Ui_MainWindow.set_zoom
def set_zoom(self, flag)
Set the zoom amount of the image previewed.
Definition: interface.py:1241
interface.Ui_MainWindow.camera_status
camera_status
Definition: interface.py:658
interface.Ui_MainWindow.preview_zoom
preview_zoom
Value of current preview zoom in %/100.
Definition: interface.py:85
interface.Ui_MainWindow.eventFilter
def eventFilter(self, obj, event)
Implements dragging inside preview area.
Definition: interface.py:876
interface.Ui_MainWindow.get_params_thread
get_params_thread
Definition: interface.py:1995
interface.Ui_MainWindow.single_frame
def single_frame(self)
Acquire and draw a single frame.
Definition: interface.py:1264
interface.Ui_MainWindow.btn_add_cti
btn_add_cti
Definition: interface.py:300
interface.Ui_MainWindow.line_edit_val_loss
line_edit_val_loss
Definition: interface.py:517
interface.Ui_MainWindow.frame_train_stats
frame_train_stats
Definition: interface.py:487
interface.Ui_MainWindow.gridLayout_7
gridLayout_7
Definition: interface.py:295
interface.Ui_MainWindow.icon_busy
icon_busy
Holds image of busy state of a camera.
Definition: interface.py:160
interface.Ui_MainWindow.label_res_width
label_res_width
Definition: interface.py:594
interface.Ui_MainWindow.load_model
def load_model(self)
When user wants to load a tensorflow model, this method will open a file dialog and makes sure the pa...
Definition: interface.py:1561
interface.Ui_MainWindow.btn_save_sequence_settings
btn_save_sequence_settings
Definition: interface.py:431
interface.Ui_MainWindow.interupt_flag
interupt_flag
Signals that a recording was stopped, either by timer or manually.
Definition: interface.py:148
interface.Ui_MainWindow.preprocess_thread
preprocess_thread
Definition: interface.py:1627
interface.Ui_MainWindow.actionSave_camera_config
actionSave_camera_config
Definition: interface.py:695
interface.Ui_MainWindow.process_flag
process_flag
Signals that computer vision class is still processing dataset.
Definition: interface.py:112
interface.Ui_MainWindow.widget_sequence_save
widget_sequence_save
Definition: interface.py:391
interface.Ui_MainWindow.label_file_name_recording
label_file_name_recording
Definition: interface.py:377
interface.Ui_MainWindow.gridLayout_9
gridLayout_9
Definition: interface.py:481
interface.Ui_MainWindow.predictions
predictions
Definition: interface.py:472
interface.Ui_MainWindow.actionLoad_camera_config
actionLoad_camera_config
Definition: interface.py:698
interface.Ui_MainWindow.connect_camera
def connect_camera(self, index)
Connect to selected camera.
Definition: interface.py:1081
interface.Ui_MainWindow.label_sequence_duration_tip
label_sequence_duration_tip
Definition: interface.py:424
interface.Ui_MainWindow.load_parameters
def load_parameters(self)
Fills layout with feature name and value pairs.
Definition: interface.py:1982
interface.Ui_MainWindow.actionAdd_Remove_cti_file
actionAdd_Remove_cti_file
Definition: interface.py:674
interface.Ui_MainWindow.feat_widgets
feat_widgets
Contains all dynamically created widgets for parameters.
Definition: interface.py:95
interface.Ui_MainWindow.get_new_val_parameters
def get_new_val_parameters(self)
Check for new parameter value.
Definition: interface.py:1914
prediction_graph.Prediction_graph
Prediction results plot.
Definition: prediction_graph.py:21
interface.Ui_MainWindow.connected
connected
Is camera connected.
Definition: interface.py:104
interface.Ui_MainWindow.preview_area
preview_area
Definition: interface.py:199
interface.Ui_MainWindow.status_label
status_label
Definition: interface.py:649
interface.Ui_MainWindow.tab_recording_config
tab_recording_config
Definition: interface.py:366
interface.Ui_MainWindow.gridLayout_4
gridLayout_4
Definition: interface.py:221
interface.Ui_MainWindow.icon_offline
icon_offline
Holds image of offline state of a camera.
Definition: interface.py:156
interface.Ui_MainWindow.preprocess_callback
def preprocess_callback(self)
Auxiliary method used to transfer thread state changes into the main thread.
Definition: interface.py:1643
interface.Ui_MainWindow.label_sequence_name
label_sequence_name
Definition: interface.py:387
interface.Ui_MainWindow.__init__
def __init__(self)
Initialize the class and all its variables.
Definition: interface.py:44
interface.Ui_MainWindow.save_cti_config
def save_cti_config(self)
Saves all currently loaded GenTL producers to the config file.
Definition: interface.py:986
interface.Ui_MainWindow.line_edit_model_name
line_edit_model_name
Definition: interface.py:454
interface.Ui_MainWindow.line_edit_loss
line_edit_loss
Definition: interface.py:530
interface.Ui_MainWindow.btn_load_dataset
btn_load_dataset
Definition: interface.py:561
interface.Ui_MainWindow.show_preview_thread
show_preview_thread
Definition: interface.py:1172
interface.Ui_MainWindow.gridLayout_5
gridLayout_5
Definition: interface.py:469
interface.Ui_MainWindow.progress_flag
progress_flag
Signal used to tell the main thread to update training progress.
Definition: interface.py:133
interface.Ui_MainWindow.children_items
children_items
Holds children widgets for tree widget.
Definition: interface.py:92
interface.Ui_MainWindow.verticalLayout
verticalLayout
Definition: interface.py:368
interface.Ui_MainWindow.tab_classify
tab_classify
Definition: interface.py:467
interface.Ui_MainWindow.setupUi
def setupUi(self, MainWindow)
Create GUI widgets.
Definition: interface.py:172
interface.Ui_MainWindow.feat_queue
feat_queue
Stores dictionaries of every parameter until they are processed to the GUI.
Definition: interface.py:99