如何裁剪在具有旋转QGraphicsRectItem的场景上设置的QPixmap?

2024-05-15 00:14:37 发布

您现在位置:Python中文网/ 问答频道 /正文

我不知道如何裁剪在场景中设置的QPixmap,旋转的QGraphicsRectItem也放置在同一场景中

这是我的QGraphicscene和QPixmap的代码

class crop_pattern(QGraphicsView):
    img_is_cropped = QtCore.Signal(object)
    def __init__(self, path, scale):
        super().__init__()
        # Connect graphics scene with graphics view
        self.setFixedSize(500, 500)
        self.scene = QGraphicsScene(self)
        self.setScene(self.scene)
        self.roi_scale = scale
      
        # Display image
        self.set_image(path)

    def set_image(self, path):
        pixmap = QtGui.QPixmap(path)

        if pixmap:
            pixmap = pixmap.scaledToHeight(self.roi_scale * pixmap.height())

        self.scene.clear()
        self.scene.addPixmap(pixmap)
        
        self.setAlignment(QtCore.Qt.AlignCenter)

    def wheelEvent(self, event):
        zoomInFactor = 1.05
        zoomOutFactor = 1 / zoomInFactor

        oldPos = self.mapToScene(event.pos())

        if event.angleDelta().y() > 0:
            zoomFactor = zoomInFactor
        else:
            zoomFactor = zoomOutFactor
            
        self.scale(zoomFactor, zoomFactor)

        newPos = self.mapToScene(event.pos())

        delta = newPos - oldPos
        self.translate(delta.x(), delta.y())

(wheelEvent函数归功于QGraphicsView Zooming in and out under mouse position using mouse wheel

以下是当用户单击某个按钮时生成的QGraphicsItem

    QtCore.Slot(bool)
    def create_shape(self):
        sender = self.sender()
        if sender.text().lower() == "circle":
            self.shape = ellipse_shape(0, 0, 100, 100)

        elif sender.text().lower() == "rectangle":
            self.shape = rect_shape(0, 0, 100, 100)
            
        self.shape.setZValue(1)
        self.shape.setTransformOriginPoint(50, 50)

        self.crop_pattern.scene.addItem(self.shape) # added item to the same scene, which is crop_pattern.

下面是问题所建议的GUI。(QGraphicsRectItem已调整大小)

a very sad cat

如何裁剪矩形内的像素?谢谢


Tags: pathcropimageselfeventdefscenesender
1条回答
网友
1楼 · 发布于 2024-05-15 00:14:37

一种可能的解决方案是创建一个隐藏的QGraphicsView,并使用render()方法保存图像部分。隐藏的QGraphicsView的目标不是修改现有视图,因为除了不受缩放影响外,图像还必须旋转

from PyQt5 import QtCore, QtGui, QtWidgets


def crop_rect(rect_item, scene):
    is_visible = rect_item.isVisible()

    rect_item.hide()

    hide_view = QtWidgets.QGraphicsView(scene)
    hide_view.rotate(-rect_item.rotation())

    polygon = rect_item.mapToScene(rect_item.rect())
    pixmap = QtGui.QPixmap(rect_item.rect().size().toSize())
    pixmap.fill(QtCore.Qt.transparent)
    source_rect = hide_view.mapFromScene(polygon).boundingRect()

    painter = QtGui.QPainter(pixmap)
    hide_view.render(
        painter,
        target=QtCore.QRectF(pixmap.rect()),
        source=source_rect,
    )
    painter.end()

    rect_item.setVisible(is_visible)

    return pixmap


def main():
    app = QtWidgets.QApplication([])

    scene = QtWidgets.QGraphicsScene()
    view = QtWidgets.QGraphicsView(alignment=QtCore.Qt.AlignCenter)
    view.setScene(scene)
    # emulate wheel
    view.scale(0.8, 0.8)

    # create pixmap
    pixmap = QtGui.QPixmap(500, 500)
    pixmap.fill(QtGui.QColor("green"))
    painter = QtGui.QPainter(pixmap)
    painter.setBrush(QtGui.QColor("salmon"))
    painter.drawEllipse(pixmap.rect().adjusted(100, 90, -80, -100))
    painter.end()

    pixmap_item = scene.addPixmap(pixmap)

    rect = QtCore.QRectF(0, 0, 200, 300)
    rect_item = scene.addRect(rect)
    rect_item.setPen(QtGui.QPen(QtGui.QColor("red"), 4))
    rect_item.setPos(100, 100)
    rect_item.setTransformOriginPoint(50, 50)
    rect_item.setRotation(10)

    view.resize(640, 480)
    view.show()

    qpixmap = crop_rect(rect_item, scene)
    label = QtWidgets.QLabel()
    label.setPixmap(qpixmap)
    label.show()

    app.exec_()


if __name__ == "__main__":
    main()

输入:

enter image description here

输出:

enter image description here

相关问题 更多 >

    热门问题