Как нарисовать QGraphicsItems со сцены на QImage, не изменяя их в QGraphicsScene? - PullRequest
0 голосов
/ 18 июня 2020

Я конвертирую QGraphicsItem в растеризованные маски в месте их расположения в QGraphicsScene. Я использую эти маски для дальнейшей обработки видео (принимая среднюю интенсивность внутри маски). Чтобы добиться этого, я раскрашиваю каждый элемент сцены один за другим на QImage, размер которого достаточно велик, чтобы охватить элемент. Все работает достаточно хорошо, но предметы в сцене исчезают. Это потому, что я снимаю ручку с предмета, когда рисую его на QImage. Когда закончу, я возвращаю исходное перо, но предметы больше не появляются на сцене. Как я могу "обновить sh" сцену, чтобы элементы снова появились, или, альтернативно, предотвратить полное исчезновение формы элементов? Так что, может, я просто делаю что-то в корне не так. Любые предложения приветствуются.

Вот мой код:

class MyThread(QtCore.QThread):
    def __init__(self, scene):
        super().__init__()
        self.scene = scene

    def run(self):
        for item in self.scene.items():
            # Render the ROI item to create a rasterized mask.
            qimage = self.qimage_from_shape_item(item)
            # do some stuff

    @staticmethod
    def qimage_from_shape_item(item: QtWidgets.QAbstractGraphicsShapeItem) -> QtGui.QImage:
        # Get items pen and brush to set back later.
        pen = item.pen()
        brush = item.brush()
        # Remove pen, set brush to white.
        item.setPen(QtGui.QPen(QtCore.Qt.NoPen))
        item.setBrush(QtCore.Qt.white)

        # Determine the bounding box in pixel coordinates.
        top = int(item.scenePos().y() + item.boundingRect().top())
        left = int(item.scenePos().x() + item.boundingRect().left())
        bottom = int(item.scenePos().y() + item.boundingRect().bottom()) + 1
        right = int(item.scenePos().x() + item.boundingRect().right()) + 1

        size = QtCore.QSize(right - left, bottom - top)

        # Initialize qimage, use 8-bit grayscale.
        qimage = QtGui.QImage(size, QtGui.QImage.Format_Grayscale8)
        qimage.fill(QtCore.Qt.transparent)
        painter = QtGui.QPainter(qimage)

        painter.setRenderHint(QtGui.QPainter.Antialiasing)

        # Offset the painter to paint item in its correct pixel location.
        painter.translate(item.scenePos().x() - left, item.scenePos().y() - top)

        # Paint the item.
        item.paint(painter, QtWidgets.QStyleOptionGraphicsItem())

        # Set the pen and brush back.
        item.setPen(pen)
        item.setBrush(brush)

        # Set the pixel coordinate offset of the item to the QImage.
        qimage.setOffset(QtCore.QPoint(left, top))

        return qimage


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)

    widget = QtWidgets.QWidget()
    layout = QtWidgets.QVBoxLayout(widget)

    view = QtWidgets.QGraphicsView()
    layout.addWidget(view)

    scene = QtWidgets.QGraphicsScene()
    view.setScene(scene)
    thread = MyThread(scene)

    view.setFixedSize(400, 300)
    scene.setSceneRect(0, 0, 400, 300)

    rect_item = QtWidgets.QGraphicsRectItem()

    p = QtCore.QPointF(123.4, 56.78)
    rect_item.setPos(p)

    r = QtCore.QRectF(0., 0., 161.8, 100.)
    rect_item.setRect(r)

    scene.addItem(rect_item)

    button = QtWidgets.QPushButton("Get masks")
    layout.addWidget(button)

    button.clicked.connect(thread.start)

    widget.show()

    sys.exit(app.exec_())

1 Ответ

0 голосов
/ 23 июня 2020

Проблема в том, что вы «можете создавать и использовать только GUI виджеты в основном потоке», см. Дополнительную информацию в этом SO-ответе здесь .

Я решил, что это было чтобы взять часть взаимодействия GUI, то есть qimage_from_shape_item (), из потока и обработать ее в основном l oop. Я полагаю, что все еще не очень хорошо, что я использую элементы напрямую, хотя нет видимого эффекта мерцания или чего-то еще от временной установки NoPen.

Альтернативой могло бы быть использование QGraphicsScene :: render ; однако я не знаю, как визуализировать элементы один за другим, не взаимодействуя с другими элементами сцены.

...