2016-06-29 12 views
3

私はPyQt4で単純なビューアを使用していますが、numpy配列(8ビットグレースケール)からQImageを表示するときに奇妙な動作があります。メモリの順序を更新する必要がある(つまり、異なるストライドのビューではない)場合でも、転置された配列からQImageを作成しようとすると、何か変わっているように思えます。numpy配列をQImageに変換するときのメモリの順序の動作の問題

以下

ビューアの多額のカットダウン版です:

import numpy as np 
from PyQt4 import QtGui 

class SimpleViewer(QtGui.QMainWindow): 

    def __init__(self, data, parent=None): 
     super(SimpleViewer, self).__init__(parent=parent) 

     hgt, wid = data.shape 

     dmin = data.min() 
     dmax = data.max() 
     bdata = ((data - dmin)/(dmax - dmin)*255).astype(np.uint8) 

     img = QtGui.QImage(bdata, wid, hgt, QtGui.QImage.Format_Indexed8) 

     self.scene = QtGui.QGraphicsScene(0, 0, wid, hgt) 
     self.px = self.scene.addPixmap(QtGui.QPixmap.fromImage(img)) 

     self.view = QtGui.QGraphicsView(self.scene) 
     self.setCentralWidget(self.view) 


if __name__ == "__main__": 

    app = QtGui.QApplication.instance() 
    if app is None: 
     app = QtGui.QApplication(['python']) 

    xx, yy = np.meshgrid(np.arange(-100,100), np.arange(350)) 
    zz = xx * np.cos(yy/350.*6*np.pi) 

    viewer = SimpleViewer(zz) 
    viewer.show() 
    app.exec_() 

、これは結構です、このような何か、生成されるよう-:私は、しかし

vertical-is-okay

を最初の次元を「x」、2番目の次元を「y」とするために、実際の画像を転置する必要があります(原点が左下ですが、ここでは範囲外です)。

hgt, wid = data.shapewid, hgt = data.shapeに変更して何もしない(間違っている)場合は、次のようになります。 QImageはメモリを読み込むだけなので意味があります。

bad-memory-order

しかし、bdata.T.copy()代わりのbdataにおけるI パスならば、私は配列を転置し、メモリコピー操作によって再注文されることを期待しています。しかし、私が得ることはこれです:

problem

それはので近いが、何らかの理由のためだけの髪でオフです。また、大きさがちょうど整数倍(たとえば200x100)であれば大丈夫だと気付きました。何が起こっている? 私は本当に本当に馬鹿なことを見逃しましたか?

これはPyQtの問題かnumpyの問題なのかどうかはわかりません...転置された配列はmatplotlibでうまくプロットされますが、matplotlibはストライディングを処理します。

私はPython 2.7とPython 3.5で同じ動作をします。 PyQt4バージョンはQtバージョン4.8.7を使用して4.11.4です。ナンシーバージョンは1.10.1です。

答えて

1

この問題は、QImageの作成に起因しています。

img = QtGui.QImage(bdata, wid, hgt, QtGui.QImage.Format_Indexed8) 

使用しているコンストラクタの署名のためのdocumentation

言う...データは、32ビットの整列されなければならず、画像データのそれぞれの走査線は、32ビットでなければなりません整列した。

それは32ビット整列されるように、あなたは(xx, yy = np.meshgrid(np.arange(-128,128), np.arange(384))を使用して、たとえば)あなたの配列の次元を変更する場合は、あなたのコードが正しく動作します。

行あたり32バイトの倍数を必要とせずに、この問題を修正するには、あなたがQImageのために少しdifferent constructorを使用したい:

あなたのケースでは
QImage(data, width, height, bytesPerLine, format) 

、これは単純です:

img = QtGui.QImage(bdata, wid, hgt, wid, QtGui.QImage.Format_Indexed8) 

であり、各ピクセルは1バイトの情報を含むからである。

+1

Whoa。何らかの理由で私は "データは32ビットで整列されていなければなりません"で読み込みを停止していなければなりませんし、 "と**それぞれの走査線**も32ビットで整列しなければなりません"。 *慎重に*ドキュメントを読むことの教訓 – Ajean

関連する問題