如何使用旋转的 QGraphicsRectItem 裁剪在场景上设置的 QPixmap?
How to crop QPixmap that is set on a Scene with a rotated QGraphicsRectItem?
我不知道如何裁剪在场景中设置的 QPixmap,同时旋转的 QGraphicsRectItem 也放置在同一场景中。
这是我的 QGraphicsScene 和 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 已调整大小)
如何裁剪矩形内的像素?谢谢!
一个可能的解决方案是创建一个隐藏的 QGraphicsView 并使用 render()
方法来保存图像部分。隐藏的QGraphicsView的objective不修改现有视图,因为图像除了不受缩放影响外还必须旋转。
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()
输入:
输出:
我不知道如何裁剪在场景中设置的 QPixmap,同时旋转的 QGraphicsRectItem 也放置在同一场景中。
这是我的 QGraphicsScene 和 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 已调整大小)
如何裁剪矩形内的像素?谢谢!
一个可能的解决方案是创建一个隐藏的 QGraphicsView 并使用 render()
方法来保存图像部分。隐藏的QGraphicsView的objective不修改现有视图,因为图像除了不受缩放影响外还必须旋转。
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()
输入:
输出: