from PyQt5.QtCore import QSize, QRunnable, Qt, QThreadPool, QObject, pyqtSignal, pyqtSlot, QThread import numpy as np from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QFrame, QComboBox, QLabel, QWidget, QVBoxLayout, QHBoxLayout, QGridLayout, QFileDialog, QProgressBar from PyQt5.QtGui import QPixmap, QImage import cv2 import sys from Relatorio import Relatorio import json from model_manager import ModelManager from explicador import Explicador class Classify(QObject): sg_progess_bar = pyqtSignal(int, str) sg_update_image = pyqtSignal(QImage) sg_report = pyqtSignal(str, float) str_loading_model = "LOADING MODEL" str_predicting = "PREDICTING" str_doing_report = "CONFIGURING REPORT" str_explaining = "EXPLAINING" str_showing_explanation = "SHOWING EXPLANATION" str_finished = "FINISHED" def __init__(self, model_manager, model_info, explicador, image, name_explainer): super().__init__() self.MODEL_MANAGER = model_manager self.EXPLICADOR = explicador self.model_info = model_info self.image = image self.name_explainer = name_explainer def run(self): self.sg_progess_bar.emit(0, self.str_loading_model) #obtem o modelo model = self.MODEL_MANAGER.configure_model(self.model_info["name"], self.model_info["directory"], self.model_info["size"], self.model_info["type"]) #faz a predicao self.sg_progess_bar.emit(20, self.str_predicting) predicted = self.MODEL_MANAGER.make_prediction(self.model_info["name"], self.image) #atualiza relatorio self.sg_progess_bar.emit(40, self.str_doing_report) self.sg_report.emit(predicted["class_name"], predicted["score"]) #obtem a explicacao self.sg_progess_bar.emit(60, self.str_explaining) if self.name_explainer == "Grad-CAM" or self.name_explainer == "Grad-CAM++": props = { "conv_layer":self.model_info["last_conv"] } elif self.name_explainer == "LIME": props = { "undo_changes":model["undo_changes"] } else: props = {} explanation = self.EXPLICADOR.get_explanation(self.image, model["model"], model["size"], self.name_explainer, model["preprocessing"], props=props) self.sg_progess_bar.emit(80, self.str_showing_explanation) #exibe a imagem na tela explanation = np.asarray(explanation) height, width, channel = explanation.shape bytesPerLine = 3 * width explanation = QImage(explanation.data, width, height, bytesPerLine, QImage.Format_RGB888).rgbSwapped() self.sg_progess_bar.emit(100, self.str_finished) self.sg_update_image.emit(explanation) # Subclass QMainWindow to customize your application's main window class MainWindow(QMainWindow): select_image_str = "select image" model_str = "select model" xai_str = "select explainer" bt_image_str = "select" run_str = "RUN" str_title = "Grapevine Classification" MODEL_MANAGER = ModelManager() EXPLICADOR = Explicador() def __init__(self): super().__init__() self.setWindowTitle(self.str_title) self.setFixedSize(QSize(600, 600)) #central widget self.central_widget = QWidget() self.setCentralWidget(self.central_widget) central_layout = QHBoxLayout(self.central_widget) #principais layouts self.left_layout = QVBoxLayout() self.image_layout = QHBoxLayout() self.model_layout = QHBoxLayout() self.xai_layout = QHBoxLayout() self.run_layout = QGridLayout() #componentes iterativos self.select_image_button = QPushButton() self.select_image_button.setText(self.bt_image_str) self.select_model_combobox = QComboBox() self.select_xai_combobox = QComboBox() self.select_run = QPushButton() self.select_run.setText(self.run_str) self.select_run.setStyleSheet("background-color: gray; color: black;") self.select_run.setEnabled(False) self.progress_bar = QProgressBar() self.progress_bar.setAlignment(Qt.AlignCenter) #componentes nao iterativos self.select_image_label = QLabel() self.select_image_label.setText(self.select_image_str) self.select_model_label = QLabel() self.select_model_label.setText(self.model_str) self.select_xai_label = QLabel() self.select_xai_label.setText(self.xai_str) #visualizador da imagem self.visualiza_imagem = QLabel() #relatorio self.relatorio_widget = Relatorio() #delete after self.relatorio_widget.configure('', 0) #povoa layouts self.image_layout.addWidget(self.select_image_label) self.image_layout.addWidget(self.select_image_button) self.model_layout.addWidget(self.select_model_label) self.model_layout.addWidget(self.select_model_combobox) self.xai_layout.addWidget(self.select_xai_label) self.xai_layout.addWidget(self.select_xai_combobox) self.run_layout.addWidget(self.select_run, 0, 3) self.left_layout.addLayout(self.image_layout) self.left_layout.addLayout(self.model_layout) self.left_layout.addLayout(self.xai_layout) self.left_layout.addWidget(self.progress_bar) self.left_layout.addLayout(self.run_layout) self.left_layout.addWidget(self.relatorio_widget) self.relatorio_widget.hide_labels() central_layout.addLayout(self.left_layout) central_layout.addWidget(self.visualiza_imagem) #carrega configuracoes self.carrega_configuracoes() #define outras variáveis self.image = None #define iteractive actions actions self.define_actions() #metodo que seta imagem que vai ser visualizada def view_image(self, img): pixmap = QPixmap(img) pixmap = pixmap.scaled(300, 300) self.visualiza_imagem.setPixmap(pixmap) def carrega_configuracoes(self): self.path_config = "config.json" if len(sys.argv) > 1: self.path_config = sys.argv[1] f = open(self.path_config) self.configs = json.load(f) f.close() models = [x["name"] for x in self.configs["models"]] self.select_model_combobox.addItems(models) self.select_xai_combobox.addItems(self.EXPLICADOR.get_explainers_name()) self.models = self.configs["models"] self.MODEL_MANAGER.configure_classes(self.configs["classes"]) #define acoes dos botoes def define_actions(self): self.select_image_button.clicked.connect(self.open_image) self.select_run.clicked.connect(self.execute) #metodo que abre a janela para selecionar o arquivo def open_image(self): fname = QFileDialog.getOpenFileName(self, self.select_image_str, filter="Image files (*.jpg *.tiff *.jpeg *.bmp *.png)") print(fname) self.image = fname[0] self.view_image(self.image) self.relatorio_widget.hide_labels() self.select_run.setStyleSheet("background-color: green; color: white;") self.select_run.setEnabled(True) #update da progress bar @pyqtSlot(int, str) def update_progress(self, progress, text): self.progress_bar.setValue(progress) self.progress_bar.setFormat(text) #faz update da imagem @pyqtSlot(QImage) def receive_image(self, img): self.view_image(img) self.progress_bar.setTextVisible(False) @pyqtSlot(str, float) def update_relatorio(self, pred_class, score): self.relatorio_widget.configure(pred_class, score) #metodo que executa as coisas def execute(self): self.progress_bar.setTextVisible(True) model = self.models[self.select_model_combobox.currentIndex()] name_explainer = str(self.select_xai_combobox.currentText()) # Step 2: Create a QThread object self.thread = QThread(parent=self) # Step 3: Create a worker object self.worker = Classify(self.MODEL_MANAGER, model, self.EXPLICADOR, self.image, name_explainer) self.worker.sg_progess_bar.connect(self.update_progress) self.worker.sg_update_image.connect(self.receive_image) self.worker.sg_report.connect(self.update_relatorio) # Step 4: Move worker to the thread self.worker.moveToThread(self.thread) # Step 5: Connect signals and slots self.thread.started.connect(self.worker.run) # Step 6: Start the thread self.thread.start() app = QApplication(sys.argv) window = MainWindow() window.show() app.exec()