diff --git a/FISH_segmentation/Application_Qt/Application_Qt_.py b/FISH_segmentation/Application_Qt/Application_Qt_.py index de0adc0..8fe1698 100644 --- a/FISH_segmentation/Application_Qt/Application_Qt_.py +++ b/FISH_segmentation/Application_Qt/Application_Qt_.py @@ -7,9 +7,8 @@ from matplotlib import pyplot as plt from PyQt6 import QtWidgets, QtCore, QtGui from PyQt6.QtCore import Qt -from PyQt6.QtGui import QImage, QPixmap -from PyQt6.QtWidgets import QFileDialog, QTableWidgetItem, QMessageBox -from ultralytics import YOLO +from PyQt6.QtGui import QImage, QPixmap, QColor, QBrush +from PyQt6.QtWidgets import QFileDialog, QTableWidgetItem, QMessageBox, QApplication from Application_Qt_module_ui import Ui_MainWindow from ChromosomePatch import ChromosomeCellDetector from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas @@ -18,19 +17,20 @@ class Func(Ui_MainWindow): width = -1 height = -1 - PhotoList = [] - PhotoNameList = [] - PhotoSegmentationList = [] - PhotoSegmentationNameList = [] - SelectionListIndex = -1 - SelectionListIndexProm = -1 - Ref = [] - DetectorsList = [] + + SelectionListIndex = "" + SelectionListIndexProm = "" + ImagesDictionary = {} + SegmentationImagesDictionary = {} + + ResultsDictionary = {} + ModelDetectorsDictionary = {} + MaskDictionary = {} + FileModelPath = os.path.join( os.path.dirname(os.path.abspath(__file__)), "..\\Model\\my_yolov8_model_core_segmentation_plus_plus.pt", ) - model = YOLO(FileModelPath) def setupUiFunc(self, MainWindow): self.setupUi(MainWindow) @@ -39,26 +39,49 @@ def setupUiFunc(self, MainWindow): # Клик по кнопке -> (вызов функции): def add_functions(self): self.pushButtonStart.clicked.connect(self.Add_Paths) - self.pushButtonSeg.clicked.connect(self.predict_image_ChromosomePatch) + self.pushButtonSeg.clicked.connect(self.ClickPushButtonSeg) self.pushButtonSave.clicked.connect(self.SavePhoto) + self.SelectionList.clicked.connect(self.SelectionListFunc) + self.SelectionListSeg.clicked.connect(self.SelectionListSegFunc) self.SelectionTable.clicked.connect(self.SelectionTableFunc) self.deleteShortcut = QtGui.QShortcut(QtCore.Qt.Key.Key_Delete, self.SelectionList) self.deleteShortcut.activated.connect(self.ListFuncDelete) - self.horizontalSlider.valueChanged.connect(self.update_label) + self.AccuracySlider.valueChanged.connect(self.update_label) + + # Соединяем сигнал с слотом из переопределенног класса ClickableLabel; + self.PlaceForPromFotos.clicked.connect(self.ClickedPlaceForPromFotos) + def ClickedPlaceForPromFotos(self, original_x, original_y): + if self.SelectionListIndexProm == "": + return + index = 0 + # Перебор найденных контуров: + masks = self.MaskDictionary[self.SelectionListIndexProm] + for mask in masks: + contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) + for contour in contours: + # Проверяем, попал ли клик мыши в контур + if cv2.pointPolygonTest(contour, (original_x, original_y), False) >= 0: + self.SelectionTable.setCurrentCell(index, 0) + self.SelectionTableFunc() + return + index += 1 + + # Обновить значение точности в поле на интерфейсе; def update_label(self): - value = float(self.horizontalSlider.value() / 100) - self.label.setText(str(value)) + value = float(self.AccuracySlider.value() / 100) + self.AccuracyLable.setText(str(value)) + # Функция для работы с таблицей; def SelectionTableFunc(self): - if self.SelectionListIndexProm != -1: + if self.SelectionListIndexProm != "": selected_items = self.SelectionTable.selectedItems() if len(selected_items) > 0: row = selected_items[0].row() try: - detector = self.DetectorsList[self.SelectionListIndexProm] + detector = self.ModelDetectorsDictionary[self.SelectionListIndexProm] radius = detector.Radius[row] item = self.SelectionTable.item(row, 1) @@ -67,7 +90,7 @@ def SelectionTableFunc(self): item = self.SelectionTable.item(row, 2) if item is not None: y = item.text() - image = self.PhotoSegmentationList[self.SelectionListIndexProm] + image = self.SegmentationImagesDictionary[self.SelectionListIndexProm] desired_size = (512, 512) image = cv2.resize(image, desired_size) @@ -83,76 +106,93 @@ def SelectionTableFunc(self): except (UnboundLocalError, IndexError) as e: error_dialog = QMessageBox() error_dialog.setWindowTitle("Ошибка") - error_dialog.setText(f"Произошла ошибка: {str(e)}. Попробуйте перевыбрать элемент в таблице.") + error_dialog.setText(f"Произошла ошибка: {str(e)}. Попробуйте снова выбрать элемент в таблице.") error_dialog.exec() + print("Ошибка таблицы: 'def SelectionTableFunc()'; ") - print("Ошибка таблицы.") - - # Функция для сегментации: - def predict_image_ChromosomePatch(self): + def ClickPushButtonSeg(self): is_checked = self.checkBoxSeg.isChecked() - if (self.SelectionListIndex == -1 and not is_checked) or len(self.PhotoList) == 0: + if (((self.SelectionListIndex == "" and self.SelectionListIndexProm == "") and not is_checked) or len(self.ImagesDictionary) == 0): return - Accuracy = float(self.horizontalSlider.value() / 100) # Берем точность с поля; + Accuracy = float(self.AccuracySlider.value() / 100) # Берем точность с поля; if (Accuracy >= 0.98): Accuracy = 0.95 - if is_checked: - Zero = 0 - Index = len(self.PhotoList) + for ImageName in self.ImagesDictionary: + self.predict_image_ChromosomePatch(Accuracy, ImageName) else: - Index = self.SelectionListIndex + 1 - Zero = self.SelectionListIndex + if self.SelectionListIndex == "": + self.predict_image_ChromosomePatch(Accuracy, self.SelectionListIndexProm) + else: + self.predict_image_ChromosomePatch(Accuracy, self.SelectionListIndex) + self.DataLabel_2.setText("Обработка завершена") + self.SelectionListSegFunc() + + # Функция для сегментации: + def predict_image_ChromosomePatch(self, Accuracy, ImageName): try: - for file in range(Zero, Index): - detectorTest = ChromosomeCellDetector(self.PhotoList[file]) - detector = ChromosomeCellDetector(self.PhotoList[file]) - number_explode, number_whole = detector.find_cells(Accuracy) - detector.detect_chromosomes() - Red_Chromosome = detector.RedChromosome - Green_Chromosome = detector.GreenChromosome - - fig, ax = plt.subplots(1, 1, figsize=(16, 16), dpi=300) - ax = detector.plot(ax) - fig.patch.set_visible(False) - ax.axis("off") - plt.subplots_adjust(left=0, right=1, top=1, bottom=0) - - canvas = FigureCanvas(fig) - canvas.draw() - self.width, self.height = fig.get_size_inches() * fig.get_dpi() - buffer_rgba = canvas.buffer_rgba() - array_rgba = np.asarray(buffer_rgba) - imgrgd = detectorTest.rgba2rgb(array_rgba) - - self.PhotoSegmentationList.append(imgrgd) - self.DetectorsList.append(detector) - self.PhotoSegmentationNameList.append(file) - - ref = ( - "Whole cell: " - + str(number_whole) - + "\nExplode cell: " - + str(number_explode) - + "\nRed chromosome: " - + str(Red_Chromosome) - + "\nGreen chromosome: " - + str(Green_Chromosome) - ) - self.Ref.append(ref) - detector.write_to_csv("Списочек", "рядом", self.PhotoNameList[file]) + self.DataLabel_2.setText("Обрабатывается изображение: " + ImageName) + # Обрабатываем события в очереди, чтобы обновить QLabel + QApplication.processEvents() + + detector = ChromosomeCellDetector(self.ImagesDictionary[ImageName]) + number_explode, number_whole = detector.find_cells(Accuracy) + detector.detect_chromosomes() + Red_Chromosome = detector.RedChromosome + Green_Chromosome = detector.GreenChromosome + + fig, ax = plt.subplots(1, 1, figsize=(16, 16), dpi=300) + ax, mask = detector.plot(ax) + fig.patch.set_visible(False) + ax.axis("off") + plt.subplots_adjust(left=0, right=1, top=1, bottom=0) + + canvas = FigureCanvas(fig) + canvas.draw() + self.width, self.height = fig.get_size_inches() * fig.get_dpi() + buffer_rgba = canvas.buffer_rgba() + array_rgba = np.asarray(buffer_rgba) + imgrgd = self.rgba2rgb(array_rgba) + + ref = ( + "Whole cell: " + + str(number_whole) + + "\nExplode cell: " + + str(number_explode) + + "\nRed chromosome: " + + str(Red_Chromosome) + + "\nGreen chromosome: " + + str(Green_Chromosome) + ) + self.ResultsDictionary[ImageName] = ref + detector.write_to_csv("Списочек", "рядом", ImageName) qimage = QImage(imgrgd, int(self.width), int(self.height), QImage.Format.Format_RGB888) pixmap = QPixmap.fromImage(qimage) pixmap = pixmap.scaled(512, 512, Qt.AspectRatioMode.IgnoreAspectRatio) + self.PlaceForPromFotos.setPixmap(pixmap) - self.DataLabel.setText(ref) - self.SelectionListFunc() + + FindImageInList = self.SelectionList.findItems(ImageName, QtCore.Qt.MatchFlag.MatchExactly) + # Если элемент найден, удалите его + if FindImageInList: + self.SelectionList.takeItem(self.SelectionList.row(FindImageInList[0])) + + if ImageName not in self.SegmentationImagesDictionary: + self.SelectionListSeg.addItem(ImageName) + + self.SegmentationImagesDictionary[ImageName] = imgrgd + self.ModelDetectorsDictionary[ImageName] = detector + self.MaskDictionary[ImageName] = mask + except IndexError as e: error_dialog = QMessageBox() error_dialog.setWindowTitle("Ошибка") error_dialog.setText(f"Произошла ошибка: {str(e)}. Попробуйте увеличить точность.") error_dialog.exec() + FindImageInList = self.SelectionList.findItems(ImageName, QtCore.Qt.MatchFlag.MatchExactly) + if FindImageInList: + FindImageInList[0].setForeground(QBrush(QColor('red'))) print("Ошибка. Попробуйте увеличить точность.") @@ -164,9 +204,14 @@ def PhotoReadAndSave(self, FilePaths): os.makedirs(folder_name) for file in range(0, len(FilePaths)): - Image_name = os.path.splitext(os.path.basename(FilePaths[file]))[0] # Для получения имени файла - items = self.SelectionList.findItems(Image_name, QtCore.Qt.MatchFlag.MatchExactly) - if not items: + ImageName = os.path.splitext(os.path.basename(FilePaths[file]))[0] # Для получения имени файла + + FindImageInList = 0 + if ImageName in self.ImagesDictionary: + FindImageInList = 1 + if ImageName in self.SegmentationImagesDictionary: + FindImageInList = 1 + if FindImageInList == 0: if FilePaths[file].endswith(".jpg"): image = mpimg.imread(FilePaths[file]) image = np.ascontiguousarray(image) @@ -182,12 +227,10 @@ def PhotoReadAndSave(self, FilePaths): if np.all(image == 0): break image = cv2.resize(image, (512, 512)) - detectorTest = ChromosomeCellDetector(image) - image = detectorTest.rgba2rgb(image) + image = self.rgba2rgb(image) - self.PhotoNameList.append(Image_name) - self.PhotoList.append(image) - self.SelectionList.addItem(Image_name) + self.ImagesDictionary[ImageName] = image + self.SelectionList.addItem(ImageName) def read_czi_image(self, filename, norm=True): try: @@ -205,7 +248,8 @@ def read_czi_image(self, filename, norm=True): except IndexError as e: error_dialog = QMessageBox() error_dialog.setWindowTitle("Ошибка") - error_dialog.setText(f"Произошла ошибка: {str(e)}. Проблема с обработкой .czi формата.") + text = "Проблема с обработкой .czi формата, возможно, ошибка с количеством каналов" + error_dialog.setText(f"Произошла ошибка: {str(e)}. {text}.") error_dialog.exec() print("Ошибка. Проблема с обработкой .czi формата.") return np.zeros((3, 3)) @@ -216,67 +260,98 @@ def Add_Paths(self): if FilePaths: self.PhotoReadAndSave(FilePaths) + # Обработка взаимодействия со списком выбранных изображений "SelectionList": def SelectionListFunc(self): - self.SelectionListIndex = self.SelectionList.currentRow() + if self.SelectionList.count() == 0: + self.SelectionListIndex = "" + return + + self.SelectionListIndexProm = "" + if self.SelectionList.currentItem() is None: + item = self.SelectionList.item(self.SelectionList.count() - 1) + self.SelectionList.setCurrentItem(item) + self.SelectionListIndex = (self.SelectionList.currentItem()).text() + myImage = Image.fromarray(self.ImagesDictionary[self.SelectionListIndex]) + # Преобразование PIL Image в QImage + MyQImage = QImage(myImage.tobytes(), myImage.size[0], myImage.size[1], QImage.Format.Format_RGB888) + # Преобразование QImage в QPixmap + MyQPixmap = QPixmap.fromImage(MyQImage) + self.PlaceForFotos.setPixmap(MyQPixmap) + + self.PlaceForPromFotos.clear() + self.DataLabel.clear() + self.SelectionTable.setRowCount(0) + + # Обработка взаимодействия со списком выбранных изображений "SelectionListSeg": + def SelectionListSegFunc(self): + if self.SelectionListSeg.count() == 0: + self.SelectionListIndexProm = "" + return - Index = -1 - for name in range(0, len(self.PhotoSegmentationNameList)): - if self.PhotoSegmentationNameList[name] == self.SelectionListIndex: - Index = name + self.SelectionListIndex = "" + if self.SelectionListSeg.currentItem() is None or self.SelectionListIndexProm == "": + item = self.SelectionListSeg.item(self.SelectionListSeg.count() - 1) + self.SelectionListSeg.setCurrentItem(item) + self.SelectionListIndexProm = (self.SelectionListSeg.currentItem()).text() - img = Image.fromarray(self.PhotoList[self.SelectionListIndex]) + myImage = Image.fromarray(self.ImagesDictionary[self.SelectionListIndexProm]) # Преобразование PIL Image в QImage - qim = QImage(img.tobytes(), img.size[0], img.size[1], QImage.Format.Format_RGB888) + MyQImage = QImage(myImage.tobytes(), myImage.size[0], myImage.size[1], QImage.Format.Format_RGB888) # Преобразование QImage в QPixmap - pix = QPixmap.fromImage(qim) - self.PlaceForFotos.setPixmap(pix) - if Index != -1: - qimage = QImage(self.PhotoSegmentationList[Index], int(self.width), int(self.height), - QImage.Format.Format_RGB888) - pixmap = QPixmap.fromImage(qimage) - pixmap = pixmap.scaled(512, 512, Qt.AspectRatioMode.IgnoreAspectRatio) - self.PlaceForPromFotos.setPixmap(pixmap) - self.DataLabel.setText(self.Ref[Index]) - else: - self.PlaceForPromFotos.clear() - self.DataLabel.clear() - self.SelectionTable.clearContents() + MyQPixmap = QPixmap.fromImage(MyQImage) + self.PlaceForFotos.setPixmap(MyQPixmap) + + myQImageSeg = QImage(self.SegmentationImagesDictionary[self.SelectionListIndexProm], + int(self.width), int(self.height), QImage.Format.Format_RGB888) + MyQPixmapSeg = QPixmap.fromImage(myQImageSeg) + MyQPixmapSeg = MyQPixmapSeg.scaled(512, 512, Qt.AspectRatioMode.IgnoreAspectRatio) + self.PlaceForPromFotos.setPixmap(MyQPixmapSeg) + + self.DataLabel.setText(self.ResultsDictionary[self.SelectionListIndexProm]) # Работа с таблицей: - self.SelectionListIndexProm = Index - if Index != -1: - self.SelectionTable.clearContents() - detector = self.DetectorsList[Index] - self.SelectionTable.setRowCount(detector.NumberWhole + detector.NumberExplode) - index = 0 - for idx, cell in enumerate(detector.cells): - for center_of_mass in cell.center_of_mass: - self.SelectionTable.setItem(index, 0, QTableWidgetItem(str(idx + 1))) - self.SelectionTable.setItem(index, 1, QTableWidgetItem(str(center_of_mass[1]))) - self.SelectionTable.setItem(index, 2, QTableWidgetItem(str(center_of_mass[0]))) - self.SelectionTable.setItem(index, 3, QTableWidgetItem(str(len(cell.green_chromosomes)))) - self.SelectionTable.setItem(index, 4, QTableWidgetItem(str(len(cell.red_chromosomes)))) - self.SelectionTable.setItem(index, 5, QTableWidgetItem("Exploded" if cell.Type == 0 else "Whole")) - index += 1 + self.SelectionTable.clearContents() + detector = self.ModelDetectorsDictionary[self.SelectionListIndexProm] + self.SelectionTable.setRowCount(detector.NumberWhole + detector.NumberExplode) + index = 0 + for idx, cell in enumerate(detector.cells): + for center_of_mass in cell.center_of_mass: + self.SelectionTable.setItem(index, 0, QTableWidgetItem(str(idx + 1))) + self.SelectionTable.setItem(index, 1, QTableWidgetItem(str(center_of_mass[1]))) + self.SelectionTable.setItem(index, 2, QTableWidgetItem(str(center_of_mass[0]))) + self.SelectionTable.setItem(index, 3, QTableWidgetItem(str(len(cell.green_chromosomes)))) + self.SelectionTable.setItem(index, 4, QTableWidgetItem(str(len(cell.red_chromosomes)))) + self.SelectionTable.setItem(index, 5, QTableWidgetItem("Exploded" if cell.Type == 0 else "Whole")) + index += 1 def ListFuncDelete(self): - currentRow = self.SelectionList.currentRow() - self.SelectionList.takeItem(currentRow) - self.PhotoNameList.pop(currentRow) - self.PhotoList.pop(currentRow) - Index = -1 - for name in range(0, len(self.PhotoSegmentationNameList)): - if self.PhotoSegmentationNameList[name] == currentRow: - Index = name - if Index != -1: - self.PhotoSegmentationList.pop(Index) - self.PhotoSegmentationNameList.pop(Index) - self.Ref.pop(Index) - self.DetectorsList.pop(Index) - for name in range(0, len(self.PhotoSegmentationNameList)): - if self.PhotoSegmentationNameList[name] >= currentRow: - self.PhotoSegmentationNameList[name] = (self.PhotoSegmentationNameList[name] - 1) - self.SelectionTable.clearContents() + if self.SelectionList.count() == 0 and self.SelectionListSeg.count() == 0: + return + Index = 0 + if self.SelectionListIndexProm == "": + currentRow = self.SelectionList.currentRow() + CurrentName = (self.SelectionList.currentItem()).text() + self.SelectionList.takeItem(currentRow) + + self.PlaceForFotos.clear() + self.SelectionListFunc() + else: + currentRow = self.SelectionListSeg.currentRow() + CurrentName = (self.SelectionListSeg.currentItem()).text() + self.SelectionListSeg.takeItem(currentRow) + Index = 1 + + self.SelectionTable.setRowCount(0) + self.DataLabel.clear() + self.PlaceForFotos.clear() + self.PlaceForPromFotos.clear() + self.SelectionListSegFunc() + + self.ImagesDictionary.pop(CurrentName) + if Index == 1: + self.SegmentationImagesDictionary.pop(CurrentName) + self.ResultsDictionary.pop(CurrentName) + self.ModelDetectorsDictionary.pop(CurrentName) def SavePhoto(self): is_checked = self.checkBoxSave.isChecked() @@ -284,37 +359,54 @@ def SavePhoto(self): Folder_Path = QFileDialog.getExistingDirectory( None, "Select a folder:", "", QFileDialog.Option.ShowDirsOnly) if Folder_Path: - for name in range(0, len(self.PhotoList)): + for name in self.ImagesDictionary: plt.imsave( - Folder_Path + "\\" + self.PhotoNameList[name] + ".png", - self.PhotoList[name]) + Folder_Path + "\\" + name + ".png", + self.ImagesDictionary[name]) if not os.path.exists(Folder_Path + "\\PhotoSeg"): os.makedirs(Folder_Path + "\\PhotoSeg") - for name in range(0, len(self.PhotoSegmentationNameList)): + for name in self.SegmentationImagesDictionary: plt.imsave(Folder_Path + "\\PhotoSeg" + "\\" - + self.PhotoNameList[self.PhotoSegmentationNameList[name]] - + ".png", self.PhotoSegmentationList[name]) + + name + ".png", self.SegmentationImagesDictionary[name]) else: - currentRow = self.SelectionList.currentRow() + index = 0 + if self.SelectionListIndexProm == "": + currentRow = self.SelectionList.currentRow() + selected_item = self.SelectionList.currentItem() + selected_text = selected_item.text() + + else: + currentRow = self.SelectionListSeg.currentRow() + selected_item = self.SelectionListSeg.currentItem() + selected_text = selected_item.text() + index = 1 if currentRow != -1: Folder_Path = QFileDialog.getExistingDirectory(None, "Select a folder:", "", QFileDialog.Option.ShowDirsOnly) if Folder_Path: - selected_item = self.SelectionList.currentItem() - selected_text = selected_item.text() - plt.imsave(Folder_Path + "\\" + selected_text + ".png", self.PhotoList[currentRow]) - - Index = -1 - for name in range(0, len(self.PhotoSegmentationNameList)): - if self.PhotoSegmentationNameList[name] == currentRow: - Index = name - if Index != -1: + plt.imsave(Folder_Path + "\\" + selected_text + ".png", self.ImagesDictionary[selected_text]) + + if index == 1: if not os.path.exists(Folder_Path + "\\PhotoSeg"): os.makedirs(Folder_Path + "\\PhotoSeg") plt.imsave(Folder_Path + "\\PhotoSeg" + "\\" + selected_text + ".png", - self.PhotoSegmentationList[Index]) + self.SegmentationImagesDictionary[selected_text]) + + def rgba2rgb(self, rgba, background=(255, 255, 255)): + row, col, ch = rgba.shape + if ch == 3: + return rgba + assert ch == 4, 'RGBA image has 4 channels.' + rgb = np.zeros((row, col, 3), dtype='float32') + r, g, b, a = rgba[:, :, 0], rgba[:, :, 1], rgba[:, :, 2], rgba[:, :, 3] + a = np.asarray(a, dtype='float32') / 255.0 + R, G, B = background + rgb[:, :, 0] = r * a + (1.0 - a) * R + rgb[:, :, 1] = g * a + (1.0 - a) * G + rgb[:, :, 2] = b * a + (1.0 - a) * B + return np.asarray(rgb, dtype='uint8') if __name__ == "__main__": diff --git a/FISH_segmentation/Application_Qt/Application_Qt_module_ui.py b/FISH_segmentation/Application_Qt/Application_Qt_module_ui.py index ba97632..b596bc7 100644 --- a/FISH_segmentation/Application_Qt/Application_Qt_module_ui.py +++ b/FISH_segmentation/Application_Qt/Application_Qt_module_ui.py @@ -1,18 +1,19 @@ # Form implementation generated from reading ui file 'Application_Qt_module_ui.ui' # -# Created by: PyQt6 UI code generator 6.4.2 +# Created by: PyQt6 UI code generator 6.6.1 # # 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 +from ClickableLabel import ClickableLabel class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") - MainWindow.resize(1078, 691) + MainWindow.resize(1147, 772) MainWindow.setMaximumSize(QtCore.QSize(16777215, 16777215)) icon = QtGui.QIcon() icon.addPixmap( @@ -21,7 +22,6 @@ def setupUi(self, MainWindow): QtGui.QIcon.State.Off, ) MainWindow.setWindowIcon(icon) - MainWindow.setAutoFillBackground(False) MainWindow.setStyleSheet( "#MainWindow\n" "{\n" @@ -36,123 +36,72 @@ def setupUi(self, MainWindow): "\n" "" ) - MainWindow.setAnimated(True) - MainWindow.setDocumentMode(False) - MainWindow.setDockNestingEnabled(False) - MainWindow.setUnifiedTitleAndToolBarOnMac(False) - self.centralwidget = QtWidgets.QWidget(parent=MainWindow) - self.centralwidget.setStyleSheet( - "#centralwidget {background-color: transparent;}" + self.CentralWidget = QtWidgets.QWidget(parent=MainWindow) + self.CentralWidget.setStyleSheet( + "#CentralWidget {background-color: transparent;}" ) - self.centralwidget.setObjectName("centralwidget") - self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget) + self.CentralWidget.setObjectName("CentralWidget") + self.verticalLayout = QtWidgets.QVBoxLayout(self.CentralWidget) self.verticalLayout.setObjectName("verticalLayout") - self.verticalGroupBox = QtWidgets.QGroupBox(parent=self.centralwidget) - self.verticalGroupBox.setAcceptDrops(False) - self.verticalGroupBox.setAutoFillBackground(False) - self.verticalGroupBox.setStyleSheet( - "#verticalGroupBox {\n" - "border: 1px inset #10f04f;\n" - "border-radius: 10px;\n" - "}" - ) - self.verticalGroupBox.setFlat(False) - self.verticalGroupBox.setCheckable(False) - self.verticalGroupBox.setObjectName("verticalGroupBox") - self.vboxlayout = QtWidgets.QVBoxLayout(self.verticalGroupBox) - self.vboxlayout.setObjectName("vboxlayout") - self.horizontalWidget = QtWidgets.QWidget(parent=self.verticalGroupBox) - self.horizontalWidget.setContextMenuPolicy( - QtCore.Qt.ContextMenuPolicy.NoContextMenu - ) - self.horizontalWidget.setStyleSheet( - "#horizontalGroupBox {\n" "border: 1px inset #10f04f;\n" "}" - ) - self.horizontalWidget.setObjectName("horizontalWidget") - self.horizontalLayout = QtWidgets.QHBoxLayout(self.horizontalWidget) - self.horizontalLayout.setContentsMargins(5, 0, 5, 0) - self.horizontalLayout.setSpacing(10) - self.horizontalLayout.setObjectName("horizontalLayout") - self.PlaceForFotos = QtWidgets.QLabel(parent=self.horizontalWidget) - self.PlaceForFotos.setStyleSheet( - "#PlaceForFotos\n" "{\n" "border: 4px inset #10f0ad;\n" "\n" "}" - ) - self.PlaceForFotos.setFrameShape(QtWidgets.QFrame.Shape.Box) - self.PlaceForFotos.setObjectName("PlaceForFotos") - self.horizontalLayout.addWidget(self.PlaceForFotos) - self.PlaceForPromFotos = QtWidgets.QLabel(parent=self.horizontalWidget) - self.PlaceForPromFotos.setStyleSheet( - "#PlaceForPromFotos\n" "{\n" "border: 4px outset #10f0e9;\n" "\n" "}" - ) - self.PlaceForPromFotos.setFrameShape(QtWidgets.QFrame.Shape.Box) - self.PlaceForPromFotos.setObjectName("PlaceForPromFotos") - self.horizontalLayout.addWidget(self.PlaceForPromFotos) - self.vboxlayout.addWidget(self.horizontalWidget) - self.gridGroupBox = QtWidgets.QGroupBox(parent=self.verticalGroupBox) - self.gridGroupBox.setMaximumSize(QtCore.QSize(16777215, 185)) - self.gridGroupBox.setStyleSheet( - "#gridGroupBox {\n" - " width: 100px;\n" - " height:100px;\n" - " border: 3px solid #1071f0;\n" - " border-radius: 15px;\n" - "}" + self.CentralGroupBox = QtWidgets.QGroupBox(parent=self.CentralWidget) + self.CentralGroupBox.setAcceptDrops(False) + self.CentralGroupBox.setStyleSheet( + "#CentralGroupBox {\n" "border: 3px inset #94D9DC;\n" "}" ) - self.gridGroupBox.setObjectName("gridGroupBox") - self.gridLayout = QtWidgets.QGridLayout(self.gridGroupBox) - self.gridLayout.setContentsMargins(9, 3, 5, 1) - self.gridLayout.setHorizontalSpacing(9) - self.gridLayout.setVerticalSpacing(3) - self.gridLayout.setObjectName("gridLayout") - self.verticalGroupBox_2 = QtWidgets.QGroupBox(parent=self.gridGroupBox) - self.verticalGroupBox_2.setMouseTracking(False) - self.verticalGroupBox_2.setTabletTracking(False) - self.verticalGroupBox_2.setAcceptDrops(False) - self.verticalGroupBox_2.setAutoFillBackground(False) - self.verticalGroupBox_2.setStyleSheet( - "#verticalGroupBox_2 {\n" - "border: 1px inset #1071f0;\n" - "border-radius: 10px;\n" - "}" - ) - self.verticalGroupBox_2.setTitle("") - self.verticalGroupBox_2.setFlat(False) - self.verticalGroupBox_2.setCheckable(False) - self.verticalGroupBox_2.setObjectName("verticalGroupBox_2") - self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.verticalGroupBox_2) - self.horizontalLayout_3.setObjectName("horizontalLayout_3") - self.DataLabel = QtWidgets.QLabel(parent=self.verticalGroupBox_2) - self.DataLabel.setMinimumSize(QtCore.QSize(150, 0)) - font = QtGui.QFont() - font.setPointSize(12) - self.DataLabel.setFont(font) - self.DataLabel.setAutoFillBackground(False) - self.DataLabel.setStyleSheet("") - self.DataLabel.setText("") - self.DataLabel.setObjectName("DataLabel") - self.horizontalLayout_3.addWidget(self.DataLabel) - self.SelectionList = QtWidgets.QListWidget(parent=self.verticalGroupBox_2) + self.CentralGroupBox.setObjectName("CentralGroupBox") + self.gridLayout_2 = QtWidgets.QGridLayout(self.CentralGroupBox) + self.gridLayout_2.setContentsMargins(5, 5, 5, 5) + self.gridLayout_2.setSpacing(5) + self.gridLayout_2.setObjectName("gridLayout_2") + self.Sec2_ToolsWidget = QtWidgets.QWidget(parent=self.CentralGroupBox) + self.Sec2_ToolsWidget.setMaximumSize(QtCore.QSize(16777215, 16777215)) + self.Sec2_ToolsWidget.setStyleSheet("") + self.Sec2_ToolsWidget.setObjectName("Sec2_ToolsWidget") + self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.Sec2_ToolsWidget) + self.verticalLayout_5.setContentsMargins(0, 1, 0, 0) + self.verticalLayout_5.setSpacing(4) + self.verticalLayout_5.setObjectName("verticalLayout_5") + self.gridLayout_4 = QtWidgets.QGridLayout() + self.gridLayout_4.setSpacing(3) + self.gridLayout_4.setObjectName("gridLayout_4") + self.SelectionList = QtWidgets.QListWidget(parent=self.Sec2_ToolsWidget) + self.SelectionList.setMinimumSize(QtCore.QSize(90, 0)) self.SelectionList.setMaximumSize(QtCore.QSize(100, 16777215)) + self.SelectionList.setMouseTracking(False) + self.SelectionList.setTabletTracking(False) + self.SelectionList.setAcceptDrops(False) + self.SelectionList.setAutoFillBackground(False) self.SelectionList.setStyleSheet( "#SelectionList\n" "{\n" - "border: 4px rgba(204, 224, 232, 0.5);\n" - "background: rgba(204, 224, 232, 0.5);\n" + "border: 2px solid #7C8081;\n" + "background: rgba(204, 224, 232, 0.7);\n" "}" ) + self.SelectionList.setWordWrap(False) self.SelectionList.setObjectName("SelectionList") - self.horizontalLayout_3.addWidget(self.SelectionList) - self.SelectionTable = QtWidgets.QTableWidget(parent=self.verticalGroupBox_2) + self.gridLayout_4.addWidget(self.SelectionList, 1, 1, 2, 1) + self.SelectionTable = QtWidgets.QTableWidget(parent=self.Sec2_ToolsWidget) + font = QtGui.QFont() + font.setFamily("Calibri") + font.setPointSize(10) + font.setBold(True) + font.setItalic(False) + font.setWeight(75) + self.SelectionTable.setFont(font) self.SelectionTable.setAcceptDrops(False) self.SelectionTable.setStyleSheet( "#SelectionTable\n" "{\n" - "border: 4px rgba(204, 224, 232, 0.5);\n" - "background: rgba(204, 224, 232, 0.5);\n" + " border: 4px outset rgba(204, 224, 232, 0.7);\n" + " background: rgba(217, 223, 226, 0.8);\n" "}\n" "QHeaderView::section {\n" - "background-color: rgba(204, 224, 232, 0.5);\n" - " }" + " background-color: rgba(204, 224, 232, 0.5);\n" + " }\n" + "QTableWidget::item {\n" + " font-weight: bold;\n" + "}" ) self.SelectionTable.setRowCount(0) self.SelectionTable.setColumnCount(6) @@ -176,61 +125,66 @@ def setupUi(self, MainWindow): self.SelectionTable.horizontalHeader().setStretchLastSection(True) self.SelectionTable.verticalHeader().setCascadingSectionResizes(False) self.SelectionTable.verticalHeader().setHighlightSections(True) - self.horizontalLayout_3.addWidget(self.SelectionTable) - self.gridLayout.addWidget(self.verticalGroupBox_2, 0, 1, 10, 1) - self.horizontalWidget_2 = QtWidgets.QWidget(parent=self.gridGroupBox) - self.horizontalWidget_2.setMinimumSize(QtCore.QSize(0, 0)) - self.horizontalWidget_2.setMaximumSize(QtCore.QSize(200, 16777215)) - self.horizontalWidget_2.setContextMenuPolicy( - QtCore.Qt.ContextMenuPolicy.PreventContextMenu + self.gridLayout_4.addWidget(self.SelectionTable, 0, 3, 3, 1) + self.label = QtWidgets.QLabel(parent=self.Sec2_ToolsWidget) + self.label.setMaximumSize(QtCore.QSize(16777215, 16)) + font = QtGui.QFont() + font.setFamily("Calibri") + font.setPointSize(10) + self.label.setFont(font) + self.label.setStyleSheet( + "#label{\n" " color: white;\n" " background: #717270;\n" " }" ) - self.horizontalWidget_2.setLayoutDirection( - QtCore.Qt.LayoutDirection.LeftToRight + self.label.setObjectName("label") + self.gridLayout_4.addWidget(self.label, 0, 1, 1, 1) + self.label_2 = QtWidgets.QLabel(parent=self.Sec2_ToolsWidget) + self.label_2.setMaximumSize(QtCore.QSize(16777215, 16)) + font = QtGui.QFont() + font.setFamily("Calibri") + font.setPointSize(10) + self.label_2.setFont(font) + self.label_2.setStyleSheet( + "#label_2{\n" " color: white;\n" " background: #717270;\n" " }" ) - self.horizontalWidget_2.setAutoFillBackground(False) - self.horizontalWidget_2.setStyleSheet( - "#horizontalGroupBox_2{ \n" "outline: none;\n" "}" + self.label_2.setObjectName("label_2") + self.gridLayout_4.addWidget(self.label_2, 0, 2, 1, 1) + self.SelectionListSeg = QtWidgets.QListWidget(parent=self.Sec2_ToolsWidget) + self.SelectionListSeg.setMinimumSize(QtCore.QSize(90, 0)) + self.SelectionListSeg.setMaximumSize(QtCore.QSize(100, 16777215)) + font = QtGui.QFont() + font.setPointSize(9) + self.SelectionListSeg.setFont(font) + self.SelectionListSeg.setStyleSheet( + "#SelectionListSeg\n" + "{\n" + "border: 2px solid #7C8081;\n" + "background: rgba(204, 224, 232, 0.7);\n" + "}" ) - self.horizontalWidget_2.setObjectName("horizontalWidget_2") - self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.horizontalWidget_2) - self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0) - self.horizontalLayout_2.setSpacing(1) - self.horizontalLayout_2.setObjectName("horizontalLayout_2") - self.labelStart = QtWidgets.QLabel(parent=self.horizontalWidget_2) - self.labelStart.setMaximumSize(QtCore.QSize(16777215, 16777215)) - self.labelStart.setStyleSheet("#labelStart{ color: white; }") - self.labelStart.setObjectName("labelStart") - self.horizontalLayout_2.addWidget(self.labelStart) - self.horizontalSlider = QtWidgets.QSlider(parent=self.horizontalWidget_2) - self.horizontalSlider.setMouseTracking(False) - self.horizontalSlider.setTabletTracking(False) - self.horizontalSlider.setAcceptDrops(False) - self.horizontalSlider.setAutoFillBackground(False) - self.horizontalSlider.setMinimum(30) - self.horizontalSlider.setSingleStep(1) - self.horizontalSlider.setPageStep(10) - self.horizontalSlider.setSliderPosition(90) - self.horizontalSlider.setTracking(True) - self.horizontalSlider.setOrientation(QtCore.Qt.Orientation.Horizontal) - self.horizontalSlider.setInvertedAppearance(False) - self.horizontalSlider.setInvertedControls(False) - self.horizontalSlider.setTickPosition(QtWidgets.QSlider.TickPosition.TicksBelow) - self.horizontalSlider.setTickInterval(0) - self.horizontalSlider.setObjectName("horizontalSlider") - self.horizontalLayout_2.addWidget(self.horizontalSlider) - self.gridLayout.addWidget(self.horizontalWidget_2, 5, 0, 1, 1) - self.checkBoxSeg = QtWidgets.QCheckBox(parent=self.gridGroupBox) - self.checkBoxSeg.setStyleSheet( - "\n" "background: rgba(204, 224, 232, 0.5)\n" "\n" "\n" "" + self.SelectionListSeg.setObjectName("SelectionListSeg") + self.gridLayout_4.addWidget(self.SelectionListSeg, 1, 2, 2, 1) + self.verticalLayout_5.addLayout(self.gridLayout_4) + self.ToolsBox = QtWidgets.QGroupBox(parent=self.Sec2_ToolsWidget) + self.ToolsBox.setMaximumSize(QtCore.QSize(16777215, 180)) + self.ToolsBox.setStyleSheet( + "#ToolsBox {\n" + " width: 100px;\n" + " height:100px;\n" + " border: 3px solid #1071f0;\n" + "}" ) - self.checkBoxSeg.setObjectName("checkBoxSeg") - self.gridLayout.addWidget(self.checkBoxSeg, 3, 0, 1, 1) - self.checkBoxSave = QtWidgets.QCheckBox(parent=self.gridGroupBox) - self.checkBoxSave.setStyleSheet("background: rgba(204, 224, 232, 0.5)") - self.checkBoxSave.setObjectName("checkBoxSave") - self.gridLayout.addWidget(self.checkBoxSave, 4, 0, 1, 1) - self.pushButtonStart = QtWidgets.QPushButton(parent=self.gridGroupBox) + self.ToolsBox.setObjectName("ToolsBox") + self.gridLayout = QtWidgets.QGridLayout(self.ToolsBox) + self.gridLayout.setContentsMargins(9, 3, 5, 1) + self.gridLayout.setHorizontalSpacing(9) + self.gridLayout.setVerticalSpacing(3) + self.gridLayout.setObjectName("gridLayout") + self.pushButtonStart = QtWidgets.QPushButton(parent=self.ToolsBox) self.pushButtonStart.setMinimumSize(QtCore.QSize(0, 27)) + font = QtGui.QFont() + font.setFamily("Calibri") + font.setPointSize(10) + self.pushButtonStart.setFont(font) self.pushButtonStart.setStyleSheet( "QPushButton {\n" " background-color:#4CAF50;\n" @@ -246,8 +200,12 @@ def setupUi(self, MainWindow): ) self.pushButtonStart.setObjectName("pushButtonStart") self.gridLayout.addWidget(self.pushButtonStart, 0, 0, 1, 1) - self.pushButtonSeg = QtWidgets.QPushButton(parent=self.gridGroupBox) + self.pushButtonSeg = QtWidgets.QPushButton(parent=self.ToolsBox) self.pushButtonSeg.setMinimumSize(QtCore.QSize(0, 27)) + font = QtGui.QFont() + font.setFamily("Calibri") + font.setPointSize(10) + self.pushButtonSeg.setFont(font) self.pushButtonSeg.setStyleSheet( "QPushButton {\n" " background-color:#4CAF50;\n" @@ -263,8 +221,30 @@ def setupUi(self, MainWindow): ) self.pushButtonSeg.setObjectName("pushButtonSeg") self.gridLayout.addWidget(self.pushButtonSeg, 1, 0, 1, 1) - self.pushButtonSave = QtWidgets.QPushButton(parent=self.gridGroupBox) + self.checkBoxSave = QtWidgets.QCheckBox(parent=self.ToolsBox) + font = QtGui.QFont() + font.setFamily("Calibri") + font.setPointSize(9) + self.checkBoxSave.setFont(font) + self.checkBoxSave.setStyleSheet("background: rgba(204, 224, 232, 0.5)") + self.checkBoxSave.setObjectName("checkBoxSave") + self.gridLayout.addWidget(self.checkBoxSave, 4, 0, 1, 1) + self.checkBoxSeg = QtWidgets.QCheckBox(parent=self.ToolsBox) + font = QtGui.QFont() + font.setFamily("Calibri") + font.setPointSize(9) + self.checkBoxSeg.setFont(font) + self.checkBoxSeg.setStyleSheet( + "\n" "background: rgba(204, 224, 232, 0.5)\n" "\n" "\n" "" + ) + self.checkBoxSeg.setObjectName("checkBoxSeg") + self.gridLayout.addWidget(self.checkBoxSeg, 3, 0, 1, 1) + self.pushButtonSave = QtWidgets.QPushButton(parent=self.ToolsBox) self.pushButtonSave.setMinimumSize(QtCore.QSize(0, 27)) + font = QtGui.QFont() + font.setFamily("Calibri") + font.setPointSize(10) + self.pushButtonSave.setFont(font) self.pushButtonSave.setStyleSheet( "QPushButton {\n" " background-color:#4CAF50;\n" @@ -280,30 +260,214 @@ def setupUi(self, MainWindow): ) self.pushButtonSave.setObjectName("pushButtonSave") self.gridLayout.addWidget(self.pushButtonSave, 2, 0, 1, 1) - self.label = QtWidgets.QLabel(parent=self.gridGroupBox) - self.label.setMinimumSize(QtCore.QSize(0, 0)) - self.label.setMaximumSize(QtCore.QSize(100, 10)) - self.label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) - self.label.setObjectName("label") - self.gridLayout.addWidget(self.label, 6, 0, 1, 1) - self.vboxlayout.addWidget(self.gridGroupBox) - self.verticalLayout.addWidget(self.verticalGroupBox) - MainWindow.setCentralWidget(self.centralwidget) + self.verticalGroupBox_2 = QtWidgets.QGroupBox(parent=self.ToolsBox) + self.verticalGroupBox_2.setMouseTracking(False) + self.verticalGroupBox_2.setTabletTracking(False) + self.verticalGroupBox_2.setAcceptDrops(False) + self.verticalGroupBox_2.setAutoFillBackground(False) + self.verticalGroupBox_2.setStyleSheet( + "#verticalGroupBox_2 {\n" "border: 2px inset #1071f0;\n" "}" + ) + self.verticalGroupBox_2.setTitle("") + self.verticalGroupBox_2.setFlat(False) + self.verticalGroupBox_2.setCheckable(False) + self.verticalGroupBox_2.setObjectName("verticalGroupBox_2") + self.gridLayout_3 = QtWidgets.QGridLayout(self.verticalGroupBox_2) + self.gridLayout_3.setContentsMargins(2, 2, 2, 2) + self.gridLayout_3.setSpacing(2) + self.gridLayout_3.setObjectName("gridLayout_3") + self.InfTools_ = QtWidgets.QFrame(parent=self.verticalGroupBox_2) + self.InfTools_.setStyleSheet( + "#InfTools_\n" "{\n" "border: 0px solid #7C8081;\n" "}" + ) + self.InfTools_.setObjectName("InfTools_") + self.InfTools = QtWidgets.QVBoxLayout(self.InfTools_) + self.InfTools.setContentsMargins(0, 0, 0, 0) + self.InfTools.setSpacing(5) + self.InfTools.setObjectName("InfTools") + self.DataLabel = QtWidgets.QLabel(parent=self.InfTools_) + self.DataLabel.setMinimumSize(QtCore.QSize(0, 0)) + self.DataLabel.setMaximumSize(QtCore.QSize(16777215, 90)) + font = QtGui.QFont() + font.setFamily("Calibri") + font.setPointSize(9) + font.setBold(False) + font.setWeight(50) + self.DataLabel.setFont(font) + self.DataLabel.setAutoFillBackground(False) + self.DataLabel.setStyleSheet( + "#DataLabel\n" + "{\n" + "border: 2px solid #7C8081;\n" + "background: #D9DFE2;\n" + "}" + ) + self.DataLabel.setText("") + self.DataLabel.setObjectName("DataLabel") + self.InfTools.addWidget(self.DataLabel) + self.DataLabel_2 = QtWidgets.QLabel(parent=self.InfTools_) + font = QtGui.QFont() + font.setFamily("Calibri") + font.setPointSize(9) + self.DataLabel_2.setFont(font) + self.DataLabel_2.setStyleSheet( + "#DataLabel_2\n" + "{\n" + "border: 2px solid #7C8081;\n" + "background: #D9DFE2;\n" + "}" + ) + self.DataLabel_2.setText("") + self.DataLabel_2.setObjectName("DataLabel_2") + self.InfTools.addWidget(self.DataLabel_2) + self.gridLayout_3.addWidget(self.InfTools_, 0, 2, 3, 1) + self.gridLayout.addWidget(self.verticalGroupBox_2, 0, 1, 10, 1) + self.AccuracyWidget = QtWidgets.QWidget(parent=self.ToolsBox) + self.AccuracyWidget.setMinimumSize(QtCore.QSize(0, 0)) + self.AccuracyWidget.setMaximumSize(QtCore.QSize(200, 16777215)) + self.AccuracyWidget.setContextMenuPolicy( + QtCore.Qt.ContextMenuPolicy.PreventContextMenu + ) + self.AccuracyWidget.setLayoutDirection(QtCore.Qt.LayoutDirection.LeftToRight) + self.AccuracyWidget.setAutoFillBackground(False) + self.AccuracyWidget.setStyleSheet("") + self.AccuracyWidget.setObjectName("AccuracyWidget") + self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.AccuracyWidget) + self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout_2.setSpacing(1) + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.AccuracyText = QtWidgets.QLabel(parent=self.AccuracyWidget) + self.AccuracyText.setMaximumSize(QtCore.QSize(16777215, 16777215)) + font = QtGui.QFont() + font.setFamily("Calibri") + font.setPointSize(8) + self.AccuracyText.setFont(font) + self.AccuracyText.setStyleSheet("#AccuracyText{ color: white; }") + self.AccuracyText.setObjectName("AccuracyText") + self.horizontalLayout_2.addWidget(self.AccuracyText) + self.AccuracySlider = QtWidgets.QSlider(parent=self.AccuracyWidget) + self.AccuracySlider.setMouseTracking(False) + self.AccuracySlider.setTabletTracking(False) + self.AccuracySlider.setAcceptDrops(False) + self.AccuracySlider.setAutoFillBackground(False) + self.AccuracySlider.setMinimum(30) + self.AccuracySlider.setSingleStep(1) + self.AccuracySlider.setPageStep(10) + self.AccuracySlider.setSliderPosition(90) + self.AccuracySlider.setTracking(True) + self.AccuracySlider.setOrientation(QtCore.Qt.Orientation.Horizontal) + self.AccuracySlider.setInvertedAppearance(False) + self.AccuracySlider.setInvertedControls(False) + self.AccuracySlider.setTickPosition(QtWidgets.QSlider.TickPosition.TicksBelow) + self.AccuracySlider.setTickInterval(0) + self.AccuracySlider.setObjectName("AccuracySlider") + self.horizontalLayout_2.addWidget(self.AccuracySlider) + self.gridLayout.addWidget(self.AccuracyWidget, 5, 0, 1, 1) + self.AccuracyLable = QtWidgets.QLabel(parent=self.ToolsBox) + self.AccuracyLable.setMinimumSize(QtCore.QSize(0, 0)) + self.AccuracyLable.setMaximumSize(QtCore.QSize(100, 10)) + font = QtGui.QFont() + font.setFamily("Calibri") + font.setPointSize(9) + self.AccuracyLable.setFont(font) + self.AccuracyLable.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) + self.AccuracyLable.setObjectName("AccuracyLable") + self.gridLayout.addWidget(self.AccuracyLable, 6, 0, 1, 1) + self.verticalLayout_5.addWidget(self.ToolsBox) + self.gridLayout_2.addWidget(self.Sec2_ToolsWidget, 1, 1, 2, 1) + self.Sec1_ImageWidget = QtWidgets.QWidget(parent=self.CentralGroupBox) + self.Sec1_ImageWidget.setStyleSheet( + "#Sec1_ImageWidget\n" + "{\n" + " border: 4px outset rgba(204, 224, 232, 0);\n" + " background: rgba(204, 224, 232, 0);\n" + "}" + ) + self.Sec1_ImageWidget.setObjectName("Sec1_ImageWidget") + self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.Sec1_ImageWidget) + self.verticalLayout_4.setContentsMargins(0, 0, 0, 0) + self.verticalLayout_4.setSpacing(0) + self.verticalLayout_4.setObjectName("verticalLayout_4") + self.tabWidget = QtWidgets.QTabWidget(parent=self.Sec1_ImageWidget) + font = QtGui.QFont() + font.setFamily("Calibri") + font.setPointSize(10) + self.tabWidget.setFont(font) + self.tabWidget.setStyleSheet( + "QTabWidget::pane{ \n" + " border: 4px outset rgba(204, 224, 232, 0.5);\n" + " background: rgba(204, 224, 232, 0);\n" + "\n" + "} \n" + "\n" + "QTabBar::tab { \n" + " border: 4px outset rgba(204, 224, 232, 0.5);\n" + " background: rgba(217, 223, 226, 0.8);\n" + " padding: 10px;\n" + " width: 100%;\n" + "\n" + "}\n" + "\n" + "QTabBar::tab:selected { \n" + " background: #8E979A; \n" + "}\n" + "\n" + "\n" + "\n" + "\n" + "" + ) + self.tabWidget.setMovable(False) + self.tabWidget.setTabBarAutoHide(True) + self.tabWidget.setObjectName("tabWidget") + self.tab = QtWidgets.QWidget() + self.tab.setStyleSheet("") + self.tab.setObjectName("tab") + self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.tab) + self.verticalLayout_3.setContentsMargins(5, 5, 5, 5) + self.verticalLayout_3.setSpacing(7) + self.verticalLayout_3.setObjectName("verticalLayout_3") + self.PlaceForFotos = QtWidgets.QLabel(parent=self.tab) + font = QtGui.QFont() + font.setBold(False) + font.setWeight(50) + self.PlaceForFotos.setFont(font) + self.PlaceForFotos.setStyleSheet( + "#PlaceForFotos\n" "{\n" "border: 4px inset #10f0ad;\n" "\n" "}" + ) + self.PlaceForFotos.setFrameShape(QtWidgets.QFrame.Shape.Box) + self.PlaceForFotos.setScaledContents(True) + self.PlaceForFotos.setObjectName("PlaceForFotos") + self.verticalLayout_3.addWidget(self.PlaceForFotos) + self.tabWidget.addTab(self.tab, "") + self.tab_2 = QtWidgets.QWidget() + self.tab_2.setStyleSheet("") + self.tab_2.setObjectName("tab_2") + self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.tab_2) + self.verticalLayout_2.setContentsMargins(5, 5, 5, 5) + self.verticalLayout_2.setObjectName("verticalLayout_2") + self.PlaceForPromFotos = ClickableLabel(parent=self.tab_2) + self.PlaceForPromFotos.setStyleSheet( + "#PlaceForPromFotos\n" "{\n" "border: 4px outset #10f0e9;\n" "\n" "}" + ) + self.PlaceForPromFotos.setFrameShape(QtWidgets.QFrame.Shape.Box) + self.PlaceForPromFotos.setScaledContents(True) + self.PlaceForPromFotos.setObjectName("PlaceForPromFotos") + self.verticalLayout_2.addWidget(self.PlaceForPromFotos) + self.tabWidget.addTab(self.tab_2, "") + self.verticalLayout_4.addWidget(self.tabWidget) + self.gridLayout_2.addWidget(self.Sec1_ImageWidget, 1, 2, 2, 1) + self.verticalLayout.addWidget(self.CentralGroupBox) + MainWindow.setCentralWidget(self.CentralWidget) self.retranslateUi(MainWindow) + self.tabWidget.setCurrentIndex(0) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "FISH data processing")) - self.PlaceForFotos.setText( - _translate( - "MainWindow", "Исходное изображение, в формате .jpeg, png или .czi" - ) - ) - self.PlaceForPromFotos.setText( - _translate("MainWindow", "Результат сегментации") - ) + self.SelectionList.setSortingEnabled(False) item = self.SelectionTable.horizontalHeaderItem(0) item.setText(_translate("MainWindow", "Номер клетки")) item = self.SelectionTable.horizontalHeaderItem(1) @@ -316,13 +480,29 @@ def retranslateUi(self, MainWindow): item.setText(_translate("MainWindow", "Красные х-мы")) item = self.SelectionTable.horizontalHeaderItem(5) item.setText(_translate("MainWindow", "Тип клетки")) - self.labelStart.setText(_translate("MainWindow", "Порог точности: ")) - self.checkBoxSeg.setText(_translate("MainWindow", "Сегментировать все")) - self.checkBoxSave.setText(_translate("MainWindow", "Сохранить все")) + self.label.setText(_translate("MainWindow", "Изображения:")) + self.label_2.setText(_translate("MainWindow", "Результат:")) self.pushButtonStart.setText(_translate("MainWindow", "Выбрать фото")) self.pushButtonSeg.setText(_translate("MainWindow", "Cегментировать")) + self.checkBoxSave.setText(_translate("MainWindow", "Сохранить все")) + self.checkBoxSeg.setText(_translate("MainWindow", "Сегментировать все")) self.pushButtonSave.setText(_translate("MainWindow", "Сохранить")) - self.label.setText(_translate("MainWindow", "0.9")) + self.AccuracyText.setText(_translate("MainWindow", "Порог точности: ")) + self.AccuracyLable.setText(_translate("MainWindow", "0.9")) + self.PlaceForFotos.setText( + _translate( + "MainWindow", "Исходное изображение, в формате .jpeg, png или .czi" + ) + ) + self.tabWidget.setTabText( + self.tabWidget.indexOf(self.tab), _translate("MainWindow", "Изображение") + ) + self.PlaceForPromFotos.setText( + _translate("MainWindow", "Результат сегментации") + ) + self.tabWidget.setTabText( + self.tabWidget.indexOf(self.tab_2), _translate("MainWindow", "Результат") + ) if __name__ == "__main__": diff --git a/FISH_segmentation/Application_Qt/Application_Qt_module_ui.ui b/FISH_segmentation/Application_Qt/Application_Qt_module_ui.ui index 6972fc9..d762671 100644 --- a/FISH_segmentation/Application_Qt/Application_Qt_module_ui.ui +++ b/FISH_segmentation/Application_Qt/Application_Qt_module_ui.ui @@ -6,8 +6,8 @@ 0 0 - 1078 - 691 + 1147 + 772 @@ -23,9 +23,6 @@ :/resources/icon.ico:/resources/icon.ico - - false - #MainWindow { @@ -40,352 +37,444 @@ background-size: 100% 100%; - - true - - - false - - - false - - - false - - + - #centralwidget {background-color: transparent;} + #CentralWidget {background-color: transparent;} - + false - - false - - #verticalGroupBox { -border: 1px inset #10f04f; -border-radius: 10px; + #CentralGroupBox { +border: 3px inset #94D9DC; } - - false - - - false - - - - - - Qt::NoContextMenu + + + 5 + + + 5 + + + 5 + + + 5 + + + 5 + + + + + + 16777215 + 16777215 + - #horizontalGroupBox { -border: 1px inset #10f04f; -} + - + - 10 + 4 - 5 + 0 - 0 + 1 - 5 + 0 0 - - - #PlaceForFotos + + + 3 + + + + + + 90 + 0 + + + + + 100 + 16777215 + + + + false + + + false + + + false + + + false + + + #SelectionList { -border: 4px inset #10f0ad; - +border: 2px solid #7C8081; +background: rgba(204, 224, 232, 0.7); } - - - QFrame::Box - - - Исходное изображение, в формате .jpeg, png или .czi - - - - - - - #PlaceForPromFotos + + + false + + + false + + + + + + + + Calibri + 10 + 75 + false + true + + + + false + + + #SelectionTable { -border: 4px outset #10f0e9; - + border: 4px outset rgba(204, 224, 232, 0.7); + background: rgba(217, 223, 226, 0.8); +} +QHeaderView::section { + background-color: rgba(204, 224, 232, 0.5); + } +QTableWidget::item { + font-weight: bold; } - - - QFrame::Box - - - Результат сегментации - - - - - - - - - - - 16777215 - 185 - - - - #gridGroupBox { - width: 100px; - height:100px; - border: 3px solid #1071f0; - border-radius: 15px; + + + 0 + + + 6 + + + false + + + 90 + + + true + + + false + + + true + + + false + + + true + + + + Номер клетки + + + + + Центр X + + + + + Центр Y + + + + + Зеленые х-мы + + + + + Красные х-мы + + + + + Тип клетки + + + + + + + + + 16777215 + 16 + + + + + Calibri + 10 + + + + #label{ + color: white; + background: #717270; + } + + + Изображения: + + + + + + + + 16777215 + 16 + + + + + Calibri + 10 + + + + #label_2{ + color: white; + background: #717270; + } + + + Результат: + + + + + + + + 90 + 0 + + + + + 100 + 16777215 + + + + + 9 + + + + #SelectionListSeg +{ +border: 2px solid #7C8081; +background: rgba(204, 224, 232, 0.7); } - - - - 9 - - - 3 - - - 5 - - - 1 - - - 9 - - - 3 - - - - - false - - - false - - - false - - - false + + + + + + + + + + 16777215 + 180 + - #verticalGroupBox_2 { -border: 1px inset #1071f0; -border-radius: 10px; + #ToolsBox { + width: 100px; + height:100px; + border: 3px solid #1071f0; } - - - - - false - - - false - - - - + + + 9 + + + 3 + + + 5 + + + 1 + + + 9 + + + 3 + + + - 150 - 0 + 0 + 27 - 12 + Calibri + 10 - - false - - + QPushButton { + background-color:#4CAF50; + color: white; + border: 1px solid gray; + border-radius: 7px; +} + +QPushButton:pressed { + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #49c44d, stop: 1 #6cd470); +} - + Выбрать фото - - - + + + - 100 - 16777215 + 0 + 27 + + + Calibri + 10 + + - #SelectionList -{ -border: 4px rgba(204, 224, 232, 0.5); -background: rgba(204, 224, 232, 0.5); + QPushButton { + background-color:#4CAF50; + color: white; + border: 1px solid gray; + border-radius: 7px; +} + +QPushButton:pressed { + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #49c44d, stop: 1 #6cd470); } + + Cегментировать + - - - - false + + + + + Calibri + 9 + - #SelectionTable -{ -border: 4px rgba(204, 224, 232, 0.5); -background: rgba(204, 224, 232, 0.5); -} -QHeaderView::section { -background-color: rgba(204, 224, 232, 0.5); - } + background: rgba(204, 224, 232, 0.5) - - 0 + + Сохранить все - - 6 + + + + + + + Calibri + 9 + + + + +background: rgba(204, 224, 232, 0.5) + + + + + + Сегментировать все - - false - - - 90 - - - true - - - false - - - true - - - false - - - true - - - - Номер клетки - - - - - Центр X - - - - - Центр Y - - - - - Зеленые х-мы - - - - - Красные х-мы - - - - - Тип клетки - - - - - - - - - - 0 - 0 - - - - - 200 - 16777215 - - - - Qt::PreventContextMenu - - - Qt::LeftToRight - - - false - - - #horizontalGroupBox_2{ -outline: none; -} - - - - 1 - - - 0 - - - 0 - - - 0 - - - 0 - - - - + + + - 16777215 - 16777215 + 0 + 27 + + + Calibri + 10 + + - #labelStart{ color: white; } + QPushButton { + background-color:#4CAF50; + color: white; + border: 1px solid gray; + border-radius: 7px; +} + +QPushButton:pressed { + background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, + stop: 0 #49c44d, stop: 1 #6cd470); +} - Порог точности: + Сохранить - - + + false @@ -398,163 +487,429 @@ outline: none; false - - 30 + + #verticalGroupBox_2 { +border: 2px inset #1071f0; +} + + + + + + false - - 1 + + false - - 10 + + + 2 + + + 2 + + + 2 + + + 2 + + + 2 + + + + + #InfTools_ +{ +border: 0px solid #7C8081; +} + + + + 5 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 16777215 + 90 + + + + + Calibri + 9 + 50 + false + + + + false + + + #DataLabel +{ +border: 2px solid #7C8081; +background: #D9DFE2; +} + + + + + + + + + + + Calibri + 9 + + + + #DataLabel_2 +{ +border: 2px solid #7C8081; +background: #D9DFE2; +} + + + + + + + + + + + + + + + + + 0 + 0 + - - 90 + + + 200 + 16777215 + - - true + + Qt::PreventContextMenu - - Qt::Horizontal + + Qt::LeftToRight - + false - - false + + - - QSlider::TicksBelow + + + 1 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 16777215 + 16777215 + + + + + Calibri + 8 + + + + #AccuracyText{ color: white; } + + + Порог точности: + + + + + + + false + + + false + + + false + + + false + + + 30 + + + 1 + + + 10 + + + 90 + + + true + + + Qt::Horizontal + + + false + + + false + + + QSlider::TicksBelow + + + 0 + + + + + + + + + + + 0 + 0 + - - 0 + + + 100 + 10 + + + + + Calibri + 9 + + + + 0.9 + + + Qt::AlignCenter - - + + + + + + + #Sec1_ImageWidget +{ + border: 4px outset rgba(204, 224, 232, 0); + background: rgba(204, 224, 232, 0); +} + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + Calibri + 10 + + - -background: rgba(204, 224, 232, 0.5) + QTabWidget::pane{ + border: 4px outset rgba(204, 224, 232, 0.5); + background: rgba(204, 224, 232, 0); +} - - - - Сегментировать все - - - - - - - background: rgba(204, 224, 232, 0.5) - - - Сохранить все - - - - - - - - 0 - 27 - - - - QPushButton { - background-color:#4CAF50; - color: white; - border: 1px solid gray; - border-radius: 7px; -} +QTabBar::tab { + border: 4px outset rgba(204, 224, 232, 0.5); + background: rgba(217, 223, 226, 0.8); + padding: 10px; + width: 100%; -QPushButton:pressed { - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #49c44d, stop: 1 #6cd470); -} - - - Выбрать фото - - - - - - - - 0 - 27 - - - - QPushButton { - background-color:#4CAF50; - color: white; - border: 1px solid gray; - border-radius: 7px; } -QPushButton:pressed { - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #49c44d, stop: 1 #6cd470); -} - - - Cегментировать - - - - - - - - 0 - 27 - - - - QPushButton { - background-color:#4CAF50; - color: white; - border: 1px solid gray; - border-radius: 7px; +QTabBar::tab:selected { + background: #8E979A; } -QPushButton:pressed { - background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, - stop: 0 #49c44d, stop: 1 #6cd470); -} - - - Сохранить - - - - - - - - 0 - 0 - + + + + - - - 100 - 10 - + + 0 - - 0.9 + + false - - Qt::AlignCenter + + true + + + + + + Изображение + + + + 7 + + + 5 + + + 5 + + + 5 + + + 5 + + + + + + 50 + false + + + + #PlaceForFotos +{ +border: 4px inset #10f0ad; + +} + + + QFrame::Box + + + Исходное изображение, в формате .jpeg, png или .czi + + + true + + + + + + + + + + + Результат + + + + 5 + + + 5 + + + 5 + + + 5 + + + + + #PlaceForPromFotos +{ +border: 4px outset #10f0e9; + +} + + + QFrame::Box + + + Результат сегментации + + + true + + + + + @@ -566,6 +921,13 @@ QPushButton:pressed { + + + ClickableLabel + QLabel +
ClickableLabel.h
+
+
diff --git a/FISH_segmentation/Application_Qt/ChromosomePatch.py b/FISH_segmentation/Application_Qt/ChromosomePatch.py index 9a48948..af60d41 100644 --- a/FISH_segmentation/Application_Qt/ChromosomePatch.py +++ b/FISH_segmentation/Application_Qt/ChromosomePatch.py @@ -53,6 +53,7 @@ def __init__(self, image: np.ndarray): self.image: np.ndarray = image self.cells: list[Cell] = [] self.Radius = [] + self.MyMask = [] def plot(self, ax=None): ax.imshow(self.image) @@ -60,6 +61,7 @@ def plot(self, ax=None): mask = np.invert(cell.masked_area.mask[..., 0]).astype(np.uint8) contour_color = 'green' if cell.cell_type == Cell.CellType.WHOLE else 'red' ax.contour(mask, colors=contour_color, linewidths=0.5, alpha=0.5) + self.MyMask.append(mask) for p in cell.red_chromosomes: circle = plt.Circle((p[1], p[0]), radius=3, color='red', fill=False, linestyle='--') @@ -68,21 +70,7 @@ def plot(self, ax=None): for p in cell.green_chromosomes: circle = plt.Circle((p[1], p[0]), radius=3, color='green', fill=False, linestyle='--') ax.add_patch(circle) - return ax - - def rgba2rgb(self, rgba, background=(255, 255, 255)): - row, col, ch = rgba.shape - if ch == 3: - return rgba - assert ch == 4, 'RGBA image has 4 channels.' - rgb = np.zeros((row, col, 3), dtype='float32') - r, g, b, a = rgba[:, :, 0], rgba[:, :, 1], rgba[:, :, 2], rgba[:, :, 3] - a = np.asarray(a, dtype='float32') / 255.0 - R, G, B = background - rgb[:, :, 0] = r * a + (1.0 - a) * R - rgb[:, :, 1] = g * a + (1.0 - a) * G - rgb[:, :, 2] = b * a + (1.0 - a) * B - return np.asarray(rgb, dtype='uint8') + return ax, self.MyMask def find_cells(self, confidence: float = 0.5): if self.cells: diff --git a/FISH_segmentation/Application_Qt/ClickableLabel.py b/FISH_segmentation/Application_Qt/ClickableLabel.py new file mode 100644 index 0000000..839cba8 --- /dev/null +++ b/FISH_segmentation/Application_Qt/ClickableLabel.py @@ -0,0 +1,24 @@ +from PyQt6.QtCore import pyqtSignal +from PyQt6.QtWidgets import QLabel + + +# Класс, необходимый для переопределения метода "mousePressEvent"; +class ClickableLabel(QLabel): + # Создаем новый сигнал; + clicked = pyqtSignal(float, float) + + def __init__(self, parent=None): + super(ClickableLabel, self).__init__(parent) + + def mousePressEvent(self, event): + # Учет растяжения картинки в окне: + pos = self.mapFromParent(event.position()) + label_size = self.size() + scale_x = 512 / label_size.width() + scale_y = 512 / label_size.height() + original_x = pos.x() * scale_x + original_y = pos.y() * scale_y + # print(f"Координаты на исходном изображении: ({original_x}, {original_y})") + + # Излучаем сигнал при нажатии кнопки мыши; + self.clicked.emit(original_x, original_y) diff --git a/FISH_segmentation/Application_Qt/resources/Background4.jpg b/FISH_segmentation/Application_Qt/resources/Background4.jpg index e7a5fbe..d0ee3c4 100644 Binary files a/FISH_segmentation/Application_Qt/resources/Background4.jpg and b/FISH_segmentation/Application_Qt/resources/Background4.jpg differ diff --git a/FISH_segmentation/Example_czi_imege/Snap-1633.czi b/FISH_segmentation/Example_czi_imege/Snap-1633.czi new file mode 100644 index 0000000..e3153fd Binary files /dev/null and b/FISH_segmentation/Example_czi_imege/Snap-1633.czi differ diff --git a/FISH_segmentation/Example_czi_imege/Snap-1634.czi b/FISH_segmentation/Example_czi_imege/Snap-1634.czi new file mode 100644 index 0000000..b2aa001 Binary files /dev/null and b/FISH_segmentation/Example_czi_imege/Snap-1634.czi differ diff --git a/FISH_segmentation/Example_czi_imege/Snap-1635.czi b/FISH_segmentation/Example_czi_imege/Snap-1635.czi new file mode 100644 index 0000000..c0c4d06 Binary files /dev/null and b/FISH_segmentation/Example_czi_imege/Snap-1635.czi differ diff --git a/FISH_segmentation/Example_czi_imege/Snap-1636.czi b/FISH_segmentation/Example_czi_imege/Snap-1636.czi new file mode 100644 index 0000000..85ff7f1 Binary files /dev/null and b/FISH_segmentation/Example_czi_imege/Snap-1636.czi differ diff --git a/FISH_segmentation/Example_czi_imege/Snap-1637.czi b/FISH_segmentation/Example_czi_imege/Snap-1637.czi new file mode 100644 index 0000000..1cbfb11 Binary files /dev/null and b/FISH_segmentation/Example_czi_imege/Snap-1637.czi differ