pyqt4旋转图像上的像素信息



我已经调整了一个图像查看器(请参见下面的代码),以便我从加载的图像中获取像素信息。您可以使用"加载图像"按钮加载图像,然后可以使用滚轮放大和缩放,然后使用鼠标左键单击并拖动锅。按下按钮"输入像素信息模式"时,禁用拖动(您仍然可以缩放),然后单击图像将提供像素坐标(整数像素索引)和像素的灰度值。

问题在于,如果您旋转图像,通过按"旋转图像"按钮,使用像素信息按钮不再提供正确的像素信息。我认为Maptoscene方法不是在旋转的图像上使用的正确方法,而是找不到其他方法。我尝试了各种事情,例如在旋转的像素上使用toimage(),然后用它替换原始图像,但似乎无效。解决这个问题的最佳方法是什么?

代码:

from PyQt4 import QtCore, QtGui
class PhotoViewer(QtGui.QGraphicsView):
    photoClicked = QtCore.pyqtSignal(QtCore.QPoint)
    def __init__(self, parent):
        super(PhotoViewer, self).__init__(parent)
        self._zoom = 0
        self._empty = True
        self._scene = QtGui.QGraphicsScene(self)
        self._photo = QtGui.QGraphicsPixmapItem()
        self._scene.addItem(self._photo)
        self.setScene(self._scene)
        self.setTransformationAnchor(QtGui.QGraphicsView.AnchorUnderMouse)
        self.setResizeAnchor(QtGui.QGraphicsView.AnchorUnderMouse)
        self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        self.setBackgroundBrush(QtGui.QBrush(QtGui.QColor(30, 30, 30)))
        self.setFrameShape(QtGui.QFrame.NoFrame)
    def fitInView(self):
        rect = QtCore.QRectF(self._photo.pixmap().rect())
        if not rect.isNull():
            unity = self.transform().mapRect(QtCore.QRectF(0, 0, 1, 1))
            self.scale(1 / unity.width(), 1 / unity.height())
            viewrect = self.viewport().rect()
            scenerect = self.transform().mapRect(rect)
            factor = min(viewrect.width() / scenerect.width(),
                         viewrect.height() / scenerect.height())
            self.scale(factor, factor)
            self.centerOn(rect.center())
            self._zoom = 0
    def hasPhoto(self):
        return not self._empty
    def toggleDragMode(self):
        if self.dragMode() == QtGui.QGraphicsView.ScrollHandDrag:
            self.setDragMode(QtGui.QGraphicsView.NoDrag)
        elif self.hasPhoto():
            self.setDragMode(QtGui.QGraphicsView.ScrollHandDrag)
    def setPhoto(self, pixmap=None):
        self._zoom = 0
        if pixmap and not pixmap.isNull():
            self._empty = False
            self.setDragMode(QtGui.QGraphicsView.ScrollHandDrag)
            self._photo.setPixmap(pixmap)
            self.fitInView()
        else:
            self._empty = True
            self.setDragMode(QtGui.QGraphicsView.NoDrag)
            self._photo.setPixmap(QtGui.QPixmap())
    def wheelEvent(self, event):
        if not self._photo.pixmap().isNull():
            if event.delta() > 0:
                factor = 1.25
                self._zoom += 1
            else:
                factor = 0.8
                self._zoom -= 1
            if self._zoom > 0:
                self.scale(factor, factor)
            elif self._zoom == 0:
                self.fitInView()
            else:
                self._zoom = 0
    def mousePressEvent(self, event):
        if (self.hasPhoto() and
            self.dragMode() == QtGui.QGraphicsView.NoDrag and
            self._photo.isUnderMouse()):
            self.photoClicked.emit(QtCore.QPoint(event.pos()))
        super(PhotoViewer, self).mousePressEvent(event)
class Window(QtGui.QWidget):
    def __init__(self):
        super(Window, self).__init__()
        self.viewer = PhotoViewer(self)
        # 'Load image' button
        self.btnLoad = QtGui.QToolButton(self)
        self.btnLoad.setText('Load image')
        self.btnLoad.clicked.connect(self.loadImage)
        # Button to change from drag/pan to getting pixel info
        self.btnPixInfo = QtGui.QToolButton(self)
        self.btnPixInfo.setText('Enter pixel info mode')
        self.btnPixInfo.clicked.connect(self.pixInfo)        
        self.editPixInfo = QtGui.QLineEdit(self)
        self.editPixInfo.setReadOnly(True)
        # Button to rotate image by 10 degrees
        self.btnRotate = QtGui.QToolButton(self)
        self.btnRotate.setText('Rotate image')
        self.btnRotate.clicked.connect(self.rotateImage)
        self.viewer.photoClicked.connect(self.photoClicked)
        # Arrange layout
        VBlayout = QtGui.QVBoxLayout(self)
        VBlayout.addWidget(self.viewer)
        HBlayout = QtGui.QHBoxLayout()
        HBlayout.setAlignment(QtCore.Qt.AlignLeft)
        HBlayout.addWidget(self.btnLoad)
        HBlayout.addWidget(self.btnRotate)
        HBlayout.addWidget(self.btnPixInfo)
        HBlayout.addWidget(self.editPixInfo)
        VBlayout.addLayout(HBlayout)
    def loadImage(self):
        self.viewer.setPhoto(QtGui.QPixmap('pic.jpg'))
    def pixInfo(self):
        self.viewer.toggleDragMode()
    def rotateImage(self):
        self.viewer._photo.setRotation(10)
    def photoClicked(self, pos):
        pos = self.viewer.mapToScene(pos)
        # p.s. I realise the following lines are probably a very convoluted way of getting
        # a grayscale value from RGB, but I couldn't make it work any other way I tried
        rot_image = self.viewer._photo.pixmap().toImage().pixel(pos.x(), pos.y())
        colour = QtGui.QColor.fromRgb(rot_image)
        gsval = QtGui.qGray(colour.red(), colour.green(), colour.blue())
        self.editPixInfo.setText('X:%d, Y:%d Grayscale: %d' % (pos.x(), pos.y(), gsval))
if __name__ == '__main__':
    import sys
    app = QtGui.QApplication(sys.argv)
    window = Window()
    window.setGeometry(500, 300, 800, 600)
    window.show()
    sys.exit(app.exec_())

您需要将场景坐标映射到项目坐标:

pos = self.viewer._photo.mapFromScene(self.viewer.mapToScene(pos))

最新更新