diff --git a/.gitignore b/.gitignore index a05c910..73a6b27 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -xgtf_to_excel/result.xlsx +xgtf_to_excel_dir/result.xlsx .idea/misc.xml .idea/modules.xml .idea/vcs.xml @@ -6,3 +6,5 @@ xgtf_to_excel/result.xlsx .idea/inspectionProfiles/profiles_settings.xml .idea/.gitignore result.xlsx + +gui-for-tester-tracker \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..c5e1418 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,162 @@ + + + + + + + + + + + + + + { + "lastFilter": { + "state": "OPEN", + "assignee": "Wintreist" + } +} + + + + + + { + "customColor": "", + "associatedIndex": -1 +} + + + + { + "keyToString": { + "RunOnceActivity.OpenProjectViewOnStart": "true", + "RunOnceActivity.ShowReadmeOnStart": "true", + "git-widget-placeholder": "xgtf__to__excel" + } +} + + + + + + + + + + + + + + + 1691487803526 + + + + + + + + + + + + + + + + + + + + + + + + file://$PROJECT_DIR$/xgtf_to_excel/xgtf_to_excel.py + 31 + + + + + \ No newline at end of file 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_dir/__pycache__/xgtf_to_excel.cpython-310.pyc b/xgtf_to_excel_dir/__pycache__/xgtf_to_excel.cpython-310.pyc new file mode 100644 index 0000000..0266aa2 Binary files /dev/null and b/xgtf_to_excel_dir/__pycache__/xgtf_to_excel.cpython-310.pyc differ diff --git a/xgtf_to_excel/__pycache__/xgtf_to_excel.cpython-311.pyc b/xgtf_to_excel_dir/__pycache__/xgtf_to_excel.cpython-311.pyc similarity index 100% rename from xgtf_to_excel/__pycache__/xgtf_to_excel.cpython-311.pyc rename to xgtf_to_excel_dir/__pycache__/xgtf_to_excel.cpython-311.pyc diff --git a/xgtf_to_excel_dir/icon.png b/xgtf_to_excel_dir/icon.png new file mode 100644 index 0000000..8c715c8 Binary files /dev/null and b/xgtf_to_excel_dir/icon.png differ diff --git a/xgtf_to_excel_dir/requirements.txt b/xgtf_to_excel_dir/requirements.txt new file mode 100644 index 0000000..4343b69 Binary files /dev/null and b/xgtf_to_excel_dir/requirements.txt differ diff --git a/xgtf_to_excel_dir/untitled.ui b/xgtf_to_excel_dir/untitled.ui new file mode 100644 index 0000000..0f2ec3b --- /dev/null +++ b/xgtf_to_excel_dir/untitled.ui @@ -0,0 +1,170 @@ + + + MainWindow + + + + 0 + 0 + 620 + 252 + + + + + 0 + 0 + + + + Xgtf to Excel GUI + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + + + + + Выход из программы + + + + + + + Очистить поля + + + + + + + ... + + + + + + + Запустить + + + + + + + true + + + + + + + ... + + + + + + + true + + + + + + + Выберите директорию для файла с результатом + + + + + + + + + + .xlsx + + + + + + + Введите название файла с результатом + + + + + + + Выберите рабочую директорию + + + + + + + + + Открыть файл с результатом + + + + + + + false + + + 0 + + + true + + + + + + + + + + + + + + 0 + 0 + 620 + 21 + + + + + + + + diff --git a/xgtf_to_excel/xgtf_to_excel.py b/xgtf_to_excel_dir/xgtf_to_excel.py similarity index 89% rename from xgtf_to_excel/xgtf_to_excel.py rename to xgtf_to_excel_dir/xgtf_to_excel.py index 4737828..3644d2f 100644 --- a/xgtf_to_excel/xgtf_to_excel.py +++ b/xgtf_to_excel_dir/xgtf_to_excel.py @@ -4,9 +4,10 @@ from argparse import ArgumentParser import cv2 from dataclasses import dataclass, field -from typing import Optional, Tuple +from typing import Optional, Tuple, Callable from math import isnan from numpy import sum as npsum +from alive_progress import alive_it # Константы @@ -94,17 +95,12 @@ def append(self, element:XgtfData): 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() - # +def xgtf_to_excel_work(work_dir, result_dir = os.path.join(os.getcwd(), 'result.xlsx'), callback:Optional[Callable[[int], None]]=None): allData = AllXgtfData() - for file_name in os.listdir(namespace.work_dir): + bar = alive_it(os.listdir(work_dir)) if callback is None else os.listdir(work_dir) + for file_name in bar: + if callback is not None: + callback(int(bar.index(file_name) * 100 / len(bar))) # Условие для обработки .xgtf if file_name.find(".xgtf") == -1: continue @@ -113,11 +109,11 @@ def append(self, element:XgtfData): data = XgtfData(file_name) try: - tree = ET.parse(os.path.join(namespace.work_dir, file_name)) + tree = ET.parse(os.path.join(work_dir, file_name)) except ET.ParseError: allData.append(data) continue - print(os.path.join(namespace.work_dir, file_name)) + print(os.path.join(work_dir, file_name)) root_data_sourcefile = tree.getroot().find(f'./{VIPER}data/{VIPER}sourcefile') # Количество рамок объектов @@ -140,7 +136,7 @@ def append(self, element:XgtfData): 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) + data.framesCount,framerate = get_fps_and_numframes_from_video(work_dir, file_name) if framerate != 0: # Расчет времени @@ -152,7 +148,7 @@ def append(self, element:XgtfData): # Вывод в файл df = pd.DataFrame(allData.to_excel(), columns=['Имя', 'Количество объектов', 'Длинна видео (секунд)', 'Длинна видео (кадры)', 'Среднее кол-во рамок объектов на кадре', 'Классы']) - writer = pd.ExcelWriter(namespace.result_dir, engine='xlsxwriter') + writer = pd.ExcelWriter(result_dir, engine='xlsxwriter') df.style.applymap(painting_errors).to_excel(writer, sheet_name='Sheet1', index=False, na_rep='NaN') for column in df: @@ -161,3 +157,16 @@ def append(self, element:XgtfData): writer.sheets['Sheet1'].set_column(col_idx, col_idx, column_length) writer.close() + if callback: + callback(100) + + +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() + # + xgtf_to_excel_work(namespace.work_dir, namespace.result_dir) + diff --git a/xgtf_to_excel_dir/xgtf_to_excel_gui.py b/xgtf_to_excel_dir/xgtf_to_excel_gui.py new file mode 100644 index 0000000..6547db9 --- /dev/null +++ b/xgtf_to_excel_dir/xgtf_to_excel_gui.py @@ -0,0 +1,99 @@ +import sys +import os +from functools import partial +import subprocess as sub +from PyQt6 import uic, QtGui +from PyQt6.QtWidgets import QMainWindow, QApplication, QPushButton, QLineEdit, QFileDialog, QMessageBox, QProgressBar +from PyQt6.QtCore import pyqtSignal +from threading import Thread +from xgtf_to_excel import xgtf_to_excel_work + +class MainWindow(QMainWindow): + updateProgressBarSignal = pyqtSignal(int) + endBackgroundProcess = pyqtSignal() + def __init__(self): + super(MainWindow, self).__init__() + uic.loadUi('xgtf_to_excel_dir/untitled.ui', self) + # Определение виджетов + self.input_work_dir = self.findChild(QLineEdit, "input_work_dir") + self.input_result_dir = self.findChild(QLineEdit, "input_result_dir") + self.input_file_name = self.findChild(QLineEdit, "input_file_name") + + self.button_select_work_dir = self.findChild(QPushButton, "button_select_work_dir") + self.button_select_result_dir = self.findChild(QPushButton, "button_select_result_dir") + self.button_exit = self.findChild(QPushButton, "button_exit") + self.button_clear_input = self.findChild(QPushButton, "button_clear_input") + self.button_start = self.findChild(QPushButton, "button_start") + self.button_open_result_file = self.findChild(QPushButton, "button_open_result_file") + + self.progressBar = self.findChild(QProgressBar, "progressBar") + # ~~~~~~~~ + # Значения по умолчанию + self.set_default_value() + # ~~~~~~~~ + # Свойства + self.input_work_dir.setReadOnly(True) + self.input_result_dir.setReadOnly(True) + self.button_open_result_file.setVisible(False) + # ~~~~~~~~ + # Сигналы + self.button_select_work_dir.clicked.connect(partial(self.openFileExplorer, self.input_work_dir)) + self.button_select_result_dir.clicked.connect(partial(self.openFileExplorer, self.input_result_dir)) + self.button_exit.clicked.connect(self.close) + self.button_clear_input.clicked.connect(self.clear_all_inputs) + self.button_start.clicked.connect(self.start_program) + # ~~~~~~~~ + self.show() + pass + def openFileExplorer(self, input_directory:QLineEdit): + directory = QFileDialog.getExistingDirectory(self, "Выберите директорию") + if directory != '': + input_directory.setText(directory) + pass + def set_default_value(self): + self.input_file_name.setText("result") + self.input_result_dir.setText(os.getcwd()) + self.progressBar.setValue(0) + self.button_open_result_file.setVisible(False) + pass + def clear_all_inputs(self): + for input in self.findChildren(QLineEdit): + input.setText('') + self.set_default_value() + pass + def start_program(self): + if not self.input_work_dir.text(): + QMessageBox.critical(self, "Ошибка запуска", "Вы не ввели рабочую директорию!") + return False + if not self.input_file_name.text(): + QMessageBox.critical(self, "Ошибка запуска", "Вы не ввели название файла с результатом!") + return False + self.button_start.setEnabled(False) + self.button_open_result_file.setVisible(False) + work_dir = os.path.join(self.input_work_dir.text()) + result_dir = os.path.join(self.input_result_dir.text(), self.input_file_name.text() + ".xlsx") + self.updateProgressBarSignal.connect(self.progressBar.setValue) + self.endBackgroundProcess.connect(partial(self.endBackgroundProcessFunction, result_dir)) + self.backgroundThread = Thread(target=self.threadFunctionForBackgroundProcess, args=(work_dir, result_dir, self.updateProgressBarSignal, self.endBackgroundProcess)) + self.backgroundThread.start() + pass + def endBackgroundProcessFunction(self, result_dir:str): + self.button_start.setEnabled(True) + self.button_open_result_file.setVisible(True) + self.button_open_result_file.clicked.connect(partial(self.open_result_file, result_dir)) + pass + def threadFunctionForBackgroundProcess(self, work_dir:str, result_dir:str, updateSignal:pyqtSignal, endSignal:pyqtSignal): + callback = updateSignal.emit + xgtf_to_excel_work(work_dir, result_dir, callback) + endSignal.emit() + pass + def open_result_file(self, file_path:str): + sub.run(["start", file_path], shell=True) + pass + +if __name__ == '__main__': + # os.chdir(os.path.realpath(__file__[:__file__.rfind("\\")])) + app = QApplication(sys.argv) + app.setWindowIcon(QtGui.QIcon('xgtf_to_excel_dir/icon.png')) + main_window = MainWindow() + app.exec() \ No newline at end of file