2016-12-19 11 views
1

イメージビューア(下記のコードを参照)を適用して、読み込んだ画像からピクセル情報を取得できるようにしました。 'イメージをロード'ボタンを使用してイメージをロードし、スクロールホイールを使用してズームイン/ズームアウトし、マウスの左クリックとドラッグを使用してパンすることができます。 'ピクセル情報入力モード'ボタンを押すと、ドラッグは無効になります(ズームすることもできます)。画像をクリックすると、ピクセル座標(整数ピクセルインデックス)とピクセルのグレースケール値が得られます。回転画像の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_()) 

答えて

0

あなたがシーンをマップする必要がありますが、アイテムの座標は座標:

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

は、以前のように(あなたが私の最後の質問に答え)あなたは私のためにそれを修正しました。興味のないものは、この種のもの(pyqt4画像の操作と描画/特にアニメーション)を学ぶための良い本やチュートリアルを知っていますか?私が知らないことがたくさんあるので、私が暗闇の中で捜しているように感じます。私はいつもより簡単に例を学ぶことができます。とにかくありがとう。 –

+0

@AndrewBirch。私は個人的な推薦を持っていません。 [PyQt Wiki](http://wiki.python.org/moin/PyQt)にはいくつかの便利なリンクがありますが、いくつかはかなり古いかもしれないことに注意してください。 [PyQt4 examples](http://github.com/Werkov/PyQt4/tree/master/examples/graphicsview)には、(Qt Docsのものに基づく)いくつかのグラフィックデモもあります。 – ekhumoro