Как получить доступ к нарисованному QPainter?

Пишу на Python программу, которая выводит на QLabel фотографию при помощи QPainter.drawPixmap, чтобы потом рисовать на ней мышью произвольные каляки-маляки (закрашенные полигоны).

Конечная задача состоит в том, чтобы посчитать площадь закрашенных красным полигонов:

введите сюда описание изображения

Не нашёл варианта лучше, чем тупо пересчитать пиксели определённого цвета.

Подскажите пожалуйста, каким образом можно получить доступ к художествам, нарисованным QPainter.

Привожу код класса MegaLabel, который я сделал, чтобы реализовать обработку нажатия и выделения мышью над QLabel:

    # This Python file uses the following encoding: utf-8
    from PyQt5 import QtWidgets
    from PyQt5.QtGui import QPixmap, QPainter, QPolygon, QPen, QBrush
    from PyQt5.QtCore import Qt
    
    
    class MegaLabel(QtWidgets.QLabel):
        def __init__(self, parent=None):
            super(MegaLabel, self).__init__(parent=parent)
            self.selected_line = []  # отдельный выделенный пользлвателем полигон
            self.selected_lines = []  # массив всех полигонов
            self.image = QPixmap()  # картинка, на фоне которой происходит рисование
            self.scale_factor = 1.0  # отношение размера отображаемой картинки к реальному
    
        def paintEvent(self, event):
            painter = QPainter(self)
    
            if not self.image.isNull():  # отображение фоновой картинки
                painter.drawPixmap(self.rect(), self.image)
    
            painter.setPen(QPen(Qt.red, 5, Qt.SolidLine))
            painter.setBrush(QBrush(Qt.red, Qt.SolidPattern))
    
            # Отрисовка всех уже залитых полигонов
            for i in range(len(self.selected_lines)):  # преобразование координат от 1:1 к отображаемым
                transformed_line = [j * self.scale_factor for j in self.selected_lines[i]]
                painter.drawPolygon(QPolygon(transformed_line))
    
            # Отображение линии в процессе рисования
            transformed_line = [j * self.scale_factor for j in self.selected_line] # преобразование координат от 1:1 к отображаемым
            painter.drawPolyline(QPolygon(transformed_line))
    
        def mousePressEvent(self, event):  # при нажатии левой кнопкой начинают записываться координаты нового полигона
            if event.buttons() & Qt.LeftButton:
                self.selected_line = []
    
        def mouseMoveEvent(self, event):  # при нажатой кнопке происходит запись координат
            if event.buttons() & Qt.LeftButton:
                # Координаты выделения приводятся к координатам фонового рисунка в масштабе 1:1
                self.selected_line.append(event.pos() / self.scale_factor)
                self.update()
    
        def mouseReleaseEvent(self, event):  # при отпускании кнопки список координат полигона передаётся в массив полигонов
            if event.button() & Qt.LeftButton:
                self.selected_lines.append(self.selected_line)
                self.update()

Ответы (1 шт):

Автор решения: pupinho

В итоге всё решилось отрисовкой на QImage, которая потом отрисовывалась на QLabel, код при этом упростился:

    from PyQt5 import QtWidgets
    from PyQt5.QtGui import QPainter, QPolygon, QPen, QBrush, QImage
    from PyQt5.QtCore import Qt
    
    
    class MegaLabel(QtWidgets.QLabel):
        def __init__(self, parent=None):
            super(MegaLabel, self).__init__(parent=parent)
            self.selected_line = []  # координаты полигона
            self.image = QImage()  # картинка, на которой происходит рисование
            self.scale_factor = 1.00  # отношение размера отображаемой картинки к реальному
    
        def paintEvent(self, event):
            painter = QPainter(self)
            if not self.image.isNull():
                painter.drawImage(self.rect(), self.image)
    
        def mousePressEvent(self, event):  # при нажатии левой кнопкой начинают записываться координаты нового полигона
            if event.buttons() & Qt.LeftButton:
                self.selected_line = []
    
        def mouseMoveEvent(self, event):  # при нажатой кнопке происходит запись координат
            if event.buttons() & Qt.LeftButton:
                impainter = QPainter(self.image)  # QPainter для image
                self.selected_line.append(event.pos() / self.scale_factor)  # Координаты выделения приводятся к координатам фонового рисунка в масштабе 1:1
                impainter.setPen(QPen(Qt.red, 5, Qt.SolidLine))
                impainter.setBrush(QBrush(Qt.red, Qt.SolidPattern))
                impainter.drawPolyline(QPolygon(self.selected_line))
                self.update()
    
        def mouseReleaseEvent(self, event):  # при отпускании кнопки список координат полигона передаётся в массив полигонов
            if event.button() & Qt.LeftButton:
                impainter = QPainter(self.image)  # QPainter для image
                impainter.setPen(QPen(Qt.red, 5, Qt.SolidLine))
                impainter.setBrush(QBrush(Qt.red, Qt.SolidPattern))
                impainter.drawPolygon(QPolygon(self.selected_line))
                self.update()

QImage поддерживает требуемые операции, в том числе, на ней можно пересчитать пиксели требуемого цвета.

→ Ссылка