Конвертировать 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.
Как указано в комментарии ниже, вот гистограмма некоторых образцов данных с датчика, чтобы проиллюстрировать динамический диапазон: