Конвертировать 16-битную шкалу серого в QImage

Я работаю над сенсорным Python-приложением, построенным на PyQt4 GUI. Датчик генерирует 16-битные измерения ... 256 16-битных «пикселей» на «строку». Квадратное «изображение» получается путем получения 256 строк, в результате чего получается массив (256 256) Numpy из 16-битных чисел. Я просто хочу отобразить это как изображение в градациях серого. Цикл датчика работает в QThread и излучает сигнал QImage. Сигнал подключается к слоту, который отображает данные в основном графическом интерфейсе, упаковывая их в 32-разрядное изображение RGB. Конечно, чтобы упаковать 16-битные пиксели в градациях серого в 32-битное RGB-изображение, я вынужден масштабировать 16-битные пиксели до 8-битных, и значительная часть динамического диапазона теряется. Предоставляется MWE, который показывает мою текущую стратегию (это, очевидно, не мое более крупное приложение на основе датчиков с резьбой ... оно просто выделяет существенные части). Обратите внимание, что я новичок в Python, и я делаю все возможное, чтобы не отставать ...

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

В частности, мои вопросы:

Есть ли способ лучше? Решение должно оставаться «легковесным» (то есть PyQt4 QImage / QPixmap). Я не могу использовать Matplotlib или что-нибудь тяжеловесное, потому что это слишком медленно. Чем ближе к родному Python / Numpy, тем лучше. Я понимаю, что в конечном счете это ограничение класса QImage, но я надеялся, что было найдено умное решение, которого я просто не вижу, которое позволило бы мне сохранить текущую проводку сигнала / слота, которая у меня есть.

В результате экспериментов я обнаружил, что должен объявить все массивы, которые в конечном итоге обрабатываются, чтобы в конечном итоге попасть в QImage, как np.uint32 (хотя np.int32, похоже, также работает). Это не сработает, если я просто объявлю предпоследний массив как uint32 / int32. Я не понимаю почему.

Я играл с изменением яркости сY' = 0.2126 * R + 0.7152 * G + 0.0722 * B и другие подобные преобразования. Вероятно, «полировка какашки» здесь, но я подумал, что включу это, потому что другие ответы на SX, кажется, указывают, что это важно. Несмотря на потерю динамического диапазона, кажется, что можно просто присвоить R, G, B то же значение, что и в моем MWE.

Как указано в комментарии ниже, вот гистограмма некоторых образцов данных с датчика, чтобы проиллюстрировать динамический диапазон:

Ответы на вопрос(1)

Ваш ответ на вопрос