4

私は、PyQt4 GUI 上に構築されたセンサーベースの Python アプリケーションに取り組んでいます。センサーは 16 ビットの測定値を生成しています...「ライン」あたり 256 個の 16 ビット「ピクセル」。正方形の「画像」は、256 ラインを取得することによって取得され、16 ビット数値の (256,256) Numpy 配列になります。これをグレースケール画像として表示したいだけです。センサー ループは QThread で実行され、QImage 信号を送信します。信号は、データを 32 ビット RGB イメージにパックすることでメイン GUI にレンダリングするスロットに接続します。もちろん、16 ビット グレースケール ピクセルを 32 ビット RGB 画像にパックするには、16 ビット ピクセルを 8 ビットにスケーリングする必要があり、かなりの量のダイナミック レンジが失われます。私の現在の戦略を示す MWE が提供されています (これは明らかに、私のより大きなスレッド化されたセンサーベースのアプリケーションではありません...単に顕著な部分を抽出するだけです)。

#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
Grayscale to RGB32 QPixmap tests
"""

import sys
import numpy as np
from PyQt4 import QtGui, QtCore

class PixmapTest(QtGui.QWidget):

    def __init__(self):
        super(PixmapTest, self).__init__()
        self.initUI()

    def initUI(self):      
        imglayout = QtGui.QHBoxLayout(self)

        img_16bit = np.random.randint(0,65535,size=(256,256)).astype(np.uint32)
        img_16bit_to_8bit = (img_16bit / 65535.0 * 255).astype(np.uint32)
        packed_img_array = (255 << 24 | (img_16bit_to_8bit) << 16 | (img_16bit_to_8bit) << 8 | (img_16bit_to_8bit)).flatten()
        img = QtGui.QImage(packed_img_array, 256, 256, QtGui.QImage.Format_RGB32)
        pixmap = QtGui.QPixmap(img.scaledToWidth(img.width()*2))

        imglabel = QtGui.QLabel(self)
        imglabel.setPixmap(pixmap)

        imglayout.addWidget(imglabel)
        self.setLayout(imglayout)

        self.move(300, 200)
        self.setWindowTitle('QPixmap Test')
        self.show()        

def main():

    app = QtGui.QApplication(sys.argv)
    form = PixmapTest()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main() 

具体的には、私の質問は次のとおりです。

  1. より良い方法はありますか?ソリューションは「軽量」のままでなければなりません (つまり、PyQt4 QImage/QPixmap)。遅すぎるため、Matplotlib などの重いものは使用できません。ネイティブの Python/Numpy に近いほど良いです。これは最終的には QImage クラスの制限であることは認識していますが、現在の信号/スロットの「配線」を維持できる、私が見ていなかった巧妙な解決策があることを望んでいました。

  2. 実験を通じて、最終的に処理されて QImage で np.uint32 として処理されるすべての配列を宣言する必要があることがわかりました (ただし、np.int32 も同様に機能するようです)。最後から 2 番目の配列を uint32/int32 として宣言するだけでは機能しません。理由がわかりません。

  3. 私は光度を変更したりY' = 0.2126 * R + 0.7152 * G + 0.0722 * B、他の同様の変換を行ったりしました。ここではおそらく「糞を磨く」のですが、SXに関する他の回答がこれが重要であることを示しているように見えるので、これを含めると思いました。ダイナミック レンジが失われるにもかかわらず、MWE のように R、G、B に同じ値を割り当てるだけでうまくいくようです。

以下のコメントで要求されているように、ダイナミック レンジを示すためにセンサーからのサンプル データのヒストグラムを次に示します。

実際のセンサーデータのヒストグラム

4

1 に答える 1

2

ここでは、デモ用にいくつかの関数データを使用します。

y, x = np.mgrid[-10:10:256j, -10:10:256j]
data = ((np.sin(y**2 + x**2) + 2) * 1000).astype(np.uint16)

img_8bit = (data / 256.0).astype(np.uint8) # use the high 8bit
img_8bit = ((data - data.min()) / (data.ptp() / 255.0)).astype(np.uint8) # map the data range to 0 - 255
img = QtGui.QImage(img_8bit.repeat(4), 256, 256, QtGui.QImage.Format_RGB32)

上位 8 ビットを使用すると、次のようになります。

ここに画像の説明を入力

最小値と最大値を (0, 255) にマップすると、次のようになります。

ここに画像の説明を入力

8 ビット イメージを 32 ビットに変換するには、 を呼び出すだけでimg_8bit.repeat(4)、すべてのバイトが 4 回繰り返されるため、メモリは uint32 バッファーとして表示できます。QImageby Format_RGB32notを作成したためFormat_ARGB32、最上位バイトは使用されません。

于 2013-03-28T03:56:55.590 に答える