Konvertieren Sie 16-Bit-Graustufen in QImage

Ich arbeite an einer sensorgestützten Python-Anwendung, die auf einer PyQt4-Benutzeroberfläche basiert. Der Sensor erzeugt 16-Bit-Messungen ... 256 16-Bit- "Pixel" pro "Zeile". Ein quadratisches "Bild" wird erhalten, indem 256 Zeilen erhalten werden, was zu einem (256,256) Numpy-Array von 16-Bit-Zahlen führt. Ich möchte dies einfach als Graustufenbild anzeigen. Die Sensorschleife läuft in einem QThread und gibt ein QImage-Signal aus. Das Signal wird an einen Steckplatz angeschlossen, der die Daten in der Haupt-GUI durch Packen in ein 32-Bit-RGB-Bild wiedergibt. Um die 16-Bit-Graustufenpixel in ein 32-Bit-RGB-Bild zu packen, bin ich natürlich gezwungen, die 16-Bit-Pixel auf 8-Bit zu skalieren, und ein beträchtlicher Teil des Dynamikbereichs geht verloren. Es wird eine MWE bereitgestellt, die meine aktuelle Strategie zeigt (dies ist offensichtlich nicht meine größere sensorgestützte Anwendung mit Thread ... sie extrahiert einfach die hervorstechenden Teile). Bitte beachten Sie, dass ich ein Python-Anfänger bin und mein Bestes gebe, um Schritt zu halten ...

#!/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() 

Konkret sind meine Fragen:

Gibt es einen besseren Weg? Die Lösung muss "leicht" bleiben (d. H. PyQt4 QImage / QPixmap). Ich kann Matplotlib oder etwas Schwergewichtiges nicht verwenden, da es zu langsam ist. Je näher an Python / Numpy, desto besser. Ich erkenne, dass dies letztendlich eine Einschränkung der QImage-Klasse ist, aber ich hatte gehofft, dass es eine clevere Lösung gibt, die es mir einfach nicht erlaubt, die aktuelle Signal- / Steckplatz- "Verdrahtung" beizubehalten, die ich habe.

Durch Experimente habe ich herausgefunden, dass ich alle Arrays deklarieren muss, die letztendlich verarbeitet werden, um im QImage als np.uint32 zu landen (obwohl np.int32 auch zu funktionieren scheint). Es funktioniert nicht, wenn ich das vorletzte Array einfach als uint32 / int32 deklariere. Ich verstehe nicht warum.

Ich habe mit wechselnder Leuchtkraft herumgespieltY' = 0.2126 * R + 0.7152 * G + 0.0722 * B und andere ähnliche Konvertierungen. Vermutlich "einen Trottel polieren", aber ich dachte, ich würde dies einschließen, weil andere Antworten auf SX darauf hinzuweisen scheinen, dass dies wichtig ist. Ungeachtet des Verlusts des Dynamikbereichs scheint es zu funktionieren, R, G, B einfach denselben Wert zuzuweisen wie in meinem MWE.

Wie in einem Kommentar unten angefordert, ist hier ein Histogramm einiger Beispieldaten vom Sensor, um den Dynamikbereich zu veranschaulichen:

Antworten auf die Frage(1)

Ihre Antwort auf die Frage