diff --git a/.gitignore b/.gitignore
index a05c910..1bcdeff 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
-xgtf_to_excel/result.xlsx
+xgtf_to_excel_dir/result.xlsx
+gui-for-tester-tracker/save_state_pyqt.py
+gui-for-tester-tracker/gui_for_tester_tracker
.idea/misc.xml
.idea/modules.xml
.idea/vcs.xml
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/WintreistsPractice.iml b/.idea/WintreistsPractice.iml
new file mode 100644
index 0000000..9d7de2b
--- /dev/null
+++ b/.idea/WintreistsPractice.iml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..43ad0d4
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..110c2ab
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 8e4b0bb..c9c5d7c 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,7 +1,9 @@
{
- "python.testing.pytestArgs": [
- "xgtf_to_excel"
- ],
- "python.testing.unittestEnabled": false,
- "python.testing.pytestEnabled": true
-}
\ No newline at end of file
+ "python.testing.pytestArgs": ["xgtf_to_excel"],
+ "python.testing.unittestEnabled": false,
+ "python.testing.pytestEnabled": true,
+ "[python]": {
+ "editor.defaultFormatter": "ms-python.autopep8"
+ },
+ "python.formatting.provider": "none"
+}
diff --git a/gui-for-tester-tracker/__pycache__/gui.cpython-310.pyc b/gui-for-tester-tracker/__pycache__/gui.cpython-310.pyc
new file mode 100644
index 0000000..7315f81
Binary files /dev/null and b/gui-for-tester-tracker/__pycache__/gui.cpython-310.pyc differ
diff --git a/gui-for-tester-tracker/__pycache__/tester.cpython-310.pyc b/gui-for-tester-tracker/__pycache__/tester.cpython-310.pyc
new file mode 100644
index 0000000..5cbfbe2
Binary files /dev/null and b/gui-for-tester-tracker/__pycache__/tester.cpython-310.pyc differ
diff --git a/gui-for-tester-tracker/__pycache__/tester.cpython-311.pyc b/gui-for-tester-tracker/__pycache__/tester.cpython-311.pyc
new file mode 100644
index 0000000..1b34c26
Binary files /dev/null and b/gui-for-tester-tracker/__pycache__/tester.cpython-311.pyc differ
diff --git a/gui-for-tester-tracker/compile.bat b/gui-for-tester-tracker/compile.bat
new file mode 100644
index 0000000..443f682
--- /dev/null
+++ b/gui-for-tester-tracker/compile.bat
@@ -0,0 +1 @@
+C:\Users\User\PycharmProjects\WintreistsPractice\venv\Scripts\python.exe -m PyQt6.uic.pyuic C:\Users\User\PycharmProjects\WintreistsPractice\gui-for-tester-tracker\gui.ui -o C:\Users\User\PycharmProjects\WintreistsPractice\gui-for-tester-tracker\gui.py
\ No newline at end of file
diff --git a/gui-for-tester-tracker/gui.py b/gui-for-tester-tracker/gui.py
new file mode 100644
index 0000000..82262cf
--- /dev/null
+++ b/gui-for-tester-tracker/gui.py
@@ -0,0 +1,263 @@
+# Form implementation generated from reading ui file 'C:\Users\User\PycharmProjects\WintreistsPractice\gui-for-tester-tracker\gui.ui'
+#
+# Created by: PyQt6 UI code generator 6.5.2
+#
+# WARNING: Any manual changes made to this file will be lost when pyuic6 is
+# run again. Do not edit this file unless you know what you are doing.
+
+
+from PyQt6 import QtCore, QtGui, QtWidgets
+
+
+class Ui_MainWindow(object):
+ def setupUi(self, MainWindow):
+ MainWindow.setObjectName("MainWindow")
+ MainWindow.resize(589, 407)
+ MainWindow.setMinimumSize(QtCore.QSize(0, 0))
+ self.centralwidget = QtWidgets.QWidget(parent=MainWindow)
+ self.centralwidget.setObjectName("centralwidget")
+ self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
+ self.verticalLayout.setObjectName("verticalLayout")
+ self.tabWidget = QtWidgets.QTabWidget(parent=self.centralwidget)
+ self.tabWidget.setLayoutDirection(QtCore.Qt.LayoutDirection.LeftToRight)
+ self.tabWidget.setObjectName("tabWidget")
+ self.tab = QtWidgets.QWidget()
+ self.tab.setObjectName("tab")
+ self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.tab)
+ self.verticalLayout_2.setObjectName("verticalLayout_2")
+ self.groupBox = QtWidgets.QGroupBox(parent=self.tab)
+ self.groupBox.setTitle("")
+ self.groupBox.setCheckable(False)
+ self.groupBox.setObjectName("groupBox")
+ self.gridLayout = QtWidgets.QGridLayout(self.groupBox)
+ self.gridLayout.setObjectName("gridLayout")
+ self.verticalLayout_3 = QtWidgets.QVBoxLayout()
+ self.verticalLayout_3.setObjectName("verticalLayout_3")
+ self.label = QtWidgets.QLabel(parent=self.groupBox)
+ self.label.setObjectName("label")
+ self.verticalLayout_3.addWidget(self.label)
+ self.label_2 = QtWidgets.QLabel(parent=self.groupBox)
+ self.label_2.setObjectName("label_2")
+ self.verticalLayout_3.addWidget(self.label_2)
+ self.label_3 = QtWidgets.QLabel(parent=self.groupBox)
+ self.label_3.setObjectName("label_3")
+ self.verticalLayout_3.addWidget(self.label_3)
+ self.label_5 = QtWidgets.QLabel(parent=self.groupBox)
+ self.label_5.setObjectName("label_5")
+ self.verticalLayout_3.addWidget(self.label_5)
+ self.gridLayout.addLayout(self.verticalLayout_3, 0, 0, 1, 1)
+ self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_3.setObjectName("horizontalLayout_3")
+ self.label_4 = QtWidgets.QLabel(parent=self.groupBox)
+ self.label_4.setObjectName("label_4")
+ self.horizontalLayout_3.addWidget(self.label_4)
+ self.gridLayout.addLayout(self.horizontalLayout_3, 1, 0, 1, 1)
+ self.gridLayout_5 = QtWidgets.QGridLayout()
+ self.gridLayout_5.setObjectName("gridLayout_5")
+ self.lineEdit_to_networks_dir = QtWidgets.QLineEdit(parent=self.groupBox)
+ self.lineEdit_to_networks_dir.setReadOnly(True)
+ self.lineEdit_to_networks_dir.setObjectName("lineEdit_to_networks_dir")
+ self.gridLayout_5.addWidget(self.lineEdit_to_networks_dir, 0, 0, 1, 1)
+ self.toolButton_select_markup_dir = QtWidgets.QToolButton(parent=self.groupBox)
+ self.toolButton_select_markup_dir.setObjectName("toolButton_select_markup_dir")
+ self.gridLayout_5.addWidget(self.toolButton_select_markup_dir, 1, 1, 1, 1)
+ self.lineEdit_path_to_epf_file = QtWidgets.QLineEdit(parent=self.groupBox)
+ self.lineEdit_path_to_epf_file.setReadOnly(True)
+ self.lineEdit_path_to_epf_file.setObjectName("lineEdit_path_to_epf_file")
+ self.gridLayout_5.addWidget(self.lineEdit_path_to_epf_file, 3, 0, 1, 1)
+ self.toolButton_select_path_to_epf_file = QtWidgets.QToolButton(parent=self.groupBox)
+ self.toolButton_select_path_to_epf_file.setObjectName("toolButton_select_path_to_epf_file")
+ self.gridLayout_5.addWidget(self.toolButton_select_path_to_epf_file, 3, 1, 1, 1)
+ self.lineEdit_to_markup_dir = QtWidgets.QLineEdit(parent=self.groupBox)
+ self.lineEdit_to_markup_dir.setReadOnly(True)
+ self.lineEdit_to_markup_dir.setObjectName("lineEdit_to_markup_dir")
+ self.gridLayout_5.addWidget(self.lineEdit_to_markup_dir, 1, 0, 1, 1)
+ self.toolButton_select_result_dir = QtWidgets.QToolButton(parent=self.groupBox)
+ self.toolButton_select_result_dir.setObjectName("toolButton_select_result_dir")
+ self.gridLayout_5.addWidget(self.toolButton_select_result_dir, 2, 1, 1, 1)
+ self.lineEdit_to_result_dir = QtWidgets.QLineEdit(parent=self.groupBox)
+ self.lineEdit_to_result_dir.setReadOnly(True)
+ self.lineEdit_to_result_dir.setObjectName("lineEdit_to_result_dir")
+ self.gridLayout_5.addWidget(self.lineEdit_to_result_dir, 2, 0, 1, 1)
+ self.toolButton_select_networks_dir = QtWidgets.QToolButton(parent=self.groupBox)
+ self.toolButton_select_networks_dir.setObjectName("toolButton_select_networks_dir")
+ self.gridLayout_5.addWidget(self.toolButton_select_networks_dir, 0, 1, 1, 1)
+ self.gridLayout.addLayout(self.gridLayout_5, 0, 1, 1, 1)
+ self.verticalLayout_4 = QtWidgets.QVBoxLayout()
+ self.verticalLayout_4.setObjectName("verticalLayout_4")
+ self.listWidget_list_classes = QtWidgets.QListWidget(parent=self.groupBox)
+ self.listWidget_list_classes.setSelectionRectVisible(False)
+ self.listWidget_list_classes.setObjectName("listWidget_list_classes")
+ self.verticalLayout_4.addWidget(self.listWidget_list_classes)
+ self.horizontalLayout_6 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_6.setObjectName("horizontalLayout_6")
+ self.label_13 = QtWidgets.QLabel(parent=self.groupBox)
+ self.label_13.setObjectName("label_13")
+ self.horizontalLayout_6.addWidget(self.label_13)
+ self.lineEdit_add_new_class = QtWidgets.QLineEdit(parent=self.groupBox)
+ self.lineEdit_add_new_class.setObjectName("lineEdit_add_new_class")
+ self.horizontalLayout_6.addWidget(self.lineEdit_add_new_class)
+ self.toolButton_add_class = QtWidgets.QToolButton(parent=self.groupBox)
+ self.toolButton_add_class.setObjectName("toolButton_add_class")
+ self.horizontalLayout_6.addWidget(self.toolButton_add_class)
+ self.verticalLayout_4.addLayout(self.horizontalLayout_6)
+ self.gridLayout.addLayout(self.verticalLayout_4, 1, 1, 1, 1)
+ self.verticalLayout_2.addWidget(self.groupBox)
+ self.tabWidget.addTab(self.tab, "")
+ self.tab_2 = QtWidgets.QWidget()
+ self.tab_2.setObjectName("tab_2")
+ self.verticalLayout_6 = QtWidgets.QVBoxLayout(self.tab_2)
+ self.verticalLayout_6.setObjectName("verticalLayout_6")
+ self.groupBox_2 = QtWidgets.QGroupBox(parent=self.tab_2)
+ self.groupBox_2.setObjectName("groupBox_2")
+ self.verticalLayout_7 = QtWidgets.QVBoxLayout(self.groupBox_2)
+ self.verticalLayout_7.setObjectName("verticalLayout_7")
+ self.gridLayout_3 = QtWidgets.QGridLayout()
+ self.gridLayout_3.setObjectName("gridLayout_3")
+ self.lineEdit_path_to_siamese_neural_network = QtWidgets.QLineEdit(parent=self.groupBox_2)
+ self.lineEdit_path_to_siamese_neural_network.setReadOnly(True)
+ self.lineEdit_path_to_siamese_neural_network.setObjectName("lineEdit_path_to_siamese_neural_network")
+ self.gridLayout_3.addWidget(self.lineEdit_path_to_siamese_neural_network, 0, 1, 1, 1)
+ self.label_10 = QtWidgets.QLabel(parent=self.groupBox_2)
+ self.label_10.setObjectName("label_10")
+ self.gridLayout_3.addWidget(self.label_10, 0, 0, 1, 1)
+ self.toolButton_select_path_to_siamese_neural_network = QtWidgets.QToolButton(parent=self.groupBox_2)
+ self.toolButton_select_path_to_siamese_neural_network.setObjectName("toolButton_select_path_to_siamese_neural_network")
+ self.gridLayout_3.addWidget(self.toolButton_select_path_to_siamese_neural_network, 0, 2, 1, 1)
+ self.verticalLayout_7.addLayout(self.gridLayout_3)
+ self.verticalLayout_8 = QtWidgets.QVBoxLayout()
+ self.verticalLayout_8.setObjectName("verticalLayout_8")
+ self.checkBox_hide_stationary_objects = QtWidgets.QCheckBox(parent=self.groupBox_2)
+ self.checkBox_hide_stationary_objects.setObjectName("checkBox_hide_stationary_objects")
+ self.verticalLayout_8.addWidget(self.checkBox_hide_stationary_objects)
+ self.gridLayout_4 = QtWidgets.QGridLayout()
+ self.gridLayout_4.setObjectName("gridLayout_4")
+ self.label_7 = QtWidgets.QLabel(parent=self.groupBox_2)
+ self.label_7.setObjectName("label_7")
+ self.gridLayout_4.addWidget(self.label_7, 0, 0, 1, 1)
+ self.lineEdit_sensitivity_detector_stationary_objects = QtWidgets.QLineEdit(parent=self.groupBox_2)
+ self.lineEdit_sensitivity_detector_stationary_objects.setObjectName("lineEdit_sensitivity_detector_stationary_objects")
+ self.gridLayout_4.addWidget(self.lineEdit_sensitivity_detector_stationary_objects, 0, 1, 1, 1)
+ self.verticalLayout_8.addLayout(self.gridLayout_4)
+ self.verticalLayout_7.addLayout(self.verticalLayout_8)
+ self.gridLayout_2 = QtWidgets.QGridLayout()
+ self.gridLayout_2.setObjectName("gridLayout_2")
+ self.label_8 = QtWidgets.QLabel(parent=self.groupBox_2)
+ self.label_8.setObjectName("label_8")
+ self.gridLayout_2.addWidget(self.label_8, 1, 0, 1, 1)
+ self.lineEdit_minimum_number_of_triggers = QtWidgets.QLineEdit(parent=self.groupBox_2)
+ self.lineEdit_minimum_number_of_triggers.setObjectName("lineEdit_minimum_number_of_triggers")
+ self.gridLayout_2.addWidget(self.lineEdit_minimum_number_of_triggers, 1, 1, 1, 1)
+ self.lineEdit_fps = QtWidgets.QLineEdit(parent=self.groupBox_2)
+ self.lineEdit_fps.setObjectName("lineEdit_fps")
+ self.gridLayout_2.addWidget(self.lineEdit_fps, 0, 1, 1, 1)
+ self.label_6 = QtWidgets.QLabel(parent=self.groupBox_2)
+ self.label_6.setObjectName("label_6")
+ self.gridLayout_2.addWidget(self.label_6, 0, 0, 1, 1)
+ self.label_9 = QtWidgets.QLabel(parent=self.groupBox_2)
+ self.label_9.setObjectName("label_9")
+ self.gridLayout_2.addWidget(self.label_9, 2, 0, 1, 1)
+ self.lineEdit_confidence_threshold = QtWidgets.QLineEdit(parent=self.groupBox_2)
+ self.lineEdit_confidence_threshold.setObjectName("lineEdit_confidence_threshold")
+ self.gridLayout_2.addWidget(self.lineEdit_confidence_threshold, 2, 1, 1, 1)
+ self.verticalLayout_7.addLayout(self.gridLayout_2)
+ self.verticalLayout_6.addWidget(self.groupBox_2)
+ self.groupBox_4 = QtWidgets.QGroupBox(parent=self.tab_2)
+ self.groupBox_4.setObjectName("groupBox_4")
+ self.verticalLayout_9 = QtWidgets.QVBoxLayout(self.groupBox_4)
+ self.verticalLayout_9.setObjectName("verticalLayout_9")
+ self.checkBox_use_MOT = QtWidgets.QCheckBox(parent=self.groupBox_4)
+ self.checkBox_use_MOT.setObjectName("checkBox_use_MOT")
+ self.verticalLayout_9.addWidget(self.checkBox_use_MOT)
+ self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_2.setObjectName("horizontalLayout_2")
+ self.label_11 = QtWidgets.QLabel(parent=self.groupBox_4)
+ self.label_11.setEnabled(True)
+ self.label_11.setObjectName("label_11")
+ self.horizontalLayout_2.addWidget(self.label_11)
+ self.lineEdit_IOU_threshold = QtWidgets.QLineEdit(parent=self.groupBox_4)
+ self.lineEdit_IOU_threshold.setEnabled(True)
+ self.lineEdit_IOU_threshold.setObjectName("lineEdit_IOU_threshold")
+ self.horizontalLayout_2.addWidget(self.lineEdit_IOU_threshold)
+ self.verticalLayout_9.addLayout(self.horizontalLayout_2)
+ self.verticalLayout_6.addWidget(self.groupBox_4)
+ self.tabWidget.addTab(self.tab_2, "")
+ self.verticalLayout.addWidget(self.tabWidget)
+ self.horizontalLayout = QtWidgets.QHBoxLayout()
+ self.horizontalLayout.setObjectName("horizontalLayout")
+ spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
+ self.horizontalLayout.addItem(spacerItem)
+ self.pushButton_start_work = QtWidgets.QPushButton(parent=self.centralwidget)
+ self.pushButton_start_work.setEnabled(False)
+ self.pushButton_start_work.setObjectName("pushButton_start_work")
+ self.horizontalLayout.addWidget(self.pushButton_start_work)
+ spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Minimum)
+ self.horizontalLayout.addItem(spacerItem1)
+ self.verticalLayout.addLayout(self.horizontalLayout)
+ MainWindow.setCentralWidget(self.centralwidget)
+ self.statusbar = QtWidgets.QStatusBar(parent=MainWindow)
+ self.statusbar.setObjectName("statusbar")
+ MainWindow.setStatusBar(self.statusbar)
+ self.menubar = QtWidgets.QMenuBar(parent=MainWindow)
+ self.menubar.setGeometry(QtCore.QRect(0, 0, 589, 21))
+ self.menubar.setObjectName("menubar")
+ self.menu = QtWidgets.QMenu(parent=self.menubar)
+ self.menu.setObjectName("menu")
+ self.menu_2 = QtWidgets.QMenu(parent=self.menu)
+ self.menu_2.setObjectName("menu_2")
+ MainWindow.setMenuBar(self.menubar)
+ self.action_save_config = QtGui.QAction(parent=MainWindow)
+ self.action_save_config.setObjectName("action_save_config")
+ self.action_load_config = QtGui.QAction(parent=MainWindow)
+ self.action_load_config.setObjectName("action_load_config")
+ self.action_style_1 = QtGui.QAction(parent=MainWindow)
+ self.action_style_1.setObjectName("action_style_1")
+ self.menu.addAction(self.action_save_config)
+ self.menu.addAction(self.action_load_config)
+ self.menu.addAction(self.menu_2.menuAction())
+ self.menubar.addAction(self.menu.menuAction())
+ self.label_4.setBuddy(self.label_4)
+
+ self.retranslateUi(MainWindow)
+ self.tabWidget.setCurrentIndex(0)
+ QtCore.QMetaObject.connectSlotsByName(MainWindow)
+
+ def retranslateUi(self, MainWindow):
+ _translate = QtCore.QCoreApplication.translate
+ MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
+ self.label.setText(_translate("MainWindow", "Путь к папке с сетями"))
+ self.label_2.setText(_translate("MainWindow", "Путь к папке с разметкой"))
+ self.label_3.setText(_translate("MainWindow", "Путь для сохранения результатов теста"))
+ self.label_5.setText(_translate("MainWindow", "Путь к .epf файлу"))
+ self.label_4.setText(_translate("MainWindow", "Список тестируемых классов:"))
+ self.toolButton_select_markup_dir.setText(_translate("MainWindow", "..."))
+ self.toolButton_select_path_to_epf_file.setText(_translate("MainWindow", "..."))
+ self.toolButton_select_result_dir.setText(_translate("MainWindow", "..."))
+ self.lineEdit_to_result_dir.setText(_translate("MainWindow", "/results"))
+ self.toolButton_select_networks_dir.setText(_translate("MainWindow", "..."))
+ self.label_13.setText(_translate("MainWindow", "Добавить новый класс:"))
+ self.toolButton_add_class.setText(_translate("MainWindow", "+"))
+ self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "Параметры тестера"))
+ self.groupBox_2.setTitle(_translate("MainWindow", "Параметры трекера"))
+ self.label_10.setText(_translate("MainWindow", "Путь к сиамской нейронной сети"))
+ self.toolButton_select_path_to_siamese_neural_network.setText(_translate("MainWindow", "..."))
+ self.checkBox_hide_stationary_objects.setText(_translate("MainWindow", "Скрывать неподвижные объекты"))
+ self.label_7.setText(_translate("MainWindow", "Чувствительность детектора неподвижных объектов"))
+ self.lineEdit_sensitivity_detector_stationary_objects.setText(_translate("MainWindow", "0.5"))
+ self.label_8.setText(_translate("MainWindow", "Минимальное число срабатываний"))
+ self.lineEdit_minimum_number_of_triggers.setText(_translate("MainWindow", "6"))
+ self.lineEdit_fps.setText(_translate("MainWindow", "13"))
+ self.label_6.setText(_translate("MainWindow", "Количество кадров трекера (FPS):"))
+ self.label_9.setText(_translate("MainWindow", "Доверительный порог"))
+ self.lineEdit_confidence_threshold.setText(_translate("MainWindow", "0.3"))
+ self.groupBox_4.setTitle(_translate("MainWindow", "Использование МОТ"))
+ self.checkBox_use_MOT.setText(_translate("MainWindow", "Использовать MOT вместо ViPER"))
+ self.label_11.setText(_translate("MainWindow", "IOU порог"))
+ self.lineEdit_IOU_threshold.setText(_translate("MainWindow", "0.3"))
+ self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("MainWindow", "Параметры трекера"))
+ self.pushButton_start_work.setText(_translate("MainWindow", "Запустить тестирование"))
+ self.menu.setTitle(_translate("MainWindow", "Меню"))
+ self.menu_2.setTitle(_translate("MainWindow", "Стили"))
+ self.action_save_config.setText(_translate("MainWindow", "Сохранить"))
+ self.action_load_config.setText(_translate("MainWindow", "Загрузить"))
+ self.action_style_1.setText(_translate("MainWindow", "Стиль 1"))
diff --git a/gui-for-tester-tracker/gui.ui b/gui-for-tester-tracker/gui.ui
new file mode 100644
index 0000000..23e2920
--- /dev/null
+++ b/gui-for-tester-tracker/gui.ui
@@ -0,0 +1,438 @@
+
+
+ MainWindow
+
+
+
+ 0
+ 0
+ 589
+ 407
+
+
+
+
+ 0
+ 0
+
+
+
+ MainWindow
+
+
+
+ -
+
+
+ Qt::LeftToRight
+
+
+ 0
+
+
+
+ Параметры тестера
+
+
+
-
+
+
+
+
+
+ false
+
+
+
-
+
+
-
+
+
+ Путь к папке с сетями
+
+
+
+ -
+
+
+ Путь к папке с разметкой
+
+
+
+ -
+
+
+ Путь для сохранения результатов теста
+
+
+
+ -
+
+
+ Путь к .epf файлу
+
+
+
+
+
+ -
+
+
-
+
+
+ Список тестируемых классов:
+
+
+ label_4
+
+
+
+
+
+ -
+
+
-
+
+
+ true
+
+
+
+ -
+
+
+ ...
+
+
+
+ -
+
+
+ true
+
+
+
+ -
+
+
+ ...
+
+
+
+ -
+
+
+ true
+
+
+
+ -
+
+
+ ...
+
+
+
+ -
+
+
+ /results
+
+
+ true
+
+
+
+ -
+
+
+ ...
+
+
+
+
+
+ -
+
+
-
+
+
+ false
+
+
+
+ -
+
+
-
+
+
+ Добавить новый класс:
+
+
+
+ -
+
+
+ -
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Параметры трекера
+
+
+ -
+
+
+ Параметры трекера
+
+
+
-
+
+
-
+
+
+ true
+
+
+
+ -
+
+
+ Путь к сиамской нейронной сети
+
+
+
+ -
+
+
+ ...
+
+
+
+
+
+ -
+
+
-
+
+
+ Скрывать неподвижные объекты
+
+
+
+ -
+
+
-
+
+
+ Чувствительность детектора неподвижных объектов
+
+
+
+ -
+
+
+ 0.5
+
+
+
+
+
+
+
+ -
+
+
-
+
+
+ Минимальное число срабатываний
+
+
+
+ -
+
+
+ 6
+
+
+
+ -
+
+
+ 13
+
+
+
+ -
+
+
+ Количество кадров трекера (FPS):
+
+
+
+ -
+
+
+ Доверительный порог
+
+
+
+ -
+
+
+ 0.3
+
+
+
+
+
+
+
+
+ -
+
+
+ Использование МОТ
+
+
+
-
+
+
+ Использовать MOT вместо ViPER
+
+
+
+ -
+
+
-
+
+
+ true
+
+
+ IOU порог
+
+
+
+ -
+
+
+ true
+
+
+ 0.3
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ false
+
+
+ Запустить тестирование
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QSizePolicy::Minimum
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+
+
+
+
+
+ Сохранить
+
+
+
+
+ Загрузить
+
+
+
+
+ Стиль 1
+
+
+
+
+
+
diff --git a/gui-for-tester-tracker/gui_for_tester_tracker.ini b/gui-for-tester-tracker/gui_for_tester_tracker.ini
new file mode 100644
index 0000000..38cc7d9
--- /dev/null
+++ b/gui-for-tester-tracker/gui_for_tester_tracker.ini
@@ -0,0 +1,14 @@
+[General]
+lineEdit_confidence_threshold=0.3
+lineEdit_minimum_number_of_triggers=6
+lineEdit_IOU_threshold=0.3
+lineEdit_sensitivity_detector_stationary_objects=0.5
+lineEdit_fps=13
+lineEdit_path_to_siamese_neural_network=
+lineEdit_path_to_epf_file=
+lineEdit_to_markup_dir=
+lineEdit_to_networks_dir=
+lineEdit_to_result_dir=/results
+checkBox_hide_stationary_objects=
+checkBox_use_MOT=
+listWidget_list_classes=@Variant(\0\0\0\b\0\0\0\x1\0\0\0\n\0H\0u\0m\0\x61\0n\0\0\0\x1\x1)
diff --git a/gui-for-tester-tracker/gui_tracker.py b/gui-for-tester-tracker/gui_tracker.py
new file mode 100644
index 0000000..a96ca20
--- /dev/null
+++ b/gui-for-tester-tracker/gui_tracker.py
@@ -0,0 +1,239 @@
+import sys
+import os
+from functools import partial
+from pathlib import Path
+from typing import Callable
+from PyQt6.QtWidgets import (
+ QLineEdit, QToolButton, QCheckBox,
+ QApplication, QMainWindow, QFileDialog,
+ QHBoxLayout, QWidget, QListWidgetItem,
+ QSpacerItem, QSizePolicy, QMessageBox,
+)
+from PyQt6 import QtGui
+from PyQt6.QtCore import QSettings, Qt, QSize
+from tester import main as testerTrackerMain
+from gui import Ui_MainWindow
+
+
+class MainWindow(QMainWindow, Ui_MainWindow):
+ # Сигналы
+ # onProgressWork = pyqtSignal(int, int, str, str)
+ # ~~~~~~~
+ def __init__(self):
+ super(MainWindow, self).__init__()
+ self.setupUi(self)
+ self.add_class(lambda: "Human", True, False)
+ # Меню
+ # Конфиг
+ self.action_save_config.triggered.connect(self.save_state)
+ self.action_load_config.triggered.connect(self.load_state)
+ # ~~~~~
+ # Сигналы
+ self.toolButton_select_markup_dir.clicked.connect(
+ partial(self.open_file_explorer, self.lineEdit_to_markup_dir, "Выберите путь к папке с разметкой"))
+ self.toolButton_select_networks_dir.clicked.connect(
+ partial(self.open_file_explorer, self.lineEdit_to_networks_dir, "Выберите путь к папке с сетями"))
+ self.toolButton_select_result_dir.clicked.connect(
+ partial(self.open_file_explorer, self.lineEdit_to_result_dir, "Выберите путь к папке для сохранения результатов"))
+ self.toolButton_select_path_to_siamese_neural_network.clicked.connect(
+ partial(self.open_file_location, self.lineEdit_path_to_siamese_neural_network, "Выберите путь к сиамской нейронной сети"))
+ self.toolButton_select_path_to_epf_file.clicked.connect(
+ partial(self.open_file_location, self.lineEdit_path_to_epf_file, "Выберите путь к .epf файлу", "*.epf"))
+ self.toolButton_add_class.clicked.connect(
+ partial(self.add_class, self.lineEdit_add_new_class.text, True, True))
+
+ self.lineEdit_add_new_class.returnPressed.connect(
+ partial(self.add_class, self.lineEdit_add_new_class.text, True, True))
+ self.lineEdit_to_networks_dir.textChanged.connect(
+ self.all_needed_line_edits_are_not_empty)
+ self.lineEdit_to_markup_dir.textChanged.connect(
+ self.all_needed_line_edits_are_not_empty)
+
+ self.pushButton_start_work.clicked.connect(self.start_work)
+
+ # Стили
+ for filename in Path(__file__).parent.glob("./styles/*.qss"):
+ action = QtGui.QAction(
+ filename.name.rpartition(".")[0], self)
+ action.triggered.connect(
+ partial(self.set_style, filename))
+ self.menu_2.addAction(action)
+
+ def set_style(self, style_filename: Path):
+ self.setStyleSheet(style_filename.read_text())
+
+ def all_needed_line_edits_are_not_empty(self):
+ allNeededLineEdits = [
+ self.lineEdit_to_networks_dir,
+ self.lineEdit_to_markup_dir,
+ ]
+ is_filled = all(lineEdit.text() for lineEdit in allNeededLineEdits)
+ self.pushButton_start_work.setEnabled(is_filled)
+
+ def open_file_explorer(self, input_directory: QLineEdit, text: str = None):
+ text = text if text else "Выберите директорию"
+ directory = QFileDialog.getExistingDirectory(self, text)
+ if directory:
+ input_directory.setText(directory)
+
+ def open_file_location(self, lineEdit_file_location: QLineEdit, text: str = None, filter: str = None):
+ text = text if text else "Выберите файл"
+ filter = filter if filter else None
+ file_location = QFileDialog.getOpenFileName(self, text, filter=filter)
+ if file_location[0]:
+ lineEdit_file_location.setText(file_location[0])
+
+ def start_work(self):
+ testing_classes = []
+ for index in range(self.listWidget_list_classes.count()):
+ item = self.listWidget_list_classes.item(index)
+ widget: ListItemClass = self.listWidget_list_classes.itemWidget(
+ item)
+ if widget.checkbox.isChecked():
+ testing_classes.append(widget.checkbox.text())
+ if len(testing_classes) == 0:
+ QMessageBox.critical(
+ self, "Ошибка", "Вы пытаетесь запустить тестирование без активных классов!")
+ return True
+ self.hide()
+ testerTrackerMain(
+ netsDir=self.lineEdit_to_networks_dir.text(),
+ videosDir=self.lineEdit_to_markup_dir.text(),
+ resDir=self.lineEdit_to_result_dir.text(),
+ targetClasses=testing_classes,
+ path2Epf=self.lineEdit_path_to_epf_file.text(),
+ useMot=self.checkBox_use_MOT.isChecked(),
+ motIouThr=float(self.lineEdit_IOU_threshold.text()),
+ framerate=int(self.lineEdit_fps.text()),
+ hideStillObjects=self.checkBox_hide_stationary_objects.isChecked(),
+ hideStillObjectsSensitivity=float(
+ self.lineEdit_sensitivity_detector_stationary_objects.text()),
+ minDetectionTriggers=int(
+ self.lineEdit_minimum_number_of_triggers.text()),
+ confThreshold=float(self.lineEdit_confidence_threshold.text()),
+ siameseFile=self.lineEdit_path_to_siamese_neural_network.text(),
+ # onProgressCallback=self.onProgressWork.emit,
+ )
+ self.show()
+
+ def load_state(self):
+ path_to_settings = QFileDialog.getOpenFileName(
+ self, 'Выберите файл настроек')
+ if path_to_settings[0]:
+ self.settings = QSettings(
+ path_to_settings[0], QSettings.Format.IniFormat)
+
+ self.lineEdit_to_markup_dir.setText(
+ self.settings.value(self.lineEdit_to_markup_dir.objectName(), ""))
+ self.lineEdit_to_networks_dir.setText(
+ self.settings.value(self.lineEdit_to_networks_dir.objectName(), ""))
+ self.lineEdit_to_result_dir.setText(
+ self.settings.value(self.lineEdit_to_result_dir.objectName(), "/results"))
+ self.lineEdit_path_to_siamese_neural_network.setText(
+ self.settings.value(self.lineEdit_path_to_siamese_neural_network.objectName(), ""))
+ self.lineEdit_path_to_epf_file.setText(
+ self.settings.value(self.lineEdit_path_to_epf_file.objectName(), ""))
+ self.lineEdit_confidence_threshold.setText(
+ self.settings.value(self.lineEdit_confidence_threshold.objectName(), "0.3"))
+ self.lineEdit_minimum_number_of_triggers.setText(
+ self.settings.value(self.lineEdit_minimum_number_of_triggers.objectName(), "6"))
+ self.lineEdit_IOU_threshold.setText(
+ self.settings.value(self.lineEdit_IOU_threshold.objectName(), "0.3"))
+ self.lineEdit_sensitivity_detector_stationary_objects.setText(
+ self.settings.value(self.lineEdit_sensitivity_detector_stationary_objects.objectName(), "0.5"))
+ self.lineEdit_fps.setText(
+ self.settings.value(self.lineEdit_fps.objectName(), "13"))
+
+ self.checkBox_hide_stationary_objects.setChecked(
+ bool(self.settings.value(self.checkBox_hide_stationary_objects.objectName(), False)))
+ self.checkBox_use_MOT.setChecked(
+ bool(self.settings.value(self.checkBox_use_MOT.objectName(), False)))
+
+ self.listWidget_list_classes.clear()
+ items = self.settings.value(self.listWidget_list_classes.objectName(), {
+ "Human": True
+ })
+ for class_name, check_state in items.items():
+ self.add_class(lambda: class_name, check_state)
+
+ def save_state(self):
+ path_to_settings = QFileDialog.getSaveFileName(
+ self, "Выберите путь\файл настроек")
+ if path_to_settings[0]:
+ self.settings = QSettings(
+ path_to_settings[0], QSettings.Format.IniFormat)
+ self.settings.setValue(self.lineEdit_confidence_threshold.objectName(),
+ self.lineEdit_confidence_threshold.text())
+ self.settings.setValue(self.lineEdit_minimum_number_of_triggers.objectName(),
+ self.lineEdit_minimum_number_of_triggers.text())
+ self.settings.setValue(self.lineEdit_IOU_threshold.objectName(),
+ self.lineEdit_IOU_threshold.text())
+ self.settings.setValue(self.lineEdit_sensitivity_detector_stationary_objects.objectName(),
+ self.lineEdit_sensitivity_detector_stationary_objects.text())
+ self.settings.setValue(self.lineEdit_fps.objectName(),
+ self.lineEdit_fps.text())
+ self.settings.setValue(self.lineEdit_path_to_siamese_neural_network.objectName(),
+ self.lineEdit_path_to_siamese_neural_network.text())
+ self.settings.setValue(self.lineEdit_path_to_epf_file.objectName(),
+ self.lineEdit_path_to_epf_file.text())
+ self.settings.setValue(self.lineEdit_to_markup_dir.objectName(),
+ self.lineEdit_to_markup_dir.text())
+ self.settings.setValue(self.lineEdit_to_networks_dir.objectName(),
+ self.lineEdit_to_networks_dir.text())
+ self.settings.setValue(self.lineEdit_to_result_dir.objectName(),
+ self.lineEdit_to_result_dir.text())
+ self.settings.setValue(self.checkBox_hide_stationary_objects.objectName(),
+ True if self.checkBox_hide_stationary_objects.checkState() == Qt.CheckState.Checked else '')
+ self.settings.setValue(self.checkBox_use_MOT.objectName(),
+ True if self.checkBox_use_MOT.checkState() == Qt.CheckState.Checked else '')
+ classes = {}
+ for index in range(self.listWidget_list_classes.count()):
+ item = self.listWidget_list_classes.item(index)
+ widget: ListItemClass = self.listWidget_list_classes.itemWidget(
+ item)
+ classes[widget.checkbox.text()] = widget.checkbox.isChecked()
+ self.settings.setValue(
+ self.listWidget_list_classes.objectName(), classes)
+
+ def add_class(self, class_name: Callable[[], str], check_state, isAddedFromLineEdit=False):
+ if class_name():
+ widget = ListItemClass(class_name(), check_state)
+ list_item = QListWidgetItem()
+ list_item.setFlags(list_item.flags() & ~
+ Qt.ItemFlag.ItemIsSelectable)
+ list_item.setSizeHint(QSize(0, 40))
+ self.listWidget_list_classes.addItem(list_item)
+ self.listWidget_list_classes.setItemWidget(list_item, widget)
+ widget.toolButton.clicked.connect(
+ partial(self.remove_class, list_item))
+ if isAddedFromLineEdit:
+ self.lineEdit_add_new_class.setText("")
+
+ def remove_class(self, item):
+ self.listWidget_list_classes.takeItem(
+ self.listWidget_list_classes.row(item))
+
+
+class ListItemClass(QWidget):
+ def __init__(self, class_name, check_state):
+ super().__init__()
+ self.layout = QHBoxLayout(self)
+ self.checkbox = QCheckBox(class_name)
+ self.checkbox.setChecked(check_state)
+ self.toolButton = QToolButton()
+ self.toolButton.setText('-')
+ self.spacer = QSpacerItem(
+ 0, 0, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
+ self.layout.addWidget(self.checkbox)
+ self.layout.addItem(self.spacer)
+ self.layout.addWidget(self.toolButton)
+
+
+if __name__ == '__main__':
+ _path = Path(__file__).parent
+ app = QApplication(sys.argv)
+ app.setWindowIcon(QtGui.QIcon(_path.joinpath('icon.png').__str__()))
+ window = MainWindow()
+ window.setWindowTitle("GUI for tester tracker")
+ window.show()
+ app.exec()
diff --git a/gui-for-tester-tracker/icon.png b/gui-for-tester-tracker/icon.png
new file mode 100644
index 0000000..8c715c8
Binary files /dev/null and b/gui-for-tester-tracker/icon.png differ
diff --git "a/gui-for-tester-tracker/styles/\320\235\320\276\321\207\320\275\320\276\320\271 \321\201\321\202\320\270\320\273\321\214.qss" "b/gui-for-tester-tracker/styles/\320\235\320\276\321\207\320\275\320\276\320\271 \321\201\321\202\320\270\320\273\321\214.qss"
new file mode 100644
index 0000000..cee7a63
--- /dev/null
+++ "b/gui-for-tester-tracker/styles/\320\235\320\276\321\207\320\275\320\276\320\271 \321\201\321\202\320\270\320\273\321\214.qss"
@@ -0,0 +1,70 @@
+QWidget {
+ background-color: #111;
+}
+
+QLabel, QCheckBox {
+ color: #aec0d4;
+ font-weight: 600;
+}
+QCheckBox {
+ background: transparent
+}
+
+QLineEdit {
+ border-radius: 8px;
+ border: 1px solid #e0e4e7;
+ padding: 5px 5px;
+ background: #baa
+}
+QLineEdit:focus {
+ border: 1px solid #d0e3ff;
+}
+
+QPushButton {
+ font-weight: 600;
+ border-radius: 8px;
+ padding: 5px 15px;
+}
+QPushButton:disabled {
+ background-color: #183055;
+ color: #999;
+ border: 1px solid #183055;
+}
+QPushButton:enabled {
+ background-color: #0e2952;
+ color: #fff;
+ border: 1px solid #0e2952;
+}
+QPushButton:hover{
+ background-color: #2d6bc9;
+ border: 3px solid #73a9f5;
+ padding: 3px;
+}
+
+QMenuBar:item {
+ padding: 1px 4px;
+ background: transparent;
+ color: #000000;
+ background-color: #fff;
+}
+QMenuBar:item:selected {
+ background-color: #afcaf3;
+}
+QMenuBar:item:pressed {
+ background-color: #5e99f3;
+}
+
+QMenu {
+ background-color: #ffffff;
+ color: #000;
+ border: 1px solid #000000;
+}
+QMenu:item {
+ font-weight: 600;
+ padding: 5px 15px;
+ padding-left: 10px;
+}
+QMenu:item:selected {
+ background-color: #5e99f3;
+}
+
diff --git "a/gui-for-tester-tracker/styles/\320\241\321\202\320\260\320\275\320\264\320\260\321\200\321\202\320\275\321\213\320\271 \321\201\321\202\320\270\320\273\321\214.qss" "b/gui-for-tester-tracker/styles/\320\241\321\202\320\260\320\275\320\264\320\260\321\200\321\202\320\275\321\213\320\271 \321\201\321\202\320\270\320\273\321\214.qss"
new file mode 100644
index 0000000..e69de29
diff --git "a/gui-for-tester-tracker/styles/\320\247\321\202\320\276-\321\202\320\276 \320\275\320\260 CSS'\320\275\320\276\320\274.qss" "b/gui-for-tester-tracker/styles/\320\247\321\202\320\276-\321\202\320\276 \320\275\320\260 CSS'\320\275\320\276\320\274.qss"
new file mode 100644
index 0000000..481e1de
--- /dev/null
+++ "b/gui-for-tester-tracker/styles/\320\247\321\202\320\276-\321\202\320\276 \320\275\320\260 CSS'\320\275\320\276\320\274.qss"
@@ -0,0 +1,69 @@
+QWidget {
+ background-color: #fff;
+}
+
+QLabel, QCheckBox {
+ color: #464d55;
+ font-weight: 600;
+}
+QCheckBox {
+ background: transparent
+}
+
+QLineEdit {
+ border-radius: 8px;
+ border: 1px solid #e0e4e7;
+ padding: 5px 5px;
+}
+QLineEdit:focus {
+ border: 1px solid #d0e3ff;
+}
+
+QPushButton {
+ font-weight: 600;
+ border-radius: 8px;
+ padding: 5px 15px;
+}
+QPushButton:disabled {
+ background-color: #183055;
+ color: #999;
+ border: 1px solid #183055;
+}
+QPushButton:enabled {
+ background-color: #0d6efd;
+ color: #fff;
+ border: 1px solid #0d6efd;
+}
+QPushButton:hover{
+ background-color: #0b5ed7;
+ border: 3px solid #9ac3fe;
+ padding: 3px;
+}
+
+QMenuBar:item {
+ padding: 1px 4px;
+ background: transparent;
+ color: #000000;
+ background-color: #fff;
+}
+QMenuBar:item:selected {
+ background-color: #afcaf3;
+}
+QMenuBar:item:pressed {
+ background-color: #5e99f3;
+}
+
+QMenu {
+ background-color: #ffffff;
+ color: #000;
+ border: 1px solid #000000;
+}
+QMenu:item {
+ font-weight: 600;
+ padding: 5px 15px;
+ padding-left: 10px;
+}
+QMenu:item:selected {
+ background-color: #5e99f3;
+}
+
diff --git a/gui-for-tester-tracker/tester.py b/gui-for-tester-tracker/tester.py
new file mode 100644
index 0000000..8258959
--- /dev/null
+++ b/gui-for-tester-tracker/tester.py
@@ -0,0 +1,31 @@
+
+
+def defaultOnProgressCallback(completed: int, all: int, curNet: str, curVideo: str):
+ if curNet and curVideo:
+ print(f"[{completed}/{all}] Work with net {curNet} and video {curVideo}")
+
+
+def defaultOnErrorCallback(message: str):
+ print(f"[E] {message}")
+
+
+from typing import Tuple, Optional, Callable
+
+def main(
+ netsDir: str,
+ videosDir: str,
+ resDir: str,
+ targetClasses: Tuple[str, ...],
+ path2Epf: Optional[str] = None,
+ useMot: bool = False,
+ motIouThr: float = 0.3,
+ framerate: int = 13,
+ hideStillObjects: bool = False,
+ hideStillObjectsSensitivity: float = 0.5,
+ minDetectionTriggers: int = 6,
+ confThreshold: float = 0.3,
+ siameseFile: str = "",
+ onProgressCallback: Callable[[int, int, str, str], None] = defaultOnProgressCallback,
+ onErrorCallback: Callable[[str], None] = defaultOnErrorCallback
+):
+ pass
diff --git a/xgtf_to_excel/__pycache__/xgtf_to_excel.cpython-311.pyc b/xgtf_to_excel/__pycache__/xgtf_to_excel.cpython-311.pyc
deleted file mode 100644
index 0e933ea..0000000
Binary files a/xgtf_to_excel/__pycache__/xgtf_to_excel.cpython-311.pyc and /dev/null differ
diff --git a/xgtf_to_excel/requirements.txt b/xgtf_to_excel/requirements.txt
deleted file mode 100644
index f1e5be5..0000000
Binary files a/xgtf_to_excel/requirements.txt and /dev/null differ
diff --git a/xgtf_to_excel/xgtf_to_excel.py b/xgtf_to_excel/xgtf_to_excel.py
deleted file mode 100644
index 4737828..0000000
--- a/xgtf_to_excel/xgtf_to_excel.py
+++ /dev/null
@@ -1,163 +0,0 @@
-import os
-import pandas as pd
-import xml.etree.ElementTree as ET
-from argparse import ArgumentParser
-import cv2
-from dataclasses import dataclass, field
-from typing import Optional, Tuple
-from math import isnan
-from numpy import sum as npsum
-
-
-# Константы
-VIPER = "{http://lamp.cfar.umd.edu/viper#}"
-VIPERDATA = "{http://lamp.cfar.umd.edu/viperdata#}"
-#
-
-def get_fps_and_numframes_from_video(work_dir:str, file_name:str) -> Tuple[float, float]:
- extensions = ["mkv", "mp4", "mpeg", "mov", "avi"]
- file_name = file_name.removesuffix(".xgtf")
- video_path = None
- for video_name in [f"{file_name}.{extension}" for extension in extensions]:
- if os.path.isfile(os.path.join(work_dir, video_name)):
- video_path = os.path.join(work_dir, video_name)
- break
- if video_path is not None:
- video = cv2.VideoCapture(video_path)
- return video.get(cv2.CAP_PROP_FRAME_COUNT), video.get(cv2.CAP_PROP_FPS)
- else:
- return 0.0, 0.0
-
-def calculate_time(time:float) -> str:
- hours = int(time // 3600)
- time -= 3600*hours
- minutes = int(time//60)
- time -= 60*minutes
- seconds = int(time)
- return f"{hours}:{minutes}:{seconds}"
-
-def get_default_value_for_class(tree:ET.ElementTree) -> str:
- default_value = "None"
- for attribute in tree.getroot().findall(f'./{VIPER}config/{VIPER}descriptor/{VIPER}attribute[@name="Class"]/{VIPER}default/{VIPERDATA}svalue'):
- default_value = attribute.attrib['value']
- return default_value
-
-def painting_errors(element):
- if isinstance(element, int):
- if element == 0:
- return 'background-color: #ff4c5b;'
- elif isinstance(element, str):
- if "None" in element or element == "":
- return 'background-color: #ff4c5b;'
- elif element == "0:0:0":
- return 'background-color: #ff4c5b;'
- elif isinstance(element, float):
- if element == 0.0:
- return 'background-color: #ff4c5b;'
- elif isnan(element):
- return 'background-color: #ff4c5b;'
- elif element is None:
- return 'background-color: #ff4c5b;'
- return None
-
-
-
-@dataclass
-class XgtfData:
- fileName:str
- objectsCount:int=0
- objectsFramesCount:int=0
- videoDuration:float=0.0
- framesCount:float=0.0
- classes:Optional[set[Optional[str]]]=field(default_factory=set)
-
- def to_excel(self) -> list:
- return [self.fileName,
- self.objectsCount,
- calculate_time(self.videoDuration),
- self.framesCount,
- self.objectsFramesCount/self.framesCount if self.framesCount != 0 else 0.0,
- ",".join(self.classes)]
- pass
-
-@dataclass
-class AllXgtfData:
- _xgtfData:list[XgtfData] = field(default_factory=list)
-
- def to_excel(self) -> list:
- statistics = XgtfData("Итого")
- statistics.objectsCount, statistics.videoDuration, statistics.framesCount, statistics.objectsFramesCount = npsum([[xgtf.objectsFramesCount, xgtf.videoDuration, xgtf.framesCount, xgtf.objectsFramesCount] for xgtf in self._xgtfData], axis=0)
- statistics.classes = set.union(*[xgtf.classes for xgtf in self._xgtfData])
- return [xgtf.to_excel() for xgtf in self._xgtfData] + [statistics.to_excel()]
- def append(self, element:XgtfData):
- self._xgtfData.append(element)
- pass
- pass
-
-
-
-if __name__ == "__main__":
- # Аргументы
- parser = ArgumentParser()
- parser.add_argument('--work-dir', required=True)
- parser.add_argument('--result-dir',nargs="?", default='result.xlsx')
- namespace = parser.parse_args()
- #
- allData = AllXgtfData()
- for file_name in os.listdir(namespace.work_dir):
- # Условие для обработки .xgtf
- if file_name.find(".xgtf") == -1:
- continue
- # Подготовка
- # Имя
- data = XgtfData(file_name)
-
- try:
- tree = ET.parse(os.path.join(namespace.work_dir, file_name))
- except ET.ParseError:
- allData.append(data)
- continue
- print(os.path.join(namespace.work_dir, file_name))
- root_data_sourcefile = tree.getroot().find(f'./{VIPER}data/{VIPER}sourcefile')
-
- # Количество рамок объектов
- for v_object in root_data_sourcefile.findall(f'./{VIPER}object'):
- data.objectsCount += 1
- for bbox in v_object.findall(f'./{VIPER}attribute[@name="Position"]/{VIPERDATA}bbox'):
- data.objectsFramesCount += sum([right-left+1 for splited_bbox in bbox.attrib["framespan"].split(" ") for left, right in [map(int, splited_bbox.split(":"))]])
-
- # Классы
- try:
- data.classes.add(v_object.find(f'./{VIPER}attribute[@name="Class"]/{VIPERDATA}svalue').attrib['value'])
- except AttributeError:
- data.classes.add(get_default_value_for_class(tree))
-
- root_data_sourcefile_file = root_data_sourcefile.find(f'./{VIPER}file')
- try:
- # Длинна видео (кадры)
- data.framesCount = float(root_data_sourcefile_file.find(f'./{VIPER}attribute[@name="NUMFRAMES"]/').attrib['value']) # NUMFRAMES
- framerate = float(root_data_sourcefile_file.find(f'.//{VIPER}attribute[@name="FRAMERATE"]/').attrib['value']) # FRAMERATE
- if data.framesCount == 0 or framerate == 0:
- raise AttributeError
- except AttributeError:
- data.framesCount,framerate = get_fps_and_numframes_from_video(namespace.work_dir, file_name)
-
- if framerate != 0:
- # Расчет времени
- data.videoDuration = data.framesCount / framerate
-
-
- # Сохраняем в общий массив
- allData.append(data)
-
- # Вывод в файл
- df = pd.DataFrame(allData.to_excel(), columns=['Имя', 'Количество объектов', 'Длинна видео (секунд)', 'Длинна видео (кадры)', 'Среднее кол-во рамок объектов на кадре', 'Классы'])
- writer = pd.ExcelWriter(namespace.result_dir, engine='xlsxwriter')
- df.style.applymap(painting_errors).to_excel(writer, sheet_name='Sheet1', index=False, na_rep='NaN')
-
- for column in df:
- column_length = max(df[column].astype(str).map(len).max(), len(column)) + 1
- col_idx = df.columns.get_loc(column)
- writer.sheets['Sheet1'].set_column(col_idx, col_idx, column_length)
-
- writer.close()